Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7019 Articles
article-image-polygon-modeling-handgun-using-blender-3d-249-part-1
Packt
30 Nov 2009
3 min read
Save for later

Polygon Modeling of a Handgun using Blender 3D 2.49: Part 1

Packt
30 Nov 2009
3 min read
With the base model created, we will be able to analyze the shape of our model and evaluate the next steps of the project. We can even decide to make changes to the project because new ideas may appear when we see the object in 3D rather than in 2D. Starting with a background image The first step to start the modeling is to add the reference image as the background of the Blender 3D view. To do that, we can go to the View menu in the 3D view and choose Background Image. The background image in Blender appears only when we are at an orthogonal or Camera view. The background image is a simple black and white drawing of the weapon, but it will be a great reference for modeling. Before we go any further, it's important to point out a few things about the Background Image menu. We can make some adjustments to the image if it doesn't fit our Blender view: Use: With this button turned on, we will use the image as a background. If you want to hide the image, just turn it off and the image will disappear. Blend: The blend slider will control the transparency of the image. If you feel that the image is actually blocking your view of the whole model, making it a bit transparent may help. Size: As the name says, we can control the scale of the image. X and Y offset: With this option, we will be able to move the image in the X or Y axis to place it in a specific location. After clicking on the Use button, just hit the load button and choose the image to be used as a reference. Since you don't have the image used in this example, visit the Packt web site and download the project files from Support. If you've never used a reference image in Blender, it is important to note that the reference images appear only in 3D view when we are using the orthographic view or the camera view mode. It works only in the top, right, left, front, and other orthographic views. If you hit 5 and change the view to perspective, the image will disappear. By using the middle mouse button or the scroll to rotate the view, the image disappears. However, it's still there and we can see the image again by changing the view to an orthogonal or camera view. Make the image more transparent by using the Blend control. It will help in focusing on the model instead of the image. A value of 0.25 will be enough to help in the modeling without causing confusion.
Read more
  • 0
  • 0
  • 3319

article-image-tabs-jquery-ui-17
Packt
30 Nov 2009
7 min read
Save for later

Tabs in jQuery UI 1.7

Packt
30 Nov 2009
7 min read
The UI tabs widget is used to toggle visibility across a set of different elements, each element containing content that can be accessed by clicking on its heading which appears as an individual tab. The tabs are structured so that they line up next to each other, whereas the content sections are layered on top of each other, with only the top one visible. Clicking a tab will highlight the tab and bring its associated content panel to the top of the stack. Only one content panel can be open at a time. The following screenshot shows the different components of a set of UI tabs: A basic tab implementation The structure of the underlying HTML elements, on which tabs are based, is rigid and widgets require a certain number of elements for them to work. The tabs must be created from a list element (ordered or unordered) and each list item must contain an <a> element. Each link will need to have a corresponding element with a specified id that it is associated with the link's href attribute. We'll clarify the exact structure of these elements after our first example. In a new file in your text editor, create the following page: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html lang="en"> <head> <link rel="stylesheet" type="text/css" href="development-bundle/themes/smoothness/ui.all.css"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>jQuery UI Tabs Example 1</title> </head> <body> <div id="myTabs"> <ul> <li><a href="#a">Tab 1</a></li> <li><a href="#b">Tab 2</a></li> </ul> <div id="a">This is the content panel linked to the first tab,  it is shown by default.</div> <div id="b">This content is linked to the second tab and will be shown when its tab is clicked.</div> </div> <script type="text/javascript" src="development-bundle/jquery-1.3.2.js"></script> <script type="text/javascript" src="development-bundle/ui/ui.core.js"></script> <script type="text/javascript" src="development-bundle/ui/ui.tabs.js"></script> <script type="text/javascript"> $(function(){ $("#myTabs").tabs(); }); </script> </body></html> Save the code as tabs1.html in your jqueryui working folder. Let's review what was used. The following script and CSS resources are needed for the default tab widget instantiation: ui.all.css jquery-1.3.2.js ui.core.js ui.tabs.js A tab widget consists of several standard HTML elements arranged in a specific manner (these can be either hardcoded into the page, or added dynamically, or can be a mixture of both depending on the requirements of your implementation). An outer container element, which the tabs method is called on A list element( <ul> or <ol>) An <a> element for each tab An element for the content of each tab The first two elements within the outer container make the clickable tab headings, which are used to show the content section that is associated with the tab. Each tab should include a list item containing the link. The href attribute of the link should be set as a fragment identifier, prefixed with #. It should match the id attribute of the element that forms the content section, with which it is associated. The content sections of each tab are created by the elements. The id attribute is required and will be targeted by its corresponding element. We've used elements in this example as the content panels for each tab, but other elements, such as elements can also be used. The elements discussed so far, along with their required attributes, are the minimum that are required from the underlying markup.We link to several <script> resources from the library at the bottom of the <body> before its closing tag. Loading scripts last, after stylesheets and page elements is a proven technique for improving performance. After linking first to jQuery, we link to the ui.core.js file that is required by all components (except the effects, which have their own core file). We then link to the component's source file that in this case is ui.tabs.js.After the three required script files from the library, we can turn to our custom < script> element in which we add the code that creates the tabs. We simply use the $(function(){}); shortcut to execute our code when the document is ready. We then call the tabs() widget method on the jQuery object, representing our tabs container element (the <ul> with an id of myTabs).When we run this file in a browser, we should see the tabs as they appeared in the first screenshot of this article(without the annotations of course). Tab CSS framework classes Using Firebug for Firefox (or another generic DOM explorer) we can see that a variety of class names are added to the different underlying HTML elements that the tabs widget is created from, as shown in the following screenshot: Let's review these briefly. To the outer container < div> the following class names are added: Class name Purpose ui-tabs Allows tab-specific structural CSS to be applied. ui-widget Sets generic font styles that are inherited by nested elements. ui-widget-content Provides theme-specific styles. ui-corner-all Applies rounded corners to container. The first element within the container is the < ul> element. This element receives the following class names: Class name Purpose ui-tabs-nav Allows tab-specific structural CSS to be applied. ui-helper-reset Neutralizes browser-specific styles applied to <ul> elements. ui-helper-clearfix Applies the clear-fix as this element has children that are floated. ui-widget-header Provides theme-specific styles. ui-corner-all Applies rounded corners. The individual < li> elements are given the following class names: Class name Purpose ui-state-default Applies theme-specific styles. ui-corner-top Applies rounded corners to the top edges of the elements. ui-tabs-selected This is only applied to the active tab. On page load of the default implementation this will be the first tab. Selecting another tab will remove this class from the currently selected tab and apply it to the new tab. ui-state-active Applies theme-specific styles to the currently selected tab. This class name will be added to the tab that is currently selected, just like the previous class name. The reason there are two class names is that ui-tabs-selected provides the functional CSS, while ui-state-active provides the visual, decorative styles. The < a> elements within each < li> are not given any class names, but they still have both structural and theme-specific styles applied to them by the framework. Finally, the elements that hold each tab's content are given the following class names: Class name Purpose ui-tabs-panel Applies structural CSS to the content panels ui-widget-content Applies theme-specific styles ui-corner-bottom Applied rounded corners to the bottom edges of the content panels All of these classes are added to the underlying elements automatically by the library, we don't need to manually add them when coding the page. As these tables illustrate, the CSS framework supplies the complete set of both structural CSS styles that control how the tabs function and theme-specific styles that control how the tabs appear, but not how they function. We can easily see which selectors we'll need to override if we wish to tweak the appearance of the widget, which is what we'll do in the following section.
Read more
  • 0
  • 0
  • 4260

article-image-report-components-nav-2009-part-3
Packt
30 Nov 2009
9 min read
Save for later

Report components in NAV 2009: Part 3

Packt
30 Nov 2009
9 min read
Make the report changes Having reviewed the VS RD in some detail, let's begin the task of making the changes we defined earlier. First, we will add the ICAN Campaign column to each data line. In the VS RD showing the original VS RD layout for Report 50002, right-click on the top line of the last data column. Ignore the three very small columns at the right end of the data line. These are Hidden Fields which we will explain later. You will see the following: Then choose the option to Insert Column to the Right. That will (surprise!) insert another column—to the right. Now expand the Data Sources, so that you can access the fields we added earlier to the Classic Sections Designer. Those fields are Gift_Ledger__ICAN_Campaign_ (data) and Gift_Ledger_ICAN__Campaign_Caption (header). Grab, drag-and-drop the data field into the new column, third row (table detail row). Grab, drag-and-drop the caption field into the new column, top row (table header row). Save, save, compile, and test. Depending on your data, the new column on your report may look similar to the following: If so, then you need to change the properties of the data field so that the full data contents can be displayed. Return to the VS RD, highlight the field containing Gift_Ledger__ICAN_Campaign_. Confirm that the property Layout | CanGrow is False, rather than True. This will keep the data field from wrapping to the next line when it exceeds the width of the available space. Instead, it will be truncated when it exceeds the available space (obviously, you may prefer different behavior in different situations). The other change required in this case is to revise the Size | Width property to a larger number. After those changes are made, the next test gives the following results for a sample of the ICAN Campaign column of data. Our second change is to add a Gift count to each total line. As all we need to do in this case is to count the detail lines printed, we should check if we can use a function which is built into the VS RD. We can count the lines if we can count the instances of one of the data elements, such as the Donor ID. Let's go exploring to see if we can find the tools and the technique to accomplish our goal. We will start our exploration by investigating how a report transformation generated total has been created. Right click on the textbox containing the Estimated Value total (shown in the following screenshot): Then click on the Properties option. As shown in the following screenshot, the Value field contains =Sum(Fields!Gift_Ledger__Estimated_Value_.Value), which is not listed in the Data Sources window. But, as Gift_Ledger__Estimated_Value_.Value is one of the items in the Data Sources window, it seems reasonable to assume that =Sum is a VS RD function and that we might find a Count function if we keep looking. As we've determined that the Value field contains an expression, let's go back to the text box, right-click again, and choose Expression…. That will open the following form, where we can see the tools that are used to construct an expression like the one that sums the total gift amounts. Our task now is to find a count function (or equivalent). We can continue our exploring, but let's move to a blank instance of the Edit Expression form, so we don't accidentally change the existing, working expression. Close the Edit Expression form for the Gift_Ledger_Estimated_Value and open an Edit Expression form for the Textbox in the same row, but in the column containing the Donor ID field (that is, the next column to the right in our example). With that empty Edit Expression form open, if we can find a count function, perhaps we can build an expression to give us our desired result. Using the very practical "peek and poke" method (that is, clicking on various fields to see what we can find), we uncover the following. There's the Count function we were hoping to find (along with quite a few other functions we can use in future situations). Double-click on the Count function or click on the Paste button, and the Count function will be pasted into the workspace above. Looking at the expression for the Estimated Value total, we can guess that now we want to identify what to count, in this case the Donor ID instance. If we click on the left pane, Fields (DataSet_Result), then we will see a list of all of the available data fields. Included in those is Gift_Ledger__Donor_ID, as shown in the following screenshot. The wavy line under the Count function in the workspace simply indicates that we don't have a complete operable expression defined yet. Double-click on the field Gift_Ledger__Donor_ID (or highlight and click on Paste). The field name will appear in the Edit Expression workspace after the Count function. You will likely still see the wavy underline, indicating you're still not quite done. If you look at the expression for the Sum, you will see that it begins with an equals sign (=) and the field name is enclosed in parentheses. Let's make those additional changes. The final expression should look like the following: Once you have that, you can close the Edit Expression form. You may notice at this point that the font for the new Count expression is different from (for example, larger) the other fields. If you want all of the fonts to be the same, obviously, you will need to change the font property of the new field to match the old fields. Once that is done, exit and save the VS RD layout changes, save and compile the report, and test it. You should now see a count of the gifts for each donor on the group total lines, looking something like the following: If this were to be a production report to be given to a client, it is likely that we would work on the layout some more, perhaps more clearly identifying the gift count total. But we certainly have achieved our original goal of obtaining and printing the count. Some interactive report capabilities Our third change is to add some interactive capabilities to our report. We want the report to display in either a summary or detail format, and we want to allow sorting the detail into different sequences. Return again to the VS RD layout, focused on Report 50002. Let's allow the users to sort on the gift amount or on the campaign. And, to provide full flexibility, let's also allow sorting on the gift date. Right-click on the heading for the column on which we wish to control the sort, and display the properties form—let's start with gift amount. Click on the Interactive Sort tab. Click on the option Add an interactive sort action to this textbox. Then choose the field on which the sort should occur. In this case, that's the =Fields!Gift_Ledger__Estimated Value_.Value: Click on OK, and then perform a similar set of actions on the layout table column for the ICAN Campaign and Date fields. Once you've done that, exit VS RD, saving the changes, then save, compile and test the changed report design. You should see a report, the top of which looks something like the following. There will be pairs of up/down arrowheads that can be used for sort control. The last one of them used will show just the option not invoked (that is, only an up or a down arrowhead, not both). The work required to implement our other interactive capability, Expand/Collapse Detail, is very similar to what we just did for the interactive sorting. Once again return to the VS RD for the layout of Report 50002. This time click on one of the layout table fields, so that the Table Element icons are visible. Then right click on the Table Detail icon. Choose Properties, this time you will not get a Properties form, but will use the VS Property window (which defaults to the lower right panel of the layout screen, but is movable anywhere within the VS RD frame). Find the Visibility property group, expand it so that you can see the Toggle Item property. Click on the selection caret at the right end of the property space and choose the fi eld with which you would like to control the Expand/Collapse option. The Gift_Ledger_DateCaption field is a good choice, because it is the topmost left field, so the Expand/Collapse option will be quite visible to the user there. After you exit, save, compile, and run the report. You will see the Expand/Collapse icon in the top left of the report, as shown in the following screenshot, where the detail data is expanded (that is visible): In the next screenshot, the detail data is collapsed (that is, hidden): As you can see, the Expand/Collapse icon will be either plus or minus, depending on whether the related data is currently visible (plus) or hidden (minus). You should also experiment with using this feature to make columns on a report be visible or hidden, at the user's option. Page Header fields Fields that are displayed in the Page Header or Page Footer sections of the VS RD cannot contain variable data. As a result, a couple of different approaches are used to be able to display "normal" report headings that do contain variable data. One approach is the use of Hidden Fields. In the following screenshot at the point of the cursor arrow, three Hidden Fields are present, which were all created as part of the automatic transformation process of Create Layout Suggestion. These fields are essentially similar to other VS RD data fields, except they are set to not be visible, and are only used to manage data rather than display it directly. Hidden Fields that are created by the Report Transformation process are set to red by default (and by convention). Hidden Fields that are created in the C/SIDE RD to hold special data or logic should be set to yellow (see the Help titled "How to: Add and Identify Hidden Fields"). This color coding makes the hidden fields' purpose easier to identify for software maintenance.
Read more
  • 0
  • 0
  • 1464

article-image-drag-and-drop-yui-part-3
Packt
30 Nov 2009
6 min read
Save for later

Drag-and-Drop with the YUI: Part-3

Packt
30 Nov 2009
6 min read
Visual Selection with the Slider Control So far in this chapter we've focused on the functionality provided by the Drag-and-Drop utility. Let's shift our focus back to the interface controls section of the library and look at one of the components which is related very closely to drag-and-drop—the Slider control. A slider can be defined using a very minimal set of HTML. All you need are two elements: the slider background and the slider thumb, with the thumb appearing as a child of the background element: <div id="slider_bg" title="the slider background"><div id="slider_thumb" title="the slider thumb"><img src="images/slider_thumb.gif"></div></div> These elements go together to form the basic Slider control, as shown in below: The Slider control works as a specific implementation of DragDrop in that the slider thumb can be dragged along the slider background either vertically or horizontally. The DragDrop classes are extended to provide additional properties, methods, and events specific to Slider. One of the main concepts differentiating Slider from DragDrop is that with a basic slider, the slider thumb is constrained to just one axis of motion, either X or Y depending on whether the Slider is horizontal or vertical respectively. The Slider is another control that can be animated by including a reference to the Animation control in the head of the page. Including this means that when any part of the slider background is clicked on, the slider thumb will gracefully slide to that point of the background rather than just moving there instantly. The Constructor and Factory Methods The constructor for the slider control is always called in conjunction with one of the three factory methods, depending on which type of slider you want to display. To generate a horizontal slider the YAHOO.widget.Slider.getHorizSlider is called, with the appropriate arguments. To generate a vertical slider, on the other hand, the YAHOO.widget.Slider.getVertSlider would instead be used. There is also another type of slider that can be created—the YAHOO.widget.Slider.getSliderRegion constructor and factory method combination creates a two-dimensional slider, the thumb of which can be moved both vertically and horizontally. There are a range of arguments used with the different types of slider constructor. The first two arguments are the same for all of them, with the first argument corresponding to the id of the background HTML element and the second corresponding to the id of the thumb element. The type of slider you are creating denotes what the next two (or four when using the SliderRegion) arguments relate to. With the horizontal slider or region slider the third argument is the number of pixels that the thumb element can move left, but with the horizontal slider it is the number of pixels it can move up. The fourth argument is either the number of pixels which the thumb can move right, or the number of pixels it can move down. When using the region slider, the fifth and sixth arguments are the number of pixels the thumb element can move up and down, so with this type of slider all four directions must be specified. Alternatively, with either the horizontal or vertical sliders, only two directions need to be accounted for. The final argument (either argument number five for the horizontal or vertical sliders, or argument number seven for the region slider) is optional and refers to the number of pixels between each tick, also known as the tick size. This is optional because you may not use ticks in your slider, therefore making the Slider control analogue rather than digital. Class of Two There are just two classes that make up the Slider control—the YAHOO.widget.Slider class is a subclass of the YAHOO.util.DragDrop class and inherits a whole bunch of its most powerful properties and methods, as well as defining a load more of its own natively. The YAHOO.widget.SliderThumb class is a subclass of the YAHOO.util.DD class and inherits properties and methods from this class (as well as defining a few of its own natively). Some of the native properties defined by the Slider class and available for you to use include: animate—a boolean indicating whether the slider thumb should animate. Defaults to true if the Animation utility is included, false if not animationDuration—an integer specifying the duration of the animation in seconds. The default is 0.2 backgroundEnabled—a boolean indicating whether the slider thumb should automatically move to the part of the background that is selected when clicked. Defaults to true enableKeys—another boolean which enables the home, end and arrow keys on the visitors keyboard to control the slider. Defaults to true, although the slider control must be clicked once with the mouse before this will work keyIncrement—an integer specifying the number of pixels the slider thumb will move when an arrow key is pressed. Defaults to 25 pixels A large number of native methods are also defined in the class, but a good deal of them are used internally by the slider control and will therefore never need to be called directly by you in your own code. There are a few of them that you may need at some point however, including: .getThumb()—returns a reference to the slider thumb .getValue()—returns an integer determining the number of pixels the slider thumb has moved from the start position .getXValue()—an integer representing the number of pixels the slider has moved along the X axis from the start position .getYValue()—an integer representing the number of pixels the slider has moved along the Y axis from the start position .onAvailable()—executed when the slider becomes available in the DOM .setRegionValue() and .setValue()—allow you to programmatically set the value of the region slider's thumb More often than not, you'll find the custom events defined by the Slider control to be most beneficial to you in your implementations. You can capture the slider thumb being moved using the change event, or detect the beginning or end of a slider interaction by subscribing to slideStart or slideEnd respectively. The YAHOO.widget.SliderThumb class is a subclass of the DD class; this is a much smaller class than the one that we have just looked at and all of the properties are private, meaning that you need not take much notice of them. The available methods are similar to those defined by the Slider class, and once again, these are not something that you need to concern yourself with in most basic implementations of the control.
Read more
  • 0
  • 0
  • 2502

article-image-linux-e-mail-using-spamassassin
Packt
30 Nov 2009
8 min read
Save for later

Linux E-mail: Using SpamAssassin

Packt
30 Nov 2009
8 min read
Now that SpamAssassin is installed, we need to configure the system to use it. SpamAssassin can be used in many ways. It can be integrated into the MTA for maximum performance; it can run as a daemon or a simple script to avoid complexity; it can use separate settings for each user or use a single set of settings for all users; and it can be used for all accounts or just for the chosen ones. In this article, we will discuss using SpamAssassin in three ways. The first method is with Procmail. This is the simplest method to configure and is suitable for low-volume sites, for example, less than 10,000 e-mails a day. The second method is to use SpamAssassin as a daemon. This is more efficient, and can still be used with Procmail, if desired. The third method is to integrate SpamAssassin with a content filter such as amavisd. This offers performance advantages, but occasionally the content filter does not work with the latest release of SpamAssassin. Problems, if any, are usually resolved quickly. To help you get the most out of SpamAssassin, Packt Publishing has published SpamAssassin: A practical guide to integration and configuration, (ISBN 1-904811-12-4) by Alistair McDonald. Using SpamAssassin with Procmail Before we configure the system to use SpamAssassin, let's consider what SpamAssassin does. SpamAssassin is not an e-mail filter. A filter is something that changes the destination of an e-mail. SpamAssassin adds e-mail headers to an e-mail message to indicate if it is spam or not. Consider an e-mail with headers like this: Return-Path: <user@domain.com>X-Original-To: jdoe@localhostDelivered-To: jdoe@host.domain.comReceived: from localhost (localhost [127.0.0.1])by domain.com (Postfix) with ESMTP id 52A2CF2948for <jdoe@localhost>; Thu, 11 Nov 2004 03:39:42 +0000 (GMT)Received: from pop.ntlworld.com [62.253.162.50]by localhost with POP3 (fetchmail-6.2.5)for jdoe@localhost (single-drop); Thu, 11 Nov 2004 03:39:42 +0000(GMT)Message-ID: <D8F7B41C.4DDAFE7@anotherdomain.com>Date: Wed, 10 Nov 2004 17:54:14 -0800From: "stephen mellors" <gregory@anotherdomain.com>User-Agent: MIME-tools 5.503 (Entity 5.501)X-Accept-Language: en-usMIME-Version: 1.0To: "Jane Doe" <jdoe@domain.com>Subject: nearest pharmacy onlineContent-Type: text/plain;charset="us-ascii"Content-Transfer-Encoding: 7bit SpamAssassin will add header lines. X-Spam-Flag: YESX-Spam-Checker-Version: SpamAssassin 3.1.0-r54722 (2004-10-13) onhost.domain.comX-Spam-Level: *****X-Spam-Status: Yes, score=5.8 required=5.0 tests=BAYES_05,HTML_00_10,HTML_MESSAGE,MPART_ALT_DIFF autolearn=noversion=3.1.0-r54722 SpamAssassin doesn't change the destination of the e-mail, all it does is add headers that enable something else to change the destination of the e-mail. The best indication that an e-mail is spam is the X-Spam-Flag. If this is YES, SpamAssassin considers the mail to be spam and it can be filtered by Procmail. SpamAssassin also assigns a score to each e-mail—the higher the score, the more likely that the e-mail is spam. The threshold that determines if an e-mail is spam can be configured on a system-wide or per-user basis. The default of 5.0 is a sensible default if you are using an unmodified installation of SpamAssassin without any custom rulesets. Global procmailrc file Let's suppose that we want to check all incoming e-mail for spam using SpamAssassin. Commands in the /etc/procmailrc file are run for all users, so executing SpamAssassin here is ideal. The following simple recipe will run SpamAssassin for all users when placed in /etc/procmailrc: :0fw| /usr/bin/spamassassin To place all spam in an individual spam folder, ensure that the global/etc/procmailrc file has a line specifying a default destination. For example: DEFAULT=$HOME/.maildir/ If not, then add a line specifying DEFAULT. To filter spam into a folder, add a recipe similar to the following: * ^X-Spam-Flag: Yes.SPAM/new This assumes that each user has a folder called SPAM already configured. To place all the spam in a single, central folder, use an absolute path to the destination in the recipe: * ^X-Spam-Flag: Yes/var/spool/poss_spam This will place all spam in a single folder, which can be reviewed by the system administrator. As times, regular e-mail may occasionally be wrongly detected as spam, the folder should not be world-readable, which leads to a more generalized statement. SpamAssassin will be run under the system account used by Postfix. This means that the Bayesian database and the auto-whitelists and blacklists will be shared by all users. From a security point of view, it's important that the various databases that SpamAssassin creates are not world-writable. SpamAssassin stores user-specific files in the ~/.spamassassin/ directory. Here is a list of fi les that may be present for a user: //===INSERT TABLE 01=== Some of them may contain confidential data—for example, regular contacts will appear in the auto-whitelist files. Careful use of permissions will ensure that the files are not readable by regular user accounts. Using SpamAssassin on a per-user basis Perhaps some users don't receive spam, or there may be issues with users sharing whitelists and Bayesian databases. SpamAssassin can be run on an individual basis by moving the recipes to the ~/.procmailrc of specific users. This should increase the filtering performance for each user, but increases disk space usage for each user and requires setting up each individual user account by modifying its ~/.procmailrc. A typical user's .procmailrc might look like this: MAILDIR=$HOME/.maildir:0fw| /usr/bin/spamassassin:0* ^X-Spam-Flag: Yes.SPAM/cur As suggested, e-mail may sometimes be wrongly detected as spam. It's worthwhile reviewing spam to ensure that legitimate e-mails have not been wrongly classified. If the user receives a lot of spam, then wading through it all is time consuming, tedious, and error prone. Procmail can filter spam by checking the spam score written in the e-mail headers by SpamAssassin. The low-scoring spam (for example, scoring up to 9) can be placed in one folder called Probable_Spam, while higher scoring e-mails (which are more likely to be spam) can be placed a folder called Certain_Spam. To do this, we use the X-Spam-Level header, which SpamAssassin creates. This is simply the number of asterisks, related to the X-Spam-Level value. By moving e-mail with more than a certain number of asterisks to the Certain_Spam folder, the remaining spam is "Probable Spam". E-mail that is marked with X-Spam-Flag: NO, is obviously not spam. The following .procmailrc file will filter high scoring spam separately from low scoring spam and non spam: MAILDIR=$HOME/.maildir:0fw| /usr/bin/spamassassin:0* ^X-Spam-Level: **************.Certain_Spam/cur:0* ^X-Spam-FLAG: YES.Probable_Spam/cur Using SpamAssassin as a daemon with Postfix A daemon is a background process; one that waits for work, processes it, and then waits for more work. Using this approach actually improves performance (as long as there is sufficient memory) because responsiveness is improved—the program is always ready and waiting and does not have to be loaded each time spam tagging is required. To use SpamAssassin as a daemon, a user account should be added—it's dangerous to run any service as root. As root, enter the following commands to make a user and a group called spam: # groupadd spam# useradd -m -d /home/spam -g spam -s /bin/false spam# chmod 0700 /home/spam To configure Postfix to run SpamAssassin, use SpamAssassin as a daemon. The Postfix master.cf file must be changed. Edit the file and locate the line that begins with 'smtp inet'. Amend the line to add -o content_filter=spamd to the end. smtp inet n - n - - smtpd -o content_filter=spamd Add the following lines to the end of the file: spamd unix - n n - - pipeflags=R user=spam argv=/usr/bin/spamc-e /usr/sbin/sendmail -oi -f ${sender} ${recipient} If the text is spread across several lines, any continuing line must begin with spaces as shown. The changes to the file define a filter called spamd that runs the spamc client for each message and also specifies that the filter should be run whenever an e-mail is received via SMTP. On this line, spamd is the name of the filter and matches the name used in the content_filter line. The user= portion specifies the user context that should be used to run the command. The argv= portion describes the program that should be run. The other flags are used by Procmail and their presence is important. Using SpamAssassin with amavisd-new amavisd-new is an interface between MTAs and content checkers. Despite its name, amavisd-new is a well-established open source package that is well maintained. Content checkers scan e-mail for viruses and/or spam. amavisd-new is slightly different. Just like like spamd, it is written in Perl and runs as a daemon, but instead of accessing SpamAssassin via the spamc or spamassassin clients, it loads SpamAssassin into memory and accesses the SpamAssassin functions directly. It is therefore closely coupled to SpamAssassin and may need to be upgraded at the same time as SpamAssassin. Unlike other Perl-based applications and utilities, amavisd-new is not available from CPAN. However, it is available in source form and RPM form for many distributions of Linux, and is also available for debian-based repositories. Details of versions available are listed on http://www.ijs.si/software/amavisd/#download. We recommend that if the version of SpamAssassin that your distributor offers is up-to-date, then you should use their package of both SpamAssassin and amavisd.
Read more
  • 0
  • 0
  • 2551

article-image-user-interface-design-icefaces-18-part-2
Packt
30 Nov 2009
11 min read
Save for later

User Interface Design in ICEfaces 1.8: Part 2

Packt
30 Nov 2009
11 min read
Facelets templating To implement the layout design, we use the Facelets templating that is officially a part of the JSF specification since release 2.0. This article will only have a look at certain parts of the Facelets technology. So, we will not discuss how to configure a web project to use Facelets. You can study the source code examples of this article, or have a look at the developer documentation (https://facelets.dev.java.net/nonav/docs/dev/docbook.html) and the articles section of the Facelets wiki (http://wiki.java.net/bin/view/Projects/FaceletsArticles)for further details. The page template First of all, we define a page template that follows our mockup design. For this, we reuse the HelloWorld(Facelets) application. You can import the WAR file now if you did not create a Facelets project. For importing a WAR file, use the menu File | Import | Web | WAR file. In the dialog box, click on the Browse button and select the corresponding WAR file. Click on the Finish button to start the import. The run configuration is done. However, you do not have to configure the Jetty server again. Instead, it can be simply selected as your target. We start coding with a new XHTML file in the WebContent folder. Use the menu File | New | Other | Web | HTML Page and click on the Next button. Use page-template.xhtml for File name in the next dialog. Click on the Next button again and choose New ICEfaces Facelets.xhtml File (.xhtml). Click on the Finish button to create the file. The ICEfaces plugin creates this code: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html > <head> <title> <ui:insert name="title"> Default title </ui:insert> </title> </head> <body> <div id="header"> <ui:include src="/header.xhtml"> <ui:param name="param_name" value="param_value"/> </ui:include> </div> <div id="content"> <ice:form> </ice:form> </div> </body> </html> The structure of the page is almost pure HTML. This is an advantage when using Facelets. The handling of pages is easier and can even be done with a standard HTML editor. The generated code is not what we need. If you try to run this, you will get an error because the header.xhtml file is missing in the project. So, we delete the code between the <body> tags and add the basic structure for the templating. The changed code looks like this: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html > <head> <title> <ui:insert name="title"> Default title </ui:insert> </title> </head> <body> <table align="center" cellpadding="0" cellspacing="0"> <tr><td><!-- header --></td></tr> <tr><td><!-- main navigation --></td></tr> <tr><td><!-- content --></td></tr> <tr><td><!-- footer --></td></tr> </table> </body> </html> We change the <body> part to a table structure. You may wonder why we use a <table> for the layout, and even the align attribute, when there is a <div> tag and CSS. The answer is pragmatism. We do not follow the doctrine because we want to get a clean code and keep things simple. If you have a look at the insufficient CSS support of the Internet Explorer family and the necessary waste of time to get things running, it makes no sense to do so. The CSS support in Internet Explorer is a good example of the violation of user expectations. We define four rows in the table to follow our layout design. You may have recognized that the <title> tag still has its <ui:insert> definition. This is the Facelets tag we use to tell the templating where we want to insert our page-specific code. To separate the different insert areas from each other, the <ui:insert> has a name attribute. We substitute the comments with the <ui:insert> definitions, so that the templating can do the replacements: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html > <head> <title> <ui:insert name="title"> Default title </ui:insert> </title> </head> <body> <table align="center" cellpadding="0" cellspacing="0"> <tr><td><ui:insert name="header"/></td></tr> <tr><td><ui:insert name="mainNavigation"/></td></tr> <tr><td><ui:insert name="content"/></td></tr> <tr><td><ui:insert name="footer"/></td></tr> </table> </body> </html> The <ui:insert> tag allows us to set defaults that are used if we do not define something for replacement. Everything defined between <ui:insert> and </ui:insert> will then be shown instead. We will use this to define a standard behavior of a page that can be overwritten, if necessary. Additionally, this allows us to give hints in the rendering output if something that should be defined in a page is missing. Here is the code showing both aspects: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html > <head> <ice:outputStyle href="/xmlhttp/css/royale/royale.css" /> <title> <ui:insert name="title"> Please, define a title. </ui:insert> </title> </head> <body> <table align="center" cellpadding="0" cellspacing="0"> <tr><td> <ui:insert name="header"> <ice:graphicImage url="/logo.png" /> </ui:insert> </td></tr> <tr><td> <ui:insert name="mainNavigation"> <ice:form> <ice:menuBar noIcons="true"> <ice:menuItem value="Menu 1"/> <ice:menuItem value="Menu 2"/> <ice:menuItem value="Menu 3"/> </ice:menuBar> </ice:form> </ui:insert> </td></tr> <tr><td> <ui:insert name="content"> Please, define some content. </ui:insert> </td></tr> <tr><td> <ui:insert name="footer"> <ice:outputText value="&#169; 2009 by The ICEcubes." /> </ui:insert> </td></tr> </table> </body> </html> The header, the main navigation, and the footer now have defaults. For the page title and the page content, there are messages that ask for an explicit definition. The header has a reference to an image. Add any image you like to the WebContent and adapt the url attribute of the <ice:graphicImage> tag, if necessary. The example project for this article will show the ICEcube logo. It is the logo that is shown in the mockup above. The <ice:menuBar> tag has to be surrounded by a <ice:form> tag, so that the JSF actions of the menu entries can be processed. Additionally, we need a reference to one of the ICEfaces default skins in the <head> tag to get a correct menu presentation. We take the Royale skin here. If you do not know what the Royale skin looks like, you can have a look at the ICEfaces Component Showcase (http://component-showcase.icefaces.org) and select it in the combo box on the top left. After your selection, all components present themselves in this skin definition. Using the template A productive page template has a lot more to define and is also different in its structure. References to your own CSS, JavaScript, or FavIcon files are missing here. The page template would be unmaintainable soon if we were to manage the pull-down menu this way. However, we will primarily look at the basics here. So, we keep the page template for now. Next, we adapt the existing ICEfacesPage1.xhtml to use the page template for its rendering. Here is the original code: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html > <head> <title> <ui:insert name="title"> Default title </ui:insert> </title> </head> <body> <div id="header"> <!-- <ui:include src="/header.xhtml" > <ui:param name="param_name" value="param_value" /> </ui:include> --> </div> <div id="content"> <ice:form> <ice:outputText value="Hello World!"/> <!-- drop ICEfaces components here --> </ice:form> </div> </body> </html> We keep the Hello World! output and use the new page template to give some decoration to it. First of all, we need a reference to the page template so that the templating knows that it has to manage the page. As the page template defines the page structure, we no longer need a <head> tag definition. You may recognize <ui:insert> in the <title> tag. This is indeed the code we normally use in a page template. Facelets has rendered the content in between because it did not find a replacement tag. Theoretically, you are free to define such statements in any location of your code. However, this is not recommended. Facelets has a look at the complete code base and matches pairs of corresponding name attribute definitions between <ui:insert name="..."> and <ui:define name="..."> tags. Here is the adapted code: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html > <body> <ui:composition template="/page-template.xhtml"> <div id="content"> <ice:form> <ice:outputText value="Hello World!"/> </ice:form> </div> </ui:composition> </body> </html> This code creates the following output: We can see our friendly reminders for the missing title and the missing content. The header, the main navigation, and the footer are rendered as expected. The structure of the template seems to be valid, although we recognize that a CSS fle is necessary to define some space between the rows of our layout table. However, something is wrong. Any idea what it is? If you have a look at the hello-world.xhtml again, you can find our Hello World! output; but this cannot be found in the rendering result. As we use the page template, we have to tell the templating where something has to be rendered in the page. However, we did not do this for our Hello World! output. The following code defines the missing <ui:define> tag and skips the <div> and <ice:form> tags that are not really necessary here: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html > <body> <ui:composition template="/page-template.xhtml"> <ui:define name="title"> Hello World on Facelets </ui:define> <ui:define name="content"> <ice:outputText value="Hello World!"/> </ui:define> </ui:composition> </body> </html>
Read more
  • 0
  • 0
  • 2540
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-linux-e-mail-busting-spam-spamassassin
Packt
30 Nov 2009
13 min read
Save for later

Linux E-mail: Busting Spam with SpamAssassin

Packt
30 Nov 2009
13 min read
Spam, or unsolicited commercial e-mail (UCE) as it is sometimes called, is the scourge of the Internet. Spam has increased relentlessly over the last ten years and now accounts for over half of all Internet bandwidth. One in six consumers have acted on spam e-mails, so there is a strong business case for keeping spam out of your users' inboxes. There are a variety of different spam solutions, ranging from outsourcing your spam entirely to no action at all. However, if you have your own e-mail server, you can add spam filtering very easily. SpamAssassin is a very popular open source anti-spam tool. It won a Linux New Media Award-2006 as the "Best Linux-based Anti-spam Solution", and is considered by many to be the best free, open source, anti-spam tool, and better than many commercial products. In fact, several commercial products and services are based on SpamAssassin or previous versions of it. Why filter e-mail If you don't receive any spam, there may be no need to filter spam. However, once one spam message has been received, it is invariably followed by many more. Spammers can sometimes detect if a spam e-mail is viewed, using techniques such as Web bugs, which are tiny images in HTML e-mails that are fetched from web servers, and then know that an e-mail address is valid and vulnerable. If spam is filtered, the initial e-mail may never get seen, and consequently the spammer may not then target the e-mail address with further spam. Despite legal efforts against spam, it is actually on the increase. In Europe and the US, the recent legislation against spam (Directive 2002/58/EC and bill number S.877 respectively) has had little effect and spam is still on the increase in both regions. The main reason for this is that spam is a very good business model. It is very cheap to send spam, as little as one thousandth of a cent per e-mail, and it takes a very low hit rate before a profit is made. The spammer needs to turn just one spam in a hundred thousand or so into a sale to make a profit. As a result, there are many spammers and spam is used to promote a wide range of goods. Spamming costs are also negligible due to use of malware that uses innocent computers to send spam on their behalf. In contrast, the costs of spam to the recipient are remarkably high. Estimates have varied, from 10 cents per spam received, through 1,000 dollars per employee per year, up to a total cost of 140 billion dollars globally in 2007 alone. This cost is mainly labor—distracting people from their work by clogging their inboxes and forcing them to deal with many extra e-mails. Spam interferes with day-to-day work and can include material that is offensive to most people. Companies have a duty to protect their employees from such content. Spam filtering is a very cheap way of minimizing the costs and protecting the workforce. Spam is a moving target Spam isn't static. It changes on a day-to-day basis, as spammers add new methods to their arsenal and anti-spammers develop countermeasures. Due to this, the anti-spam tools that work best are those that are updated frequently. It's a similar predicament to antivirus software—virus definitions need to be updated regularly or new viruses won't be detected. SpamAssassin is regularly updated. In addition to new releases of the software, there is a vigorous community creating, critiquing, and testing new anti-spam rules. These rules can be downloaded automatically for up-to-date protection against spam. Let's discuss some of the measures used by SpamAssassin to fight spam: Open relays: These are e-mail servers that allow spammers to send e-mails even though they are not connected to the owner of the server in any way. To counter this, the anti-spam community has developed blocklists, also known as blacklists, which can be used by anti-spam software to detect spam. Any e-mail that has passed through a server on a blocklist is treated more suspiciously than one that has not. SpamAssassin uses a number of blocklists to test e-mails. Keyword filters: These are useful tools against spam. Spammers tend to repeat the same words and phrases again and again. Rules to detect these phrases are used extensively by SpamAssassin. These make up the bulk of the tests, and the user community rules mentioned previously is normally of this form. They allow specific words, phrases, or sequences of letters, numbers, and punctuation to be detected. Blacklists and whitelists: These are used to list known senders of spam and sources of good e-mail respectively. E-mails from an address on a blacklist are probably spam and are treated accordingly, while e-mails from addresses on a whitelist will be less likely to be treated as spam. SpamAssassin allows the user to enter blacklists and whitelists manually, and also builds up an automatic whitelist and blacklist based on the e-mails that it processes. Statistical filters: These are automated systems that give the probability that an e-mail is spam. This filtration is based on what the filter has seen previously as both spam and non-spam. They generally work by finding words that are present in one type of e-mail but not the other, and using this knowledge to determine which type a new e-mail is. SpamAssassin has a statistical filter called the Bayesian filter that can be very effective in improving detection rates. Content databases: These are mass e-mail detection systems. A lot of e-mail servers receive and submit e-mails to central servers. If the same e-mail is sent to thousands of recipients, it is probably a spam. The content databases prevent confidential e-mails from being sent to the server, by using a technique called hashing that also lowers the amount of data sent to the server. SpamAssassin can integrate with several content databases, notably Vipul's Razor (http://razor.sourceforge.net), Pyzor (http://sourceforge.net/apps/trac/pyzor/), and the Distributed Checksum Clearinghouse, that is, DCC (http://www.rhyolite.com/dcc/). URL blocklists: These are similar to open relay blocklists, but list the websites used by spammers. In nearly all spams, a web address is given. A database of these is built so that spam e-mails can be quickly detected. This is a very efficient and effective tool against spam. By default, SpamAssassin uses Spam URI Realtime BlockLists (SURBLs), without any further configuration required. Spam filtering options Spam can be filtered on the server or the client. The two approaches are explained next. In the first scenario, spam is filtered on the client. Mail is processed by the MTA. The e-mail is then placed in the appropriate user's inbox. The e-mail client reads all new e-mail from the inbox. The e-mail client then passes the e-mail to the filter. When the filter returns the results, the client can display the valid e-mail and either discard spam or file it in a separate folder. In this approach, the spam filtering is always done by the client and is always done when new e-mail is processed. Often when the user may be present, so he or she may either experience a delay before e-mail is visible or there may be a period where spam e-mail is present in the inbox before the client software can filter the spam from view. The amount of spam filtering that can be performed on the client may be limited. In particular, the network tests such as open relay blocklists or SURBLs might be too time consuming or complex to perform on the user's PC. As spam is a moving target, updating many client PCs can become a difficult administrative task. In the second scenario, the spam filtering is performed on the e-mail server. Incoming e-mail is received by the MTA. It is then passed on to the spam filter. The results are then sent back to the MTA. Depending on the results, the MTA places the e-mail in the appropriate user's inbox (4a), or in a separate folder for spam (4b). The e-mail client accesses e-mails in the user's inbox and it can also access the spam folder if required. This approach has several advantages: The spam filtering is done when the e-mail is received, which may be any time of the day. The user is less likely to be inconvenienced by delays. The server can specialize in spam filtering. It may use external services such as open relay blocklists, online content databases, and SURBLs. Configuration is centralized, which will ease setup (for example, firewalls may need to be configured to use online spam tests) and also maintenance (updating of rules or software). On the other hand, the disadvantages include: A single point of failure now exists. However, with care, a broken spam filtering service can be configured around. If the service is not available, e-mail will still be delivered but spam will not be filtered. All spam must be processed by one service. If this service is not scalable, large volumes of e-mail may affect mail delivery times, resulting in poor or intermittent filtering, or possibly even the loss of e-mail service. Introduction to SpamAssassin Spam filtering actually involves two phases—detecting the spam and then doing something with it. SpamAssassin is a spam detector and it modifies the e-mail it processes by putting in headers to mark whether it is spam. It is up to the MTA or the mail delivery agent in the e-mail system to react to the headers that SpamAssassin creates in an e-mail, to filter it out. However, it's possible that another part of the e-mail system could perform this task. The previous figure gives a schematic representation of SpamAssassin. At the heart of SpamAssassin is its Rules Engine that determines which rules are called. Rules trigger whether the various tests are used, including the Bayesian Filter, the network tests, and the auto-whitelists. SpamAssassin uses various databases to do its work, and these are shown too. The rules and scores are text files. Default rules and scores are included in the SpamAssassin distribution and, as we will see, both system administrators and users can add rules or change the scores of existing rules by adding them to files in specific locations. The Bayesian filter (which is a major part of SpamAssassin, and will be covered later) uses a database of statistical data based on previous spam and non-spam e-mails. The Auto-Blacklist/Whitelist also creates its own database. Downloading and installing SpamAssassin SpamAssassin is slightly different from most of the software that is used in this book. It is written in a language called Perl, which has its own distribution method called CPAN (Comprehensive Perl Archive Network). CPAN is a large website of Perl software (normally, Perl modules), and the term CPAN is also the name of the software used to download those modules and install them. Though SpamAssassin is provided as a package by many Linux distributions, we strongly recommend that you install it from source rather than use a package. This way, you will get the latest version of SpamAssassin rather than the one that was current when your Linux distributer created its release. Most Perl users will build Perl modules using CPAN and experience no difficulties. CPAN can automatically locate and install any dependencies (other components that are required to make the desired component work properly). From a Perl point of view, using CPAN to install Perl modules is like using the rpm or apt-get commands in Linux. The basics are very simple and, once a system is configured, it generally works every time. However, learning and configuring a new way of installing software may put off some people. A SpamAssassin release is distributed in source form, but administrators of Red Hat Package Manager (RPM) based systems can easily convert the latest SpamAssassin release into rpm format and then the regular rpm command can be used to install the package. The Debian repository is updated fairly quickly when SpamAssassin is updated and the regular apt-get commands can be used to install SpamAssassin. We strongly advise you to install via apt-get, CPAN, or using the rpmbuild command as described next, in preference to using an RPM provided by a distributor. As SpamAssassin is a Perl Module, it appears on CPAN first. In fact, it is only released when it arrives at CPAN. Users of CPAN can download the latest version of SpamAssassin literally minutes after it has been released. Support is also easier to obtain if SpamAssassin is built from source. Some distributors make unusual decisions when creating their RPM of SpamAssassin or may modify certain default values. These make obtaining support more difficult. RPMs also take time to be delivered. Distributors need time to build and test new versions of software before they release them, and most software packages are not updated as quickly as SpamAssassin. So, Linux distributions may not provide the latest software, and what is provided can be several versions out of date. Using CPAN The prerequisites for installing SpamAssassin 3.2.5 using CPAN are as follows: Perl version 5.6.1 or later: Most modern Linux distributions will include this as a part of the base package. Several Perl modules: The current version of SpamAssassin needs the Digest::SHA1, HTML::Parser, and the Net::DNS modules. CPAN will install these if you configure it to follow dependencies, but there are many additional Perl modules that are optional and should be installed to get the best spam detection. CPAN will issue warnings with the module names, which will enable you to identify and install them. C compiler: This may not be installed by default and may have to be added using the rpm command. The compiler used will normally be called gcc. Internet connection: CPAN will attempt to download the modules using HTTP or FTP, so the network should be configured to allow this. Configuring CPAN If you've used CPAN before, you can skip to the next section, Installing SpamAssassin Using CPAN. If a proxy server is required for Internet traffic, CPAN (and other Perl modules and scripts) will use the http_proxy environment variable. If the proxy requires a username and password, these need to be specified using environment variables. As CPAN is normally run as root, these commands should be entered as root: # HTTP_proxy=http://proxy.name:80# export HTTP_proxy# HTTP_proxy_user=username# export HTTP_proxy_user# HTTP_proxy_pass=password# export HTTP_proxy_pass Next, enter this command: # perl -MCPAN -e shell If the output is similar to the following, the CPAN module is already installed and configured, and you can skip to the next section, Installing SpamAssassin Using CPAN. cpan shell -- CPAN exploration and modules installation (v1.7601)ReadLine support enabled If the output prompts for manual configuration, as shown next, the CPAN module is installed but not configured. Are you ready for manual configuration? [yes] During configuration, the CPAN Perl module prompts for answers to around 30 questions. For most of the questions, selecting the default value is the best response. This initial configuration must be completed before the CPAN Perl module can be used. The questions are mainly about the location of various utilities, and the defaults can be chosen by pressing Enter. The only question for which we should change the default is the one about building prerequisite modules. If we configure CPAN to follow dependencies, it will install the required modules without prompting. Policy on building prerequisites (follow, ask or ignore)? [ask] follow Once CPAN is configured, exit the shell by typing exit and pressing Enter. We are now ready to use CPAN to install SpamAssassin.
Read more
  • 0
  • 0
  • 1942

article-image-ways-improve-performance-your-server-modsecurity-25
Packt
30 Nov 2009
13 min read
Save for later

Ways to improve performance of your server in ModSecurity 2.5

Packt
30 Nov 2009
13 min read
A typical HTTP request To get a better picture of the possible delay incurred when using a web application firewall, it helps to understand the anatomy of a typical HTTP request, and what processing time a typical web page download will incur. This will help us compare any added ModSecurity processing time to the overall time for the entire request. When a user visits a web page, his browser first connects to the server and downloads the main resource requested by the user (for example, an .html file). It then parses the downloaded file to discover any additional files, such as images or scripts, that it must download to be able to render the page. Therefore, from the point of view of a web browser, the following sequence of events happens for each file: Connect to web server. Request required file. Wait for server to start serving file. Download file. Each of these steps adds latency, or delay, to the request. A typical download time for a web page is on the order of hundreds of milliseconds per file for a home cable/DSL user. This can be slower or faster, depending on the speed of the connection and the geographical distance between the client and server. If ModSecurity adds any delay to the page request, it will be to the server processing time, or in other words the time from when the client has connected to the server to when the last byte of content has been sent out to the client. Another aspect that needs to be kept in mind is that ModSecurity will increase the memory usage of Apache. In what is probably the most common Apache configuration, known as "prefork", Apache starts one new child process for each active connection to the server. This means that the number of Apache instances increases and decreases depending on the number of client connections to the server.As the total memory usage of Apache depends on the number of child processes running and the memory usage of each child process, we should look at the way ModSecurity affects the memory usage of Apache. A real-world performance test In this section we will run a performance test on a real web server running Apache 2.2.8 on a Fedora Linux server (kernel 2.6.25). The server has an Intel Xeon 2.33 GHz dual-core processor and 2 GB of RAM. We will start out benchmarking the server when it is running just Apache without having ModSecurity enabled. We will then run our tests with ModSecurity enabled but without any rules loaded. Finally, we will test ModSecurity with a ruleset loaded so that we can draw conclusions about how the performance is affected. The rules we will be using come supplied with ModSecurity and are called the "core ruleset". The core ruleset The ModSecurity core ruleset contains over 120 rules and is shipped with the default ModSecurity source distribution (it's contained in the rules sub-directory). This ruleset is designed to provide "out of the box" protection against some of the most common web attacks used today. Here are some of the things that the core ruleset protects against: Suspicious HTTP requests (for example, missing User-Agent or Accept headers) SQL injection Cross-Site Scripting (XSS) Remote code injection File disclosure We will examine these methods of attack, but for now, let's use the core ruleset and examine how enabling it impacts the performance of your web service. Installing the core ruleset To install the core ruleset, create a new sub-directory named modsec under your Apache conf directory (the location will vary depending on your distribution). Then copy all the .conf files from the rules sub-directory of the source distribution to the new modsec directory: mkdir /etc/httpd/conf/modseccp/home/download/modsecurity-apache/rules/modsecurity_crs_*.conf /etc/httpd/conf/modsec Finally, enter the following line in your httpd.conf file and restart Apache to make it read the new rule files: # Enable ModSecurity core rulesetInclude conf/modsecurity/*.conf Putting the core rules in a separate directory makes it easy to disable them—all you have to do is comment out the above Include line in httpd.conf, restart Apache, and the rules will be disabled. Making sure it works The core ruleset contains a file named modsecurity_crs_10_config.conf. This file contains some of the basic configuration directives needed to turn on the rule engine and configure request and response body access. Since we have already configured these directives, we do not want this file to conflict with our existing configuration, and so we need to disable this. To do this, we simply need to rename the file so that it has a different extension as Apache only loads *.conf files with the Include directive we used above: $ mv modsecurity_crs_10_config.conf modsecurity_crs_10_config.conf.disabled Once we have restarted Apache, we can test that the core ruleset is loaded by attempting to access an URL that it should block. For example, try surfing to http://yourserver/ftp.exe and you should get the error message Method Not Implemented, ensuring that the core rules are loaded. Performance testing basics So what effect does loading the core ruleset have on web application response time and how do we measure this? We could measure the response time for a single request with and without the core ruleset loaded, but this wouldn't have any statistical significance—it could happen that just as one of the requests was being processed, the server started to execute a processor-intensive scheduled task, causing a delayed response time. The best way to compare the response times is to issue a large number of requests and look at the average time it takes for the server to respond. An excellent tool—and the one we are going to use to benchmark the server in the following tests—is called httperf. Written by David Mosberger of Hewlett Packard Research Labs, httperf allows you to simulate high workloads against a web server and obtain statistical data on the performance of the server. You can obtain the program at http://www.hpl.hp.com/research/linux/httperf/ where you'll also find a useful manual page in the PDF file format and a link to the research paper published together with the first version of the tool. Using httperf We'll run httperf with the options --hog (use as many TCP ports as needed), --uri/index.html (request the static web page index.html) and we'll use --num-conn 1000 (initiate a total of 1000 connections). We will be varying the number of requests per second (specified using --rate) to see how the server responds under different workloads. This is what the typical output from httperf looks like when run with the above options: $ ./httperf --hog --server=bytelayer.com --uri /index.html --num-conn1000 --rate 50Total: connections 1000 requests 1000 replies 1000 test-duration20.386 sConnection rate: 49.1 conn/s (20.4 ms/conn, <=30 concurrentconnections)Connection time [ms]: min 404.1 avg 408.2 max 591.3 median 404.5stddev 16.9Connection time [ms]: connect 102.3Connection length [replies/conn]: 1.000Request rate: 49.1 req/s (20.4 ms/req)Request size [B]: 95.0Reply rate [replies/s]: min 46.0 avg 49.0 max 50.0 stddev 2.0 (4samples)Reply time [ms]: response 103.1 transfer 202.9Reply size [B]: header 244.0 content 19531.0 footer 0.0 (total19775.0)Reply status: 1xx=0 2xx=1000 3xx=0 4xx=0 5xx=0CPU time [s]: user 2.37 system 17.14 (user 11.6% system 84.1% total95.7%)Net I/O: 951.9 KB/s (7.8*10^6 bps)Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0 The output shows us the number of TCP connections httperf initiated per second ("Connection rate"), the rate at which it requested files from the server ("Request rate"), and the actual reply rate that the server was able to provide ("Reply rate"). We also get statistics on the reply time—the "reply time – response" is the time taken from when the first byte of the request was sent to the server to when the first byte of the reply was received—in this case around 103 milliseconds. The transfer time is the time to receive the entire response from the server. The page we will be requesting in this case, index.html, is 20 KB in size which is a pretty average size for an HTML document. httperf requests the page one time per connection and doesn't follow any links in the page to download additional embedded content or script files, so the number of such links in the page is of no relevance to our test. Getting a baseline: Testing without ModSecurity When running benchmarking tests like this one, it's always important to get a baseline result so that you know the performance of your server when the component you're measuring is not involved. In our case, we will run the tests against the server when ModSecurity is disabled. This will allow us to tell which impact, if any, running with ModSecurity enabled has on the server. Response time The following chart shows the response time, in milliseconds, of the server when it is running without ModSecurity. The number of requests per second is on the horizontal axis: As we can see, the server consistently delivers response times of around 300 milliseconds until we reach about 75 requests per second. Above this, the response time starts increasing, and at around 500 requests per second the response time is almost a second per request. This data is what we will use for comparison purposes when looking at the response time of the server after we enable ModSecurity. Memory usage Finding the memory usage on a Linux system can be quite tricky. Simply running the Linux top utility and looking at the amount of free memory doesn't quite cut it, and the reason is that Linux tries to use almost all free memory as a disk cache. So even on a system with several gigabytes of memory and no memory-hungry processes, you might see a free memory count of only 50 MB or so. Another problem is that Apache uses many child processes, and to accurately measure the memory usage of Apache we need to sum the memory usage of each child process. What we need is a way to measure the memory usage of all the Apache child processes so that we can see how much memory the web server truly uses. To solve this, here is a small shell script that I have written that runs the ps command to find all the Apache processes. It then passes the PID of each Apache process to pmap to find the memory usage, and finally uses awk to extract the memory usage (in KB) for summation. The result is that the memory usage of Apache is printed to the terminal. The actual shell command is only one long line, but I've put it into a file called apache_mem.sh to make it easier to use: #!/bin/sh# apache_mem.sh# Calculate the Apache memory usageps -ef | grep httpd | grep ^apache | awk '{ print $2 }' | xargs pmap -x | grep 'total kB' | awk '{ print $3 }' | awk '{ sum += $1 } END { print sum }' Now, let's use this script to look at the memory usage of all of the Apache processes while we are running our performance test. The following graph shows the memory usage of Apache as the number of requests per second increases: Apache starts out consuming about 300 MB of memory. Memory usage grows steadily and at about 150 requests per second it starts climbing more rapidly. At 500 requests per second, the memory usage is over 2.4 GB—more than the amount of physical RAM of the server. The fact that this is possible is because of the virtual memory architecture that Linux (and all modern operating systems) use. When there is no more physical RAM available, the kernel starts swapping memory pages out to disk, which allows it to continue operating. However, since reading and writing to a hard drive is much slower than to memory, this starts slowing down the server significantly, as evidenced by the increase in response time seen in the previous graph. CPU usage In both of the tests above, the server's CPU usage was consistently around 1 to 2%, no matter what the request rate was. You might have expected a graph of CPU usage in the previous and subsequent tests, but while I measured the CPU usage in each test, it turned out to run at this low utilization rate for all tests, so a graph would not be very useful. Suffice it to say that in these tests, CPU usage was not a factor. ModSecurity without any loaded rules Now, let's enable ModSecurity—but without loading any rules—and see what happens to the response time and memory usage. Both SecRequestBodyAccess and SecResponseBodyAccess were set to On, so if there is any performance penalty associated with buffering requests and responses, we should see this now that we are running ModSecurity without any rules. The following graph shows the response time of Apache with ModSecurity enabled: We can see that the response time graph looks very similar to the response time graph we got when ModSecurity was disabled. The response time starts increasing at around 75 requests per second, and once we pass 350 requests per second, things really start going downhill. The memory usage graph is also almost identical to the previous one: Apache uses around 1.3 MB extra per child process when ModSecurity is loaded, which equals a total increase of memory usage of 26 MB for this particular setup. Compared to the total amount of memory Apache uses when the server is idle (around 300 MB) this equals an increase of about 10%. Mod Security with the core ruleset loaded Now for the really interesting test we'll run httperf against ModSecurity with the core ruleset loaded and look at what that does to the response time and memory usage. Response time The following graph shows the server response time with the core ruleset loaded: At first, the response time is around 340 ms, which is about 35 ms slower than in previous tests. Once the request rate gets above 50, the server response time starts deteriorating. As the request rates grows, the response time gets worse and worse, reaching a full 5 seconds at 100 requests per second. I have capped the graph at 100 requests per second, as the server performance has already deteriorated enough at this point to allow us to see the trend. We see that the point at which memory usage starts increasing has gone down from 75 to 50 requests per second now that we have enabled the core ruleset. This equals a reduction in the maximum number of requests per second the server can handle of 33%.
Read more
  • 0
  • 0
  • 20675

article-image-polygon-modeling-handgun-using-blender-3d-249-part-2
Packt
30 Nov 2009
4 min read
Save for later

Polygon Modeling of a Handgun using Blender 3D 2.49: Part 2

Packt
30 Nov 2009
4 min read
Modeling the hand wrap Set the view to front again, and select the vertices pointed in the following image. This time we will need two extrusions. Select the vertices in the top-left corner of the model, and move them down to align them to the image. Then, select the other three vertices shown in the following image and extrude them once: As the extruded geometry doesn't fit the guides of our reference image, we will have to select and move the lower vertices and place them as shown in the following image. They don't have to be exactly in the same position, but they should be placed in such a way that the shape of the model looks like our reference image. Remember that you can also select the vertices with the brush select tool. Press the B key twice, and then you will be able to paint the selection. Right after you place the vertices in their new positions, make another extrusion. By the end of the extrusion, try to place the lower vertices aligned with the right side of the guidelines. Just by looking at the image, you'll notice that one side of the model won't be aligned. So, select the vertices on the left or right (any one that isn't aligned with the image) and move it until it gets aligned. By now, the work will be a repetition of extrusions until we have our model created. Select the vertices pointed in the next images, and extrude them until you get the final shape. At this point in the project, you should be familiar with the technique. It's important to remember that for those operations, most of the alignment of the objects with the reference image is done by eye. At the end of each extrusion, use the S key to set the size of the new geometry until it fits with the reference image. If you prefer, the transform ation can be executed in face select mode to speed up the selection of the faces used in the extrusion. Here, we'll use the Skin Faces/Edge-Loops option again to connect the two selected faces. Sometimes, the faces created with this option will be generated with a Set Smooth option selected. This may cause the faces to look odd and have a different set of shading from the other faces. To make it look exactly the same as other faces of the model, select the created faces and click on the Set Solid button. If you don't know where this button is located, you will find it in the Editing panel. After the Skin Faces/Edge-Loops option is applied, the shade of the object will look a bit strange. This is because the smooth option of Blender is being used. Use the Set Solid option to make the faces appear in flat shade mode. A big part of the modeling is complete, but there are a few parts of the weapon missing. Our next task is to create additional parts of the gun, such as a detail for the hand wrap and the energy tank. For this project, we will create different objects for those parts to make our modeling easier. As you can see in the following image, we have created a big part of the gun with a well-organized topology and a fairly clean mesh, which is represented by a minimum number of faces and vertices, made only by quad faces. This type of mesh can be easily edited later by using subdivisions and new extrudes, which is a good reason to keep it as clean as possible.
Read more
  • 0
  • 0
  • 2191

article-image-report-components-nav-2009-part-2
Packt
30 Nov 2009
6 min read
Save for later

Report components in NAV 2009: Part 2

Packt
30 Nov 2009
6 min read
Data item Sections Earlier in our discussion on reports, we referred to the primary components of a report. The Triggers and Properties we have reviewed so far are the data processing components. Next in the report processing sequence are Sections. In Classic RD reports, Sections are the output layout and formatting components. In RTC reports, Sections have a much more limited, but still critically important, role. In the process of creating the initial report design, you may be entering data either completely manually as we've done in our example work, or you may use the Classic Report Wizard. If you use the Wizard, you will end up with Sections defined suitable for Classic Client Report processing. Those Sections may be only rough draft equivalents of what you may want your final report to look like, but they are a suitable starting place for the Classic RD layout work, if that were the tool you were going to use. If you are creating your report completely manually, that is by not using the Wizard, you may also find it appropriate to define Sections to the point that the Classic Client could print a basic, readable report. In our case, we are focusing our production report development effort on the RoleTailored Client, so we will invest minimal effort on Classic Client compatible report layouts. We might do just enough to allow test report runs for data examination purposes and logic flow debugging. However, creating basic Section layouts provides us with another benefit relative to our VS RD layout work, especially if we can create them using the Report Wizard, because all the fields to be used by VS RD must be specified in the Sections. Creating RTC reports via the Classic Report Wizard Let's look at the RTC report development flow again. The preceding image is very similar to the one we studied earlier in this articles, but this flowchart only shows the steps that are pertinent to VS RD. In Step 6 of this flow, there is an option to Create Layout Suggestion in the Visual Studio Report Designer as shown in the following screenshot: When you choose Create Layout Suggestion, the C/SIDE Report Designer will invoke a process that transforms the layout in Sections to a layout in the Visual Studio Report Designer. If a VS RD layout previously existed, the newly created layout will overwrite it. Therefore, this option will normally be used only once, in the initial stages of report design. Let's experiment by using the Report Wizard to create a simple report listing the gifts received by ICAN. We will access the Report Wizard in the Object Designer. Click on Reports | New, then fill in the Wizard screen as shown in the following image. Then click on OK and choose fields to display in the report as shown in the following screenshot. Click on Next, then choose the sorting order (that is index or key) that starts with Donor ID. Click on Next again and choose to Group the data by Donor ID. Click on Next again and choose to create totals for the Estimated Value field. One more, click on Next and choose the List Style for the report, then click on Finish. At this point, you will have generated a Classic Client report using the Report Wizard. If you View | Sections, you should see a C/SIDE report layout that looks much like the following screenshot. Let's save our newly generated report so that, if we need to, we can come back to this point as a checkpoint. Click on File | Save As and assign the report to ID 50002 with the Name of Gifts by Donor. Now click on Tools | Create Layout Suggestion. The process of transforming the Classic Report Layout to a Visual Studio Report Designer Layout will take a few seconds. When the report layout transformation process completes, you should see a screen that looks very similar to the following screenshot. The primary data layout portion of the same VS RD screen is shown in the next image. Compare this to the Classic RD data layout we just looked at a couple of steps ago. You will see some similarities and some considerable differences. Without doing anything else, let's save the VS RD layout we just created for the RoleTailored Client, then run both versions of the report to see the differences in the generated results. To save the VS RD layout, start by simply exiting the VS Report Designer. Once the VS RD screen closes, you will see the following question. Respond by clicking Yes. Then, when you exit the Classic Report Designer, you will see this question. Respond by clicking Yes. You will then be presented with the following message. Again, click on Yes. If there were an error in the RDLC created within the VS RD (such as an incorrect variable name used), an error message similar to the following would display. Since, hopefully, we didn't get such an error message, we can proceed to test both the Classic Client and the RoleTailored Client versions of our generated report. We can test the Classic Client (or C/SIDE RD) version of Report 50002 from the same Object Designer screen where we did our initial design work. Highlight the line for Report 50002 and click on the Run button. You should see the following screen: If we were running this as users, we might want to make a selection of specific Donors here on which to report. As we are just testing, simply click on Preview to see our report onscreen. The report will then appear, looking like the following: As you can see, with minimum development effort (and a minimum of technical knowledge), we have designed and created a report listing Gifts by Donor with subtotals by Donor. The report has proper page and column headings. Not only that, but the report was initiated withs a Request Form allowing application of filters. Close the Classic Client report; now let's run the RTC version. Just like we could do with Pages, we will run our Report test from the Windows Run option. Click on Run and enter the command to run Report 50002, as shown in the next screenshot. Click on OK. If the RoleTailored Client is not active, after a short pause, it will be activated. Then the Request Page will appear. Compare the look and contents of this Request Page with the one we saw previously for the Classic Client. As before, click on Preview and view the report. Of course, this time we're looking at the RTC version. This method of automatic transformation is very useful for getting an initial base for a new report or, obviously, for the complete generation process for a simple report where the requirements for layout are not too restrictive.
Read more
  • 0
  • 0
  • 2556
article-image-moodle-19-math-quizzes-part-2
Packt
30 Nov 2009
4 min read
Save for later

Moodle 1.9 Math Quizzes: Part 2

Packt
30 Nov 2009
4 min read
Adding a math quiz Once we've added a question or two to the question bank, we can add a quiz to our course. I want a simple quiz where each student is allowed one attempt with no help along the way. Let's see how to achieve this now: Return to your course's front page, choose a topic, click on the Add an activity drop-down menu, and select Quiz from the list. Give the quiz a name (this will appear on the course's front page) and, if you wish, you can specify a short introduction: Scroll down to the Attempts box. Set Attempts allowed to 1 and Adaptive mode to No: Scroll down to the bottom of the page, and click the Save and display button. A split screen page is displayed with the course question bank on the right and the (currently empty) quiz on the left: To add questions from the question bank to the quiz, simply select them and click on the Add to quiz button: The questions are now added to the quiz. You'll now see them listed on the left-hand side of the page: To preview the quiz, click on the Preview tab at the top of the page: That's it! The quiz is now configured. Recall that I set Adaptive mode to No. Adaptive mode adds a Submit button to each question, allowing students (with some suitable feedback from me) to learn from their mistakes as they work through the quiz. Try experimenting with this setting. See how your students behave with the Submit button. For example, don't let them think that they can guess a multiple choice answer until they eventually get it right. Remind them that they'll be penalized for each wrong answer. Encouraging students as they attempt the quiz You've seen that there are a lot of settings I've simply ignored as I've configured this quiz. Return to your course's front page, and click on Questions from the course administration block to open the course Question bank. Click on the edit icon next to the numerical question we configured earlier in this article. (Have you spotted that you can tell what type of question it is from the icon on the far-right? Hover the mouse pointer over the icon.): Remember how I mentioned that I'd started filling out feedback? I'm going to finish doing that now in this question by giving some General feedback: When you are happy with your feedback, remember to scroll to the bottom of the page and click on the Save changes button. Now, return to your course's front page, turn editing on, and click on the update icon next to the quiz we added in the previous section: On the quiz configuration page, scroll down to the Attempts section and set Adaptive mode to Yes: Scroll to the bottom of the page, and click on the Save changes button. Preview the quiz now, and notice that under each question there is a Submit button. Experiment with entering both correct and incorrect responses. Click on the Submit button, and see how Moodle reacts by giving the student our feedback. Remember: if you are planning to use Adaptive mode, then it's worth reminding your students that they will be penalized if they get an answer wrong! Reporting quiz results What's great about a Moodle quiz is the detailed reporting Moodle provides for us. Here is an example of the report page for my quiz once a student has attempted it. (In fact, this is a colleague of mine helping me to check that my feedback is understandable!): Such reporting not only allows us to see what our students have been up to, but I also find it an invaluable tool for determining the success of my teaching. Once someone has attempted your quiz, you can no longer modify it (add or remove questions). You will need to delete the attempts to unlock the quiz.
Read more
  • 0
  • 0
  • 1883

article-image-moodle-19-math-quizzes-part-1
Packt
30 Nov 2009
5 min read
Save for later

Moodle 1.9 Math Quizzes: Part 1

Packt
30 Nov 2009
5 min read
As good as the Moodle quiz module is at recognizing the correctness of our students' answers, we quickly run into problems when we need Moodle to recognize, for example, that 3a+2b is exactly the same as 2b+3a . To accomplish this, we're going to need a Computer Algebra System (CAS). The Maxima system (more on this later) has been successfully integrated into Moodle, thanks to the work carried out by Chris Sangwin and Alex Billingsley at the University of Birmingham in the UK. In this article, we will also learn how to perform these tasks: Install and integrate STACK into Moodle Create questions that can be automatically marked using STACK Let's start by adding numeric questions into the course question bank. Creating quizzes Creating a quiz in Moodle is a two-stage process. First, we add our questions to the question bank (each course has its own question bank). Once we've added questions to the question bank, we can add a quiz activity to the course and then choose questions to add to it from the question bank. What are the advantages of having a two-stage process? I worked in much the same way creating quizzes before I started with Moodle. My bookshelf of math books was my question bank, and I would take questions from there to add into my quizzes. Here are just a few of the advantages: If there is a particular point you want to reinforce, then it's easy to include the same question in different quizzes throughout your course. It's easy to share your questions with other Moodle courses. For example, questions on the Pythagorean Theorem are relevant to pure math, mechanics, engineering, and physics. Questions can be exported from and imported into the question bank. This means converting questions over to Moodle is a job that can be shared between colleagues. Here's a basic Pythagorean Theorem question I converted over to Moodle: Question types However, I don't want to convert just this single question over to Moodle; I also want to have questions similar to this one but with different numbers. I want those numbers chosen randomly by Moodle, so I don't have to keep thinking up different numbers each time I set the quiz. The question type I need is Calculated, which we'll learn about in the next section. Calculated question type Let's learn how to add a calculated question to the course question bank now: Return to your course's front page, and click on Questions in the course Administration block: The course Question bank is displayed. From the Create new question drop-down menu, choose Calculated: Give the question a name. Make sure it's a name that you (and, potentially, your colleagues) can recognize when it's in the question bank. Don't call it '1', 'i', or 'a)' because you don't know where it will appear in the quiz. Now, supply the question text: Notice that I have used placeholders in the text, {a} and {b}. We will be configuring Moodle to replace those with numbers shortly. Scroll down to the Answer box. We need to enter the correct calculation into the Correct Answer Formula edit box (don't include a '=' in your answer): The students need to give the correct answer (exactly), but don't worry about the Tolerance setting: leave it set to 0.01. Set the Grade to 100%. I want the students to give their answers to three significant figures, and to that end I needed to click on the Correct answer shows drop-down menu, set that to 3, and change the Format to significant figures: Scroll down to the bottom of the page, and click on the Next Page button. You are now taken to the Choose dataset properties page. The numbers for the variables {a} and {b} will be chosen from a dataset. I want to use my own datasets for each variable. Select will use a new shared dataset for both drop-downs: Click on the Next Page button. You are taken to the Edit the datasets page. Now, we can specify the range of values for {a} and {b}: We need to add numbers to this dataset. I want to add 20 possible pairs of numbers for {a} and {b}. Scroll down to the Add box, select 20 items from the item(s) drop-down menu and click on the Add button: Twenty pairs of numbers are now added to the dataset. Moodle will choose pairs of numbers in this dataset when the student is presented with the question. If you want to alter any of the numbers Moodle has automatically generated for us, you can do so in the second-half of the page. Scroll down to the very bottom of the page, and click on the Save changes button. Our new calculated question is now added to the question bank: To recap, we have seen that creating a calculated question is a two-step process. First, we need to specify the question text. The question text contains variables that Moodle will then replace with random values when the quiz is taken. Then, we need to specify datasets for each of the variables, from which Moodle will choose the values when the quiz is taken. We can have Moodle choose the numbers for us, or we can select our own.
Read more
  • 0
  • 0
  • 3658

article-image-navigating-your-site-using-codeigniter-17-part-2
Packt
30 Nov 2009
9 min read
Save for later

Navigating Your Site using CodeIgniter 1.7: Part 2

Packt
30 Nov 2009
9 min read
Designing a better view At this stage, you might ask: Why are we going through so much effort to serve a simple HTML page? Why not put everything in one file? For a simple site, that's a valid point—but whoever heard of a simple site? One of the coolest things about CI is the way it helps us to develop a consistent structure. So, as we add to and develop our site, it is internally consistent, well laid out, and simple to maintain. At the start, we need to take these three common steps: Write a view page Write a stylesheet Update our config file to specify where the stylesheet is After this is done, we need to update our controller to accept parameters from the URL, and pass variables to the view. First, let's redesign our view and save it as testview.php, at /www/codeigniter/application/views/testview.php. <html><head><!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0Strict//EN'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'><html ><title>Web test Site</title><link rel="stylesheet" type="text/css" href="<?php echo$base."/".$css;?>"></head><body><h1><?php echo $mytitle; ?> </h1><p class='test'> <?php echo $mytext; ?> </p></body></html> It's still mostly HTML, but notice the PHP "code islands" in the highlighted lines. You'll notice that the first bits of PHP code build a link to a stylesheet. Let's save a simple stylesheet as styles.css, at www/codeigniter/css/styles.css. It just says: h1{margin: 5px;padding-left: 10px;padding-right: 10px;background: #ffffff;color: blue;width: 100%;font-size: 36px;}.test{margin: 5px;padding-left: 10px;padding-right: 10px;background: #ffffff;color: red;width: 100%;font-size: 36px;} This gives us two styles to play with, and you'll see we've used both of them in the view. Firstly, let's add an entry to the config file: $config['css'] = 'css/styles.css'; This is simply to tell the name and address of the CSS file that we've just written to the site. But note that the link to the stylesheet is referenced at $base/$css: Where do those variables, $base and $css, get their values? And come to think of it, those variables $mytitle and $mytext at the end of the code? We need a new controller! Designing a better controller Now, we need a new controller. We'll call it Start and save it as start.php, at /www/codeigniter/application/controllers/start.php. This controller has to do several things: Call a view Provide the view with the base URL and the location of the CSS file we just wrote Provide the view with some data—it's expecting a title ($mytitle) and some text ($mytext) Lastly, accept a parameter from the user (that is using the URL request) In other words, we have to populate the variables in the view. So let's start with our Start controller. This is an OO class: <?phpclass Start extends Controller{var $base;var $css; Notice that here we've declared the $base and $css (the CSS filename) as variables or class properties. This saves us from having to redeclare them if we write more than one function in each class. But you can define and use them as local variables within one function, if you prefer. The constructor function now defines the properties we've declared, by looking them up in the config file. To do this, we use the syntax: $this->config->item('name_of_config_variable'); As in: function Start(){parent::Controller();$this->base = $this->config->item('base_url');$this->css = $this->config->item('css');} CI recovers whatever we entered in the config file against that name. Using this system, no matter how many controllers and functions we write, we'll have to change these fundamental variables only once. This is true even if our site becomes so popular that we have to move it to a bigger server. Getting parameters to a function Now, within the Start controller class, let's define the function that will actually do the work. function hello($name = 'Guest'){$data['css'] = $this->css;$data['base'] = $this->base;$data['mytitle'] = 'Welcome to this site';$data['mytext'] = "Hello, $name, now we're getting dynamic!";$this->load->view('testview', $data);} This function expects the parameter $name, but you can set a default value—myfunction($myvariable = 0), which it uses to build the string assigned to the $mytext variable. Well, as we just asked, where does that come from? In this case, it needs to come from the URL request, where it will be the third parameter. So, it comes through the HTTP request: http://127.0.0.1/codeigniter/start/hello/Jose This example code doesn't "clean" the passed variable Jose, or check it in any way. You might want to do this while writing the code. We'll look at how to check form inputs. Normally, variables passed by hyperlinks in this way are generated by your own site. A malicious user can easily add his or her own, just by sending a URL such as: http://www.mysite.com/index.php/start/hello/my_malicious_variable. So, you might want to check that the variables you receive are within the range you expect, before handling them. The last segment of the URL is passed to the function as a parameter. In fact, you can add more segments of extra parameters if you like, subject to the practical limits imposed by your browser. Let's recap on how CI handles URLs, since we've covered it all now: URL segment   What it does   http://www.mysite.com   The base URL that finds your site.   /index.php   Finds the CI router that sets about reading the rest of the URL and selecting the correct route into your site. If you have added the .htaccess file in the previous chapter, this part will not be visible, but will still work as supposed.   /start   The name of the controller that CI will call (If no name is set, CI will call whichever default controller you've specified).   /hello   The name of a function that CI will call, inside the selected controller (If no function is specified, it defaults to the index function, unless you've used _remap).   /Jose   CI passes this to the function as a variable.   If there is a further URL segment, for example, /bert   CI passes this to the function as the second variable. More variables   CI will pass further URL segments as consequent variables.   Passing data to a view Let's go back to the hello function: function hello($name){$data['css'] = $this->css;$data['base'] = $this->base;$data['mytitle'] = 'Welcome to this site';$data['mytext'] = "Hello, $name, now we're getting dynamic!";$this->load->view('testview', $data);} Notice how the hello() function first creates an array called $data, taking a mixture of object properties set up by the constructor and text. Then it loads the view by name, with the array it has just built as the second parameter. Behind the scenes, CI makes good use of another PHP function—extract(). This takes each value in the $data array and turns it into a new variable in its own right. So, the $data array that we've just defined is received by the view as a series of separate variables; $text (equal to "Hello, $name, now we're getting dynamic"), $css (equal to the value from the config file), and so on. In other words, when built, the $data array looks like this: Array([css] => 'mystyles.css';[base] => 'http://127.0.0.1/packt';[mytitle] => 'Welcome to this site';[mytext] => 'Hello, fred, now we're getting dynamic!';) But on its way to the view, it is unpacked, and the following variables are created in the view to correspond to each key/value pair in the array: $css = 'mystyles.css';$base = 'http://127.0.0.1/packt';$mytitle = 'Welcome to this site';$mytext = 'Hello, fred, now we're getting dynamic!';) Although you can only pass one variable to a view, you can pack a lot of information into it. Each value in the $data array can itself be another array, so you can pass pieces of information to the view in a tightly structured manner. Now navigate to http://127.0.0.1/codeigniter/start/hello/jose (note that the URL is different—it is looking for the start function we wrote in the index controller) and you'll see the result—a dynamic page written using MVC architecture. (well, VC at least! We haven't really used the M yet). You can see that the parameter jose is the last segment of the URL. It has been passed into the function, and then to the view. Please remember that your view must be written in parallel with your controller. If the view does not expect and make a place for a variable, it won't be displayed. If the view is expecting a variable to be set and it isn't, you are likely to get an error message (your view can of course accept variables conditionally). Also, a controller can use more than one view; this way we can separate our pages into sections such as the header, the menu, and so on. Each of these views can be nested one inside the other. Child views can even inherit variables passed by the controller to their parent view. Loading a view from inside another view is very easy; just put something like this PHP snippet in your HTML code: <body><div id="menu"><?php $this->load->view('menu'); ?> This way we can load a view inside a view, with all variables in the first one also available into the nested one.
Read more
  • 0
  • 0
  • 3765
article-image-facelets-components-jsf-12
Packt
30 Nov 2009
12 min read
Save for later

Facelets Components in JSF 1.2

Packt
30 Nov 2009
12 min read
One of the more advanced features of the Facelets framework is the ability to define complex templates containing dynamic nested content. What is a template?The Merriam-Webster dictionary defines the word "template" as "a gauge, pattern, or mold (as a thin plate or board) used as a guide to the form of a piece being made" and as "something that establishes or serves as a pattern." In the context of user interface design for the Web, a template can be thought of as an abstraction of a set of pages in the web application.A template does not define content, but rather it defines placeholders for content, and provides the layout, orientation, flow, structure, and logical organization of the elements on the page. We can also think of templates as documents with "blanks" that will be filled in with real data and user interface controls at request time. One of the benefits of templating is the separation of content from presentation, making the maintenance of the views in our web application much easier. The <ui:insert> tag has a name attribute that is used to specify a dynamic content region that will be inserted by the template client. When Facelets renders a UI composition template, it attempts to substitute any <ui:insert> tags in the Facelets template document with corresponding <ui:define> tags from the Facelets template client document. Conceptually, the Facelets composition template transformation process can be visualized as follows: In this scenario, the browser requests a Facelets template client document in our JSF application. This document contains two <ui:define> tags that specify named content elements and references a Facelets template document using the <ui:composition> tag's template attribute. The Facelets template document contains two <ui:insert> tags that have the same names as the <ui:define> tags in the client document, and three <ui:include> tags for the header, footer, and navigation menu. This is a good example of the excellent support that Facelets provides for the Composite View design pattern. Facelets transforms the template client document by merging any content it defines using <ui:define> tags with the content insertion points specified in the Facelets template document using the <ui:insert> tag. The result of merging the Facelets template client document with the Facelets template document is rendered in the browser as a composite view. While this concept may seem a bit complicated at first, it is actually a powerful feature of the Facelets view defi nition framework that can greatly simplify user interface templating in a web application. In fact, the Facelets composition template document can itself be a template client by referencing another composition template. In this way, a complex hierarchy of templates can be used to construct a flexible, multi-layered presentation tier for a JSF application. Without the Facelets templating system, we would have to copy and paste view elements such as headers, footers, and menus from one page to the next to achieve a consistent look and feel across our web application. Facelets templating enables us to define our look and feel in one document and to reuse it across multiple pages. Therefore, if we decide to change the look and feel, we only have to update one document and the change is immediately propagated to all the views of the JSF application. Let's look at some examples of how to use the Facelets templating feature. A simple Facelets template The following is an example of a simple Facelets template. It simply renders a message within an HTML <h2> element. Facelets will replace the "unnamed" <ui:insert> tag (without the name attribute) in the template document with the content of the <ui:composition> tag from the template client document. template01.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>Facelets template example</title><link rel="stylesheet" type="text/css" href="/css/style.css" /></head><body><h2><ui:insert /></h2></body></html> A simple Facelets template client Let's look at a simple example of Facelets templating. The following page is a Facelets template client document. (Remember: you can identify a Facelets template client by looking for the existence of the template attribute on the <ui:composition> tag.) The <ui:composition> tag simply contains the text Hello World. templateClient01.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>ui:composition example</title></head><body><ui:composition template="/WEB-INF/templates/template01.jsf">Hello World</ui:composition><ui:debug /></body></html> The following screenshot displays the result of the Facelets UI composition template transformation when the browser requests templateClient01.jsf. Another simple Facelets template client The following Facelets template client example demonstrates how a template can be reused across multiple pages in the JSF application: templateClient01a.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>ui:composition example</title></head><body><ui:composition template="/WEB-INF/templates/template01.jsf">How are you today?</ui:composition><ui:debug /></body></html> The following screenshot displays the result of the Facelets UI composition template transformation when the browser requests templateClient01a.jsf: A more complex Facelets template The Facelets template in the previous example is quite simple and does not demonstrate some of the more advanced capabilities of Facelets templating. In particular, the template in the previous example only has a single <ui:insert> tag, with no name attribute specified. The behavior of the unnamed <ui:insert> tag is to include any content in the referencing template client page. In more complex templates, multiple <ui:insert> tags can be used to enable template client documents to defi ne several custom content elements that will be inserted throughout the template. The following Facelets template document declares three named <ui:insert> elements. Notice carefully where these tags are located. template02.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title><ui:insert name="title" /></title><link rel="stylesheet" type="text/css" href="/css/style.css" /></head><body><ui:include src="/WEB-INF/includes/header.jsf" /><h2><ui:insert name="header" /></h2><ui:insert name="content" /><ui:include src="/WEB-INF/includes/footer.jsf" /></body></html> In the following example, the template client document defines three content elements named title, header, and content using the <ui:define> tag. Their position in the client document is not important because the template document determines where this content will be positioned. templateClient02.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>ui:composition example</title></head><body><ui:composition template="/WEB-INF/templates/template02.jsf"><ui:define name="title">Facelet template example</ui:define><ui:define name="header">Hello World</ui:define><ui:define name="content">Page content goes here.</ui:define></ui:composition><ui:debug /></body></html> The following screenshot displays the result of a more complex Facelets UI composition template transformation when the browser requests the page named templateClient02.jsf. The next example demonstrates reusing a more advanced Facelets UI composition template. At this stage, we should have a good understanding of the basic concepts of Facelets templating and reuse. templateClient02a.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>ui:composition example</title></head><body>Facelets Components[ 78 ]<ui:composition template="/WEB-INF/templates/template02.jsf"><ui:define name="title">Facelet template example</ui:define><ui:define name="header">Thanks for visiting!</ui:define><ui:define name="content">We hope you enjoyed our site.</ui:define></ui:composition><ui:debug /></body></html> The next screenshot displays the result of the Facelets UI composition transformation when the browser requests templateClient02a.jsf. We can follow this pattern to make a number of JSF pages reuse the template in this manner to achieve a consistent look and feel across our web application. Decorating the user interface The Facelets framework supports the definition of smaller, reusable view elements that can be combined at runtime using the Facelets UI tag library. Some of these tags, such as the <ui:composition> and <ui:component> tags, trim their surrounding content. This behavior is desirable when including content from one complete XHTML document within another complete XHTML document. There are cases, however, when we do not want Facelets to trim the content outside the Facelets tag, such as when we are decorating content on one page with additional JSF or HTML markup defi ned in another page. For example, suppose there is a section of content in our XHTML document that we want to wrap or "decorate" with an HTML <div> element defined in another Facelets page. In this scenario, we want all the content on the page to be displayed, and we are simply surrounding part of the content with additional markup defined in another Facelets template. Facelets provides the <ui:decoration> tag for this purpose. Decorating content on a Facelets page The following example demonstrates how to decorate content on a Facelets page with markup from another Facelets page using the <ui:decoration> tag. The <ui:decoration> tag has a template attribute and behaves like the <ui:composition> tag. Facelets templating typically uses the <ui:composition>. It references a Facelets template document that contains markup to be included in the current document. The main difference between the <ui:composition> tag and the <ui:decoration> tag is that Facelets trims the content outside the <ui:composition> tag but does not trim the content outside the <ui:decoration> tag. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>ui:decorate example</title><link rel="stylesheet" type="text/css" href="css/style.css" /></head><body>Text before will stay.<ui:decorate template="/WEB-INF/templates/box.jsf"><span class="header">Information Box</span><p>This is the first line of information.</p><p>This is the second line of information.</p><p>This is the third line of information.</p></ui:decorate>Text after will stay.<ui:debug /></body></html> Creating a Facelets decoration Let's examine the Facelets decoration template referenced by the previous example. The following source code demonstrates how to create a Facelets template to provide the decoration that will surround the content on another page. As we are using a <ui:composition> tag, only the content inside this tag will be used. In this example, we declare an HTML <div> element with the "box" CSS style class that contains a single Facelets <ui:insert> tag. When Facelets renders the above Facelets page, it encounters the <ui:decorate> tag that references the box.jsf page. The <ui:decorate> tag will be merged together with the associated decoration template and then rendered in the view. In this scenario, Facelets will insert the child content of the <ui:decorate> tag into the Facelets decoration template where the <ui:insert> tag is declared. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>Box</title></head><body><ui:composition><div class="box"><ui:insert /></div></ui:composition></body></html> The result is that our content is surrounded or "decorated" by the <div> element. Any text before or after the <ui:decoration> is still rendered on the page, as shown in the next screenshot: The included decoration is rendered as is, and is not nested inside a UI component as demonstrated in the following Facelets debug page:
Read more
  • 0
  • 0
  • 4033

article-image-linux-e-mail-customizing-spamassassin
Packt
30 Nov 2009
8 min read
Save for later

Linux E-mail: Customizing SpamAssassin

Packt
30 Nov 2009
8 min read
SpamAssassin is very configurable. Almost every setting can be configured on a system-wide or user-specific basis. Reasons to customize If SpamAssassin is so good, then why configure it? Well, there are several reasons why it's worth improving spam filtering with SpamAssassin. SpamAssassin by default (that is, when installed but not customized) typically manages to detect over 80% of spam. After adding a few customizations, the detection rate can be greater than 95%. Everyone's spam is different and one user's spam might look like another user's ham. By trying to be general, SpamAssassin may fail to filter spam for every user. Some of the features of SpamAssassin are disabled by default. By enabling them, the spam recognition rate is increased. The following configuration options are discussed in this article: Altering the scores for rules: This allows rules to be disabled, poor rules to be given less weight, and better rules to be given a higher weight. Obtaining and using new rules: This can improve spam detection. Adding e-mail addresses to white and blacklists: This allows the e-mail from specified senders to always be treated as ham, no matter what the content is, or the opposite. Enabling SpamAssassin's Bayesian filter: This can increase filtering accuracy from 80% to 95% or more. Rules and scores The configuration files for standard, sitewide, and user-specific settings are saved in different directories as follows: Standard configuration settings are stored in /usr/share/spamassassin. Site-wide customizations and settings are stored in /etc/mail/spamassassin/. All files matching *.cf are examined by SpamAssassin. User-specific settings are stored in ~/.spamassassin/local.cf. The bulk of the standard configuration files is devoted to simple rules and their scores. A rule is typically a match for letters, numbers, or other printing characters. Rules are written using a technique called regular expressions, or regex for short. This is a shorthand method of specifying that certain combinations of characters will trigger the rule. A rule might try to detect a particular word, such as "Rolex", or it might look for particular words in certain orders, such as "buy Rolex online". The rules are stored in text files. Default files are stored in /usr/share/spamassassin. These are files that are shipped with SpamAssassin and may change with each release. It's best not to modify these files or place new files in this directory, as an upgrade to SpamAssassin will overwrite these files. Most of the rules that SpamAssassin uses, and the scores applied to each rule, are defined within files in this directory. The defaults can be overwritten by sitewide configuration files. These are placed in /etc/mail/spamassassin. SpamAssassin will read all files matching *.cf in this directory. Settings made here can overrule those in the default files. They can include defining new rules and new rule scores. User-specific customizations can be placed in the ~/.spamassassin/local.cf file. Settings made here can override sitewide settings defined in /etc/mail/spamassassin, and default settings in /usr/share/spamassassin/. New rules may be defined here, and scores for existing rules can be overridden. SpamAssassin first reads all the files in /usr/share/spamassassin in alphanumerical order; 10_misc.cf will be read before 23_bayes.cf. SpamAssassin then reads all the .cf files in /etc/mail/spamassassin/, again in alphanumeric order. Finally, SpamAssassin reads ~user/.spamassassin/user_prefs. If a rule or score is defined in two files, the setting in the last file read is used. This allows the administrator to override the defaults and a user to override the sitewide settings. Each line in a rules file can be blank or contain a comment or a command. The hash or pound (#) symbol is used for comments. Rules generally have three parts, the rule definition, a textual description, and the score or series of scores. Convention dictates that all rule scores for rules provided by SpamAssassin should be located together in a separate file. That file is /usr/share/spamassassin/50_scores.cf. Altering rule scores The simplest configuration change is to change a rule score. There are two reasons why this might be done: A rule is very good at detecting spam, but the rule has a low score. E-mails that fire the rule are not being detected as spam. A rule is acting on non spam. As a result, e-mails that fire the rule are wrongly being detected as spam. The rules that give a positive result when SpamAssassin is run are listed in the X-Spam-Status: header of the e-mail: X-Spam-Status: Yes, score=5.8 required=5.0 tests=BAYES_05,HTML_00_10,HTML_MESSAGE,MPART_ALT_DIFF autolearn=noversion=3.1.0-r54722 The rules applied to the e-mail are listed after tests=. If one continually appears in e-mail that should be marked as spam, but isn't, then the score for the rule should be increased. If a rule often fires in e-mail that is wrongly classified as spam, the score should be decreased. To find the current score, use the grep utility in all the locations where a score can be defined. grep score.*BAYES /usr/share/spamassassin/* /etc/mail/spamassassin/*~/.spamassassin/local.cf/etc/mail/spamassassin/local_scores.cf:score RULE_NAME 0 0 1.665 2.599/etc/mail/spamassassin/local_scores.cf: 4.34 In the previous example, the rule has a default score that is overridden in /etc/mail/spamassassin/local_scores.cf. The original score for the rule had four values. SpamAssassin changes the scores it uses, depending on whether network tests (for example, those that test open relays) are in use and whether the Bayesian Filter is in use. Four scores are listed, which are used in the following circumstances: //===INSERT TABLE 02=== If only one score is given, as overridden in /etc/mail/spamassassin/local_scores.cf, it is used in all circumstances. In the previous example, the system administrator has overridden the default score in /etc/mail/spamassassin/local_scores.cf with a single value in /etc/mail/spamassassin/local_scores.cf. To change this value for a particular user, their ~/.spamassassin/local.cf might read: score RULE_NAME 1.2 This changes the score used from 4.34, set in /etc/mail/spamassassin/local_scores.cf, to 1.2. To disable the rule entirely, the score can be set to zero. score RULE_NAME 0 Endless hours can be spent configuring rule scores. SpamAssassin includes tools to recalculate optimal rule scores, by examining existing e-mails, both spam and non spam. They are covered in detail in the book SpamAssassin published by Packt. Using other rulesets SpamAssassin has a large following, and the design of SpamAssassin has made it easy to add new rulesets, which are sets of rules and default scores for those rules. There are many different rulesets available. Most are based on a particular theme, for example finding the names of drugs often sold with spam or telephone numbers found in spam e-mails. Most custom rulesets are listed on the Custom Rulesets page of the SpamAssassin Wiki at http://wiki.apache.org/spamassassin/CustomRulesets. As the battle against spam is so aggressive, rulesets have been developed that may possibly be uploaded daily. SpamAssassin provides this ability with the sa-update utility. You can choose to use sa-update on a regular basis, or to download a particular ruleset and keep it, or to manually update the rulesets that you choose. To obtain the best results in filtering spam, use of sa-update is recommended. If you wish to install rulesets manually, the Wiki page gives a general description of each ruleset and a URL to download it. Once a ruleset has been chosen, we install it as follows: In a browser, follow the link on the SpamAssassin Wiki page. In most cases, the link will be to a file with a name matching *.cf, and a browser will open it as a text file. Save the file using the browser (normally, the File menu has a Save as option). Copy the file to /etc/mail/spamassassin—the rules will be automatically run if the file is placed in this location. Check that the file has scores in it, otherwise the rules will not be used. Monitor spam performance to ensure that legitimate e-mail is not being detected as spam. Adding rules to SpamAssassin will increase the memory used by SpamAssassin, and the time that it takes to process e-mails. It is best to be cautious and add new rulesets gradually, to ensure that the effect on the machine is understood. You may manually monitor the ruleset and update it on your system using the same process. If you choose to use sa-update, you should plan your use of it. sa-update can use several channels, which are basically sources of rulesets. By default, the channel updates.spamassassin.org is used; another popular channel is the OpenProtect channel, called saupdates.openprotect.com. To enable sa-update, it must be run regularly, for example via cron. Add a cron entry to your system calling the following commands, to update the base rulesets: sa-update If you use an additional channel, the command might look like: sa-update –channel saupdates.openprotect.com To protect against DNS poisoning and impersonation, SpamAssassin allows digital signing of rulesets. To use a signed ruleset, use the –gpgkey parameter to sa-update. The correct value to use with the –gpgkey parameter will be described in the SpamAssassin wiki page for the ruleset.
Read more
  • 0
  • 0
  • 3528
Modal Close icon
Modal Close icon