+Example:
+
+(.h) extern int load_aclfile( struct client_state *csp );
+(.c) int load_aclfile( struct client_state *csp )
+
+Instead of:
+
+(.h) extern int load_aclfile( struct client_state * ); or
+(.h) extern int load_aclfile();
+(.c) int load_aclfile( struct client_state *csp )
+
+-------------------------------------------------------------------------------
+
+4.3.4. Enumerations, and #defines
+
+Explanation:
+
+Use all capital letters, with underscores between words. Do not start an
+identifier with an underscore. (ANSI C reserves these for use by the compiler
+and system headers.)
+
+Example:
+
+(enumeration) : enum Boolean { FALSE, TRUE };
+(#define) : #define DEFAULT_SIZE 100;
+
+Note: We have a standard naming scheme for #defines that toggle a feature in
+the preprocessor: FEATURE_>, where > is a short (preferably 1 or 2 word)
+description.
+
+Example:
+
+#define FEATURE_FORCE 1
+
+#ifdef FEATURE_FORCE
+#define FORCE_PREFIX blah
+#endif /* def FEATURE_FORCE */
+
+-------------------------------------------------------------------------------
+
+4.3.5. Constants
+
+Explanation:
+
+Spell common words out entirely (do not remove vowels).
+
+Use only widely-known domain acronyms and abbreviations. Capitalize all letters
+of an acronym.
+
+Use underscore (_) to separate adjacent acronyms and abbreviations. Never
+terminate a name with an underscore.
+
+Example:
+
+#define USE_IMAGE_LIST 1
+
+Instead of:
+
+#define USE_IMG_LST 1 or
+#define _USE_IMAGE_LIST 1 or
+#define USE_IMAGE_LIST_ 1 or
+#define use_image_list 1 or
+#define UseImageList 1
+
+-------------------------------------------------------------------------------
+
+4.4. Using Space
+
+4.4.1. Put braces on a line by themselves.
+
+Explanation:
+
+The brace needs to be on a line all by itself, not at the end of the statement.
+Curly braces should line up with the construct that they're associated with.
+This practice makes it easier to identify the opening and closing braces for a
+block.
+
+Example:
+
+if ( this == that )
+{
+ ...
+}
+
+Instead of:
+
+if ( this == that ) { ... }
+
+or
+
+if ( this == that ) { ... }
+
+Note: In the special case that the if-statement is inside a loop, and it is
+trivial, i.e. it tests for a condition that is obvious from the purpose of the
+block, one-liners as above may optically preserve the loop structure and make
+it easier to read.
+
+Status: developer-discretion.
+
+Example exception:
+
+while ( more lines are read )
+{
+ /* Please document what is/is not a comment line here */
+ if ( it's a comment ) continue;
+
+ do_something( line );
+}
+
+-------------------------------------------------------------------------------
+
+4.4.2. ALL control statements should have a block
+
+Explanation:
+
+Using braces to make a block will make your code more readable and less prone
+to error. All control statements should have a block defined.
+
+Example:
+
+if ( this == that )
+{
+ DoSomething();
+ DoSomethingElse();
+}
+
+Instead of:
+
+if ( this == that ) DoSomething(); DoSomethingElse();
+
+or
+
+if ( this == that ) DoSomething();
+
+Note: The first example in "Instead of" will execute in a manner other than
+that which the developer desired (per indentation). Using code braces would
+have prevented this "feature". The "explanation" and "exception" from the point
+above also applies.
+
+-------------------------------------------------------------------------------
+
+4.4.3. Do not belabor/blow-up boolean expressions
+
+Example:
+
+structure->flag = ( condition );
+
+Instead of:
+
+if ( condition ) { structure->flag = 1; } else { structure->flag = 0; }
+
+Note: The former is readable and concise. The later is wordy and inefficient.
+Please assume that any developer new to the project has at least a "good"
+knowledge of C/C++. (Hope I do not offend by that last comment ... 8-)
+
+-------------------------------------------------------------------------------
+
+4.4.4. Use white space freely because it is free
+
+Explanation:
+
+Make it readable. The notable exception to using white space freely is listed
+in the next guideline.
+
+Example:
+
+int firstValue = 0;
+int someValue = 0;
+int anotherValue = 0;
+int thisVariable = 0;
+
+if ( thisVariable == thatVariable )
+
+firstValue = oldValue + ( ( someValue - anotherValue ) - whatever )
+
+-------------------------------------------------------------------------------
+
+4.4.5. Don't use white space around structure operators
+
+Explanation:
+
+- structure pointer operator ( "->" ) - member operator ( "." ) - functions and
+parentheses
+
+It is a general coding practice to put pointers, references, and function
+parentheses next to names. With spaces, the connection between the object and
+variable/function name is not as clear.
+
+Example:
+
+aStruct->aMember;
+aStruct.aMember;
+FunctionName();
+
+Instead of: aStruct -> aMember; aStruct . aMember; FunctionName ();
+
+-------------------------------------------------------------------------------
+
+4.4.6. Make the last brace of a function stand out
+
+Example:
+
+int function1( ... )
+{
+ ...code...
+ return( retCode );
+
+} /* -END- function1 */
+
+
+int function2( ... )
+{
+} /* -END- function2 */
+
+Instead of:
+
+int function1( ... ) { ...code... return( retCode ); } int function2( ... ) { }
+
+Note: Use 1 blank line before the closing brace and 2 lines afterward. This
+makes the end of function standout to the most casual viewer. Although function
+comments help separate functions, this is still a good coding practice. In
+fact, I follow these rules when using blocks in "for", "while", "do" loops, and
+long if {} statements too. After all whitespace is free!
+
+Status: developer-discretion on the number of blank lines. Enforced is the end
+of function comments.
+
+-------------------------------------------------------------------------------
+
+4.4.7. Use 3 character indentions
+
+Explanation:
+
+If some use 8 character TABs and some use 3 character TABs, the code can look *
+very* ragged. So use 3 character indentions only. If you like to use TABs, pass
+your code through a filter such as "expand -t3" before checking in your code.
+
+Example:
+
+static const char * const url_code_map[256] =
+{
+ NULL, ...
+};
+
+
+int function1( ... )
+{
+ if ( 1 )
+ {
+ return( ALWAYS_TRUE );
+ }
+ else
+ {
+ return( HOW_DID_YOU_GET_HERE );
+ }
+
+ return( NEVER_GETS_HERE );
+
+}
+
+-------------------------------------------------------------------------------
+
+4.5. Initializing
+
+4.5.1. Initialize all variables
+
+Explanation:
+
+Do not assume that the variables declared will not be used until after they
+have been assigned a value somewhere else in the code. Remove the chance of
+accidentally using an unassigned variable.
+
+Example:
+
+short anShort = 0;
+float aFloat = 0;
+struct *ptr = NULL;
+
+Note: It is much easier to debug a SIGSEGV if the message says you are trying
+to access memory address 00000000 and not 129FA012; or arrayPtr[20] causes a
+SIGSEV vs. arrayPtr[0].
+
+Status: developer-discretion if and only if the variable is assigned a value
+"shortly after" declaration.
+
+-------------------------------------------------------------------------------
+
+4.6. Functions
+
+4.6.1. Name functions that return a boolean as a question.
+
+Explanation:
+
+Value should be phrased as a question that would logically be answered as a
+true or false statement
+
+Example:
+
+ShouldWeBlockThis();
+ContainsAnImage();
+IsWebPageBlank();
+
+-------------------------------------------------------------------------------
+
+4.6.2. Always specify a return type for a function.
+
+Explanation:
+
+The default return for a function is an int. To avoid ambiguity, create a
+return for a function when the return has a purpose, and create a void return
+type if the function does not need to return anything.
+
+-------------------------------------------------------------------------------
+
+4.6.3. Minimize function calls when iterating by using variables
+
+Explanation:
+
+It is easy to write the following code, and a clear argument can be made that
+the code is easy to understand:
+
+Example:
+
+for ( size_t cnt = 0; cnt < blockListLength(); cnt ++ )
+{
+ ....
+}
+
+Note: Unfortunately, this makes a function call for each and every iteration.
+This increases the overhead in the program, because the compiler has to look up
+the function each time, call it, and return a value. Depending on what occurs
+in the blockListLength() call, it might even be creating and destroying
+structures with each iteration, even though in each case it is comparing "cnt"
+to the same value, over and over. Remember too - even a call to blockListLength
+() is a function call, with the same overhead.
+
+Instead of using a function call during the iterations, assign the value to a
+variable, and evaluate using the variable.
+
+Example:
+
+size_t len = blockListLength();
+
+for ( size_t cnt = 0; cnt < len; cnt ++ )
+{
+ ....
+}
+
+Exceptions: if the value of blockListLength() *may* change or could *
+potentially* change, then you must code the function call in the for/while
+loop.
+
+-------------------------------------------------------------------------------
+
+4.6.4. Pass and Return by Const Reference
+
+Explanation:
+
+This allows a developer to define a const pointer and call your function. If
+your function does not have the const keyword, we may not be able to use your
+function. Consider strcmp, if it were defined as: extern int strcmp( char *s1,
+char *s2 );
+
+I could then not use it to compare argv's in main: int main( int argc, const
+char *argv[] ) { strcmp( argv[0], "privoxy" ); }
+
+Both these pointers are *const*! If the c runtime library maintainers do it, we
+should too.
+
+-------------------------------------------------------------------------------
+
+4.6.5. Pass and Return by Value
+
+Explanation:
+
+Most structures cannot fit onto a normal stack entry (i.e. they are not 4 bytes
+or less). Aka, a function declaration like: int load_aclfile( struct
+client_state csp )
+
+would not work. So, to be consistent, we should declare all prototypes with
+"pass by value": int load_aclfile( struct client_state *csp )
+
+-------------------------------------------------------------------------------
+
+4.6.6. Names of include files
+
+Explanation:
+
+Your include statements should contain the file name without a path. The path
+should be listed in the Makefile, using -I as processor directive to search the
+indicated paths. An exception to this would be for some proprietary software
+that utilizes a partial path to distinguish their header files from system or
+other header files.
+
+Example:
+
+#include <iostream.h> /* This is not a local include */
+#include "config.h" /* This IS a local include */
+
+Exception:
+
+/* This is not a local include, but requires a path element. */
+#include <sys/fileName.h>
+
+Note: Please! do not add "-I." to the Makefile without a _very_ good reason.
+This duplicates the #include "file.h" behavior.
+
+-------------------------------------------------------------------------------
+
+4.6.7. Provide multiple inclusion protection
+
+Explanation:
+
+Prevents compiler and linker errors resulting from redefinition of items.
+
+Wrap each header file with the following syntax to prevent multiple inclusions
+of the file. Of course, replace PROJECT_H with your file name, with "." Changed
+to "_", and make it uppercase.
+
+Example:
+
+#ifndef PROJECT_H_INCLUDED
+#define PROJECT_H_INCLUDED
+ ...
+#endif /* ndef PROJECT_H_INCLUDED */
+
+-------------------------------------------------------------------------------
+
+4.6.8. Use `extern "C"` when appropriate
+
+Explanation:
+
+If our headers are included from C++, they must declare our functions as
+`extern "C"`. This has no cost in C, but increases the potential re-usability
+of our code.
+
+Example:
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* def __cplusplus */
+
+... function definitions here ...
+
+#ifdef __cplusplus
+}
+#endif /* def __cplusplus */
+
+-------------------------------------------------------------------------------
+
+4.6.9. Where Possible, Use Forward Struct Declaration Instead of Includes
+
+Explanation:
+
+Useful in headers that include pointers to other struct's. Modifications to
+excess header files may cause needless compiles.
+
+Example:
+
+/*********************************************************************
+ * We're avoiding an include statement here!
+ *********************************************************************/
+struct file_list;
+extern file_list *xyz;
+
+Note: If you declare "file_list xyz;" (without the pointer), then including the
+proper header file is necessary. If you only want to prototype a pointer,
+however, the header file is unnecessary.
+
+Status: Use with discretion.
+
+-------------------------------------------------------------------------------
+
+4.7. General Coding Practices
+
+4.7.1. Turn on warnings
+
+Explanation
+
+Compiler warnings are meant to help you find bugs. You should turn on as many
+as possible. With GCC, the switch is "-Wall". Try and fix as many warnings as
+possible.
+
+-------------------------------------------------------------------------------
+
+4.7.2. Provide a default case for all switch statements
+
+Explanation:
+
+What you think is guaranteed is never really guaranteed. The value that you
+don't think you need to check is the one that someday will be passed. So, to
+protect yourself from the unknown, always have a default step in a switch
+statement.
+
+Example:
+
+switch( hash_string( cmd ) )
+{
+ case hash_actions_file :
+ ... code ...
+ break;
+
+ case hash_confdir :
+ ... code ...
+ break;
+
+ default :
+ log_error( ... );
+ ... anomaly code goes here ...
+ continue; / break; / exit( 1 ); / etc ...
+
+} /* end switch( hash_string( cmd ) ) */
+
+Note: If you already have a default condition, you are obviously exempt from
+this point. Of note, most of the WIN32 code calls `DefWindowProc' after the
+switch statement. This API call *should* be included in a default statement.
+
+Another Note: This is not so much a readability issue as a robust programming
+issue. The "anomaly code goes here" may be no more than a print to the STDERR
+stream (as in load_config). Or it may really be an ABEND condition.
+
+Status: Programmer discretion is advised.
+
+-------------------------------------------------------------------------------
+
+4.7.3. Try to avoid falling through cases in a switch statement.
+
+Explanation:
+
+In general, you will want to have a 'break' statement within each 'case' of a
+switch statement. This allows for the code to be more readable and
+understandable, and furthermore can prevent unwanted surprises if someone else
+later gets creative and moves the code around.
+
+The language allows you to plan the fall through from one case statement to
+another simply by omitting the break statement within the case statement. This
+feature does have benefits, but should only be used in rare cases. In general,
+use a break statement for each case statement.
+
+If you choose to allow fall through, you should comment both the fact of the
+fall through and reason why you felt it was necessary.
+
+-------------------------------------------------------------------------------
+
+4.7.4. Use 'long' or 'short' Instead of 'int'
+
+Explanation:
+
+On 32-bit platforms, int usually has the range of long. On 16-bit platforms,
+int has the range of short.
+
+Status: open-to-debate. In the case of most FSF projects (including X/
+GNU-Emacs), there are typedefs to int4, int8, int16, (or equivalence ... I
+forget the exact typedefs now). Should we add these to IJB now that we have a
+"configure" script?
+
+-------------------------------------------------------------------------------
+
+4.7.5. Don't mix size_t and other types
+
+Explanation:
+
+The type of size_t varies across platforms. Do not make assumptions about
+whether it is signed or unsigned, or about how long it is. Do not compare a
+size_t against another variable of a different type (or even against a
+constant) without casting one of the values. Try to avoid using size_t if you
+can.
+
+-------------------------------------------------------------------------------
+
+4.7.6. Declare each variable and struct on its own line.
+
+Explanation:
+
+It can be tempting to declare a series of variables all on one line. Don't.
+
+Example:
+
+long a = 0;
+long b = 0;
+long c = 0;
+
+Instead of:
+
+long a, b, c;
+
+Explanation: - there is more room for comments on the individual variables -
+easier to add new variables without messing up the original ones - when
+searching on a variable to find its type, there is less clutter to "visually"
+eliminate
+
+Exceptions: when you want to declare a bunch of loop variables or other trivial
+variables; feel free to declare them on 1 line. You should, although, provide a
+good comment on their functions.
+
+Status: developer-discretion.
+
+-------------------------------------------------------------------------------
+
+4.7.7. Use malloc/zalloc sparingly
+
+Explanation:
+
+Create a local struct (on the stack) if the variable will live and die within
+the context of one function call.
+
+Only "malloc" a struct (on the heap) if the variable's life will extend beyond
+the context of one function call.
+
+Example:
+
+If a function creates a struct and stores a pointer to it in a
+list, then it should definitely be allocated via `malloc'.
+
+-------------------------------------------------------------------------------
+
+4.7.8. The Programmer Who Uses 'malloc' is Responsible for Ensuring 'free'
+
+Explanation:
+
+If you have to "malloc" an instance, you are responsible for insuring that the
+instance is `free'd, even if the deallocation event falls within some other
+programmer's code. You are also responsible for ensuring that deletion is
+timely (i.e. not too soon, not too late). This is known as "low-coupling" and
+is a "good thing (tm)". You may need to offer a free/unload/destuctor type
+function to accommodate this.
+
+Example:
+
+int load_re_filterfile( struct client_state *csp ) { ... }
+static void unload_re_filterfile( void *f ) { ... }
+
+Exceptions:
+
+The developer cannot be expected to provide `free'ing functions for C run-time
+library functions ... such as `strdup'.
+
+Status: developer-discretion. The "main" use of this standard is for allocating
+and freeing data structures (complex or nested).
+
+-------------------------------------------------------------------------------
+
+4.7.9. Add loaders to the `file_list' structure and in order
+
+Explanation:
+
+I have ordered all of the "blocker" file code to be in alpha order. It is
+easier to add/read new blockers when you expect a certain order.
+
+Note: It may appear that the alpha order is broken in places by POPUP tests
+coming before PCRS tests. But since POPUPs can also be referred to as
+KILLPOPUPs, it is clear that it should come first.
+
+-------------------------------------------------------------------------------
+
+4.7.10. "Uncertain" new code and/or changes to existing code, use FIXME
+
+Explanation:
+
+If you have enough confidence in new code or confidence in your changes, but
+are not *quite* sure of the repercussions, add this:
+
+/* FIXME: this code has a logic error on platform XYZ, * attempting to fix */ #
+ifdef PLATFORM ...changed code here... #endif
+
+or:
+
+/* FIXME: I think the original author really meant this... */ ...changed code
+here...
+
+or:
+
+/* FIXME: new code that *may* break something else... */ ...new code here...
+
+Note: If you make it clear that this may or may not be a "good thing (tm)", it
+will be easier to identify and include in the project (or conversely exclude
+from the project).
+
+-------------------------------------------------------------------------------
+
+4.8. Addendum: Template for files and function comment blocks:
+
+Example for file comments:
+
+const char FILENAME_rcs[] = "$Id: developer-manual.sgml,v 1.42 2002/05/05 20:26:02 hal9 Exp $";
+/*********************************************************************
+ *
+ * File : $Source$
+ *
+ * Purpose : (Fill me in with a good description!)
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * Privoxy team. http://www.privoxy.org/
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log$
+ *
+ *********************************************************************/
+
+
+#include "config.h"
+
+ ...necessary include files for us to do our work...
+
+const char FILENAME_h_rcs[] = FILENAME_H_VERSION;
+
+Note: This declares the rcs variables that should be added to the
+"show-proxy-args" page. If this is a brand new creation by you, you are free to
+change the "Copyright" section to represent the rights you wish to maintain.
+
+Note: The formfeed character that is present right after the comment flower box
+is handy for (X|GNU)Emacs users to skip the verbiage and get to the heart of
+the code (via `forward-page' and `backward-page'). Please include it if you
+can.
+
+Example for file header comments:
+
+#ifndef _FILENAME_H
+#define _FILENAME_H
+#define FILENAME_H_VERSION "$Id: developer-manual.sgml,v 1.42 2002/05/05 20:26:02 hal9 Exp $"
+/*********************************************************************
+ *
+ * File : $Source$
+ *
+ * Purpose : (Fill me in with a good description!)
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * Privoxy team. http://www.privoxy.org/
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log$
+ *
+ *********************************************************************/
+
+
+#include "project.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ ... function headers here ...
+
+
+/* Revision control strings from this header and associated .c file */
+extern const char FILENAME_rcs[];
+extern const char FILENAME_h_rcs[];
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _FILENAME_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
+
+Example for function comments:
+
+/*********************************************************************
+ *
+ * Function : FUNCTION_NAME
+ *
+ * Description : (Fill me in with a good description!)
+ *
+ * parameters :
+ * 1 : param1 = pointer to an important thing
+ * 2 : x = pointer to something else
+ *
+ * Returns : 0 => Ok, everything else is an error.
+ *
+ *********************************************************************/
+int FUNCTION_NAME( void *param1, const char *x )
+{
+ ...
+ return( 0 );
+
+}
+
+Note: If we all follow this practice, we should be able to parse our code to
+create a "self-documenting" web page.
+
+-------------------------------------------------------------------------------
+
+5. Testing Guidelines
+
+To be filled.
+
+-------------------------------------------------------------------------------
+
+5.1. Testplan for releases
+
+Explain release numbers. major, minor. developer releases. etc.
+
+ 1. Remove any existing rpm with rpm -e
+
+ 2. Remove any file that was left over. This includes (but is not limited to)
+
+ + /var/log/privoxy
+
+ + /etc/privoxy
+
+ + /usr/sbin/privoxy
+
+ + /etc/init.d/privoxy
+
+ + /usr/doc/privoxy*
+
+ 3. Install the rpm. Any error messages?
+
+ 4. start,stop,status Privoxy with the specific script (e.g. /etc/rc.d/init/
+ privoxy stop). Reboot your machine. Does autostart work?
+
+ 5. Start browsing. Does Privoxy work? Logfile written?
+
+ 6. Remove the rpm. Any error messages? All files removed?
+
+-------------------------------------------------------------------------------
+
+5.2. Test reports
+
+Please submit test reports only with the test form at sourceforge. Three simple
+steps:
+
+ * Select category: the distribution you test on.
+
+ * Select group: the version of Privoxy that we are about to release.
+
+ * Fill the Summary and Detailed Description with something intelligent (keep
+ it short and precise).
+
+Do not mail to the mailinglist (we cannot keep track on issues there).
+
+-------------------------------------------------------------------------------
+
+6. Releasing a New Version
+
+When we release versions of Privoxy, our work leaves our cozy secret lab and
+has to work in the cold RealWorld[tm]. Once it is released, there is no way to
+call it back, so it is very important that great care is taken to ensure that
+everything runs fine, and not to introduce problems in the very last minute.
+
+So when releasing a new version, please adhere exactly to the procedure
+outlined in this chapter.
+
+The following programs are required to follow this process: ncftpput (ncftp),
+scp, ssh (ssh), gmake (GNU's version of make), autoconf, cvs.
+
+-------------------------------------------------------------------------------
+
+6.1. Version numbers
+
+First you need to determine which version number the release will have. Privoxy
+version numbers consist of three numbers, separated by dots, like in X.Y.Z,
+where:
+
+ * X, the version major, is rarely ever changed. It is increased by one if
+ turning a development branch into stable substantially changes the
+ functionality, user interface or configuration syntax. Majors 1 and 2 were
+ Junkbuster, and 3 will be the first stable Privoxy release.
+
+ * Y, the version minor, represents the branch within the major version. At
+ any point in time, there are two branches being maintained: The stable
+ branch, with an even minor, say, 2N, in which no functionality is being
+ added and only bugfixes are made, and 2N+1, the development branch, in
+ which the further development of Privoxy takes place. This enables us to
+ turn the code upside down and inside out, while at the same time providing
+ and maintaining a stable version. The minor is reset to zero (and one) when
+ the major is inrcemented. When a development branch has matured to the
+ point where it can be turned into stable, the old stable branch 2N is given
+ up (i.e. no longer maintained), the former development branch 2N+1 becomes
+ the new stable branch 2N+2, and a new development branch 2N+3 is opened.
+
+ * Z, the point or sub version, represents a release of the software within a
+ branch. It is therefore incremented immediately before each code freeze. In
+ development branches, only the even point versions correspond to actual
+ releases, while the odd ones denote the evolving state of the sources on
+ CVS in between. It follows that Z is odd on CVS in development branches
+ most of the time. There, it gets increased to an even number immediately
+ before a code freeze, and is increased to an odd number again immediately
+ thereafter. This ensures that builds from CVS snapshots are easily
+ distinguished from released versions. The point version is reset to zero
+ when the minor changes.
+
+-------------------------------------------------------------------------------
+
+6.2. Before the Release: Freeze
+
+The following must be done by one of the developers prior to each new release.
+
+ * Make sure that everybody who has worked on the code in the last couple of
+ days has had a chance to yell "no!" in case they have pending changes/fixes
+ in their pipelines. Announce the freeze so that nobody will interfere with
+ last minute changes.
+
+ * Increment the version number (point from odd to even in development
+ branches!) in configure.in.
+
+ * If default.action has changed since last release (i.e. software release or
+ standalone actions file release), bump up its version info to A.B in this
+ line:
+
+ {+add-header{X-Actions-File-Version: A.B} -filter -no-popups}
+
+ Then change the version info in doc/webserver/actions/index.php, line:
+ '$required_actions_file_version = "A.B";'
+
+ * If the HTML documentation is not in sync with the SGML sources you need to
+ regenerate and upload it to the webserver. (If in doubt, just do it.) See
+ the Section "Updating the webserver" in this manual for details.
+
+ * Commit all files that were changed in the above steps!
+
+ * Tag all files in CVS with the version number with "cvs tag v_X_Y_Z". Don't
+ use vX_Y_Z, ver_X_Y_Z, v_X.Y.Z (won't work) etc.
+
+ * If the release was in a development branch, increase the point version from
+ even to odd (X.Y.(Z+1)) again in configure.in and commit your change.
+
+ * On the webserver, copy the user manual to a new top-level directory called
+ X.Y.Z. This ensures that help links from the CGI pages, which have the
+ version as a prefix, will go into the right version of the manual. If this
+ is a development branch release, also symlink X.Y.(Z-1) to X.Y.Z and X.Y.
+ (Z+1) to . (i.e. dot).
+
+-------------------------------------------------------------------------------
+
+6.3. Building and Releasing the Packages
+
+Now the individual packages can be built and released. Note that for GPL
+reasons the first package to be released is always the source tarball.
+
+For all types of packages, including the source tarball, you must make sure
+that you build from clean sources by exporting the right version from CVS into
+an empty directory:.
+
+ mkdir dist # delete or choose different name if it already exists
+ cd dist
+ cvs -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa login
+ cvs -z3 -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa export -r v_X_Y_Z current
+
+Do NOT change a single bit, including, but not limited to version information
+after export from CVS. This is to make sure that all release packages, and with
+them, all future bug reports, are based on exactly the same code.
+
+Please find additional instructions for the source tarball and the individual
+platform dependent binary packages below.
+
+-------------------------------------------------------------------------------
+
+6.3.1. Source Tarball
+
+First, make sure that you have freshly exported the right version into an empty
+directory. (See "Building and releasing packages" above). Then run:
+
+ cd current
+ autoheader && autoconf && ./configure
+
+Then do:
+
+ make tarball-dist
+
+To upload the package to Sourceforge, simply issue
+
+ make tarball-upload
+
+Go to the displayed URL and release the file publicly on Sourceforge. For the
+change log field, use the relevant section of the ChangeLog file.
+
+-------------------------------------------------------------------------------
+
+6.3.2. SuSE or Red Hat RPM
+
+In following text, replace dist with either "rh" for Red Hat or "suse" for
+SuSE.
+
+First, make sure that you have freshly exported the right version into an empty
+directory. (See "Building and releasing packages" above).
+
+As the only exception to not changing anything after export from CVS, now
+examine the file privoxy-dist.spec and make sure that the version information
+and the RPM release number are correct. The RPM release numbers for each
+version start at one. Hence it must be reset to one if this is the first RPM
+for dist which is built from version X.Y.Z. Check the file list if unsure.
+Else, it must be set to the highest already available RPM release number for
+that version plus one.
+
+Then run:
+
+ cd current
+ autoheader && autoconf && ./configure
+
+Then do
+
+ make dist-dist
+
+To upload the package to Sourceforge, simply issue
+
+ make dist-upload rpm_packagerev
+
+where rpm_packagerev is the RPM release number as determined above. Go to the
+displayed URL and release the file publicly on Sourceforge. Use the release
+notes and change log from the source tarball package.
+
+-------------------------------------------------------------------------------
+
+6.3.3. OS/2
+
+First, make sure that you have freshly exported the right version into an empty
+directory. (See "Building and releasing packages" above). Then get the OS/2
+Setup module:
+
+ cvs -z3 -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa co os2setup
+
+You will need a mix of development tools. The main compilation takes place with
+IBM Visual Age C++. Some ancillary work takes place with GNU tools, available
+from various sources like hobbes.nmsu.edu. Specificially, you will need
+autoheader, autoconf and sh tools. The packaging takes place with WarpIN,
+available from various sources, including its home page: xworkplace.
+
+Change directory to the os2setup directory. Edit the os2build.cmd file to set
+the final executable filename. For example,
+
+ installExeName='privoxyos2_setup_X.Y.Z.exe'
+
+Next, edit the IJB.wis file so the release number matches in the PACKAGEID
+section:
+
+ PACKAGEID="Privoxy Team\Privoxy\Privoxy Package\X\Y\Z"
+
+You're now ready to build. Run:
+
+ os2build
+
+You will find the WarpIN-installable executable in the ./files directory.
+Upload this anonymously to uploads.sourceforge.net/incoming, create a release
+for it, and you're done. Use the release notes and Change Log from the source
+tarball package.
+
+-------------------------------------------------------------------------------
+
+6.3.4. Solaris
+
+Login to Sourceforge's compilefarm via ssh:
+
+ ssh cf.sourceforge.net
+
+Choose the right operating system (not the Debian one). When logged in, make
+sure that you have freshly exported the right version into an empty directory.
+(See "Building and releasing packages" above). Then run:
+
+ cd current
+ autoheader && autoconf && ./configure
+
+Then run
+
+ gmake solaris-dist
+
+which creates a gzip'ed tar archive. Sadly, you cannot use make solaris-upload
+on the Sourceforge machine (no ncftpput). You now have to manually upload the
+archive to Sourceforge's ftp server and release the file publicly. Use the
+release notes and Change Log from the source tarball package.
+
+-------------------------------------------------------------------------------
+
+6.3.5. Windows
+
+You should ensure you have the latest version of Cygwin (from http://
+www.cygwin.com/). Run the following commands from within a Cygwin bash shell.
+
+First, make sure that you have freshly exported the right version into an empty
+directory. (See "Building and releasing packages" above). Then get the Windows
+setup module:
+
+ cvs -z3 -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa co winsetup
+
+Then you can build the package. This is fully automated, and is controlled by
+winsetup/GNUmakefile. All you need to do is:
+
+ cd winsetup
+ make
+
+Now you can manually rename privoxy_setup.exe to privoxy_setup_X_Y_Z.exe, and
+upload it to SourceForge. When releasing the package on SourceForge, use the
+release notes and Change Log from the source tarball package.
+
+-------------------------------------------------------------------------------
+
+6.3.6. Debian
+
+First, make sure that you have freshly exported the right version into an empty
+directory. (See "Building and releasing packages" above). Then, run:
+
+ cd current
+ autoheader && autoconf && ./configure
+
+Then do FIXME.
+
+-------------------------------------------------------------------------------
+
+6.3.7. Mac OSX
+
+First, make sure that you have freshly exported the right version into an empty
+directory. (See "Building and releasing packages" above). Then get the Mac OSX
+setup module:
+
+ cvs -z3 -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa co osxsetup
+
+Then run:
+
+ cd osxsetup
+ build
+
+This will run autoheader, autoconf and configure as well as make. Finally, it
+will copy over the necessary files to the ./osxsetup/files directory for
+further processing by PackageMaker.
+
+Bring up PackageMaker with the PrivoxyPackage.pmsp definition file, modify the
+package name to match the release, and hit the "Create package" button. If you
+specify ./Privoxy.pkg as the output package name, you can then create the
+distributable zip file with the command:
+
+zip -r privoxyosx_setup_x.y.z.zip Privoxy.pkg
+
+You can then upload privoxyosx_setup_x.y.z.zip anonymously to
+uploads.sourceforge.net/incoming, create a release for it, and you're done. Use
+the release notes and Change Log from the source tarball package.
+
+-------------------------------------------------------------------------------
+
+6.3.8. FreeBSD
+
+Login to Sourceforge's compilefarm via ssh:
+
+ ssh cf.sourceforge.net
+
+Choose the right operating system. When logged in, make sure that you have
+freshly exported the right version into an empty directory. (See "Building and
+releasing packages" above). Then run:
+
+ cd current
+ autoheader && autoconf && ./configure
+
+Then run:
+
+ gmake freebsd-dist
+
+which creates a gzip'ed tar archive. Sadly, you cannot use make freebsd-upload
+on the Sourceforge machine (no ncftpput). You now have to manually upload the
+archive to Sourceforge's ftp server and release the file publicly. Use the
+release notes and Change Log from the source tarball package.
+
+-------------------------------------------------------------------------------
+
+6.3.9. HP-UX 11
+
+First, make sure that you have freshly exported the right version into an empty
+directory. (See "Building and releasing packages" above). Then run:
+
+ cd current
+ autoheader && autoconf && ./configure
+
+Then do FIXME.
+
+-------------------------------------------------------------------------------
+
+6.3.10. Amiga OS
+
+First, make sure that you have freshly exported the right version into an empty
+directory. (See "Building and releasing packages" above). Then run:
+
+ cd current
+ autoheader && autoconf && ./configure
+
+Then do FIXME.
+
+-------------------------------------------------------------------------------
+
+6.3.11. AIX
+
+Login to Sourceforge's compilefarm via ssh:
+
+ ssh cf.sourceforge.net
+
+Choose the right operating system. When logged in, make sure that you have
+freshly exported the right version into an empty directory. (See "Building and
+releasing packages" above). Then run:
+
+ cd current
+ autoheader && autoconf && ./configure
+
+Then run:
+
+ make aix-dist
+
+which creates a gzip'ed tar archive. Sadly, you cannot use make aix-upload on
+the Sourceforge machine (no ncftpput). You now have to manually upload the
+archive to Sourceforge's ftp server and release the file publicly. Use the
+release notes and Change Log from the source tarball package.
+
+-------------------------------------------------------------------------------
+
+6.4. Uploading and Releasing Your Package
+
+After the package is ready, it is time to upload it to SourceForge, and go
+through the release steps. The upload is done via FTP:
+
+ * Upload to: ftp://upload.sourceforge.net/incoming
+
+ * user: anonymous
+
+ * password: ijbswa-developers@lists.sourceforge.net
+
+Once this done go to http://sourceforge.net/project/admin/editpackages.php?
+group_id=11118, making sure you are logged in. Find your target platform in the
+second column, and click Add Release. You will then need to create a new
+release for your package, using the format of $VERSION ($CODE_STATUS), e.g.
+2.9.15 (beta).
+
+Now just follow the prompts. Be sure to add any appropriate Release notes. You
+should see your freshly uploaded packages in "Step 2. Add Files To This
+Release". Check the appropriate box(es). Remember at each step to hit the
+"Refresh/Submit" buttons! You should now see your file(s) listed in Step 3.
+Fill out the forms with the appropriate information for your platform, being
+sure to hit "Update" for each file. If anyone is monitoring your platform,
+check the "email" box at the very bottom to notify them of the new package.
+This should do it!
+
+If you have made errors, or need to make changes, you can go through
+essentially the same steps, but select Edit Release, instead of Add Release.
+
+-------------------------------------------------------------------------------
+
+6.5. After the Release
+
+When all (or: most of the) packages have been uploaded and made available, send
+an email to the announce mailing list, Subject: "Version X.Y.Z available for
+download". Be sure to include the download location, the release notes and the
+change log.
+
+-------------------------------------------------------------------------------
+
+7. Update the Webserver
+
+When updating the webserver, please follow these steps to make sure that no
+broken links, incosistent contents or permission problems will occur:
+
+If you have changed anything in the documentation source SGML files, do:
+
+ make dok # (or make redkat-dok if make dok doesn't work for you)
+
+That will generate doc/webserver/user-manual, doc/webserver/developer-manual,
+doc/webserver/faq and doc/webserver/index.html automatically.
+
+If you changed the manual page source, generate doc/webserver/man-page/
+privoxy-man-page.html by running "make man". (This is a separate target due to
+dependencies on some obscure perl scripts. See comments in GNUmakefile.)
+
+If you want to add new files to the webserver, create them locally in the doc/
+webserver/* directory (or create new directories under doc/webserver).
+
+Next, commit any changes from the above steps to CVS. All set? Then do
+
+ make webserver
+
+This will do the upload to the webserver (www.privoxy.org) and ensure all files
+and directories there are group writable.
+
+Please do NOT use any other means of transferring files to the webserver to
+avoid permission problems.
+
+-------------------------------------------------------------------------------
+
+8. Contacting the developers, Bug Reporting and Feature Requests
+
+We value your feedback. However, to provide you with the best support, please
+note the following sections.
+
+-------------------------------------------------------------------------------
+
+8.1. Get Support
+
+To get support, use the Sourceforge Support Forum:
+
+ http://sourceforge.net/tracker/?group_id=11118&atid=211118
+
+-------------------------------------------------------------------------------
+
+8.2. Report bugs
+
+To submit bugs, use the Sourceforge Bug Forum:
+
+ http://sourceforge.net/tracker/?group_id=11118&atid=111118.
+
+Make sure that the bug has not already been submitted. Please try to verify
+that it is a Privoxy bug, and not a browser or site bug first. If you are using
+your own custom configuration, please try the stock configs to see if the
+problem is a configuration related bug. And if not using the latest development
+snapshot, please try the latest one. Or even better, CVS sources. Please be
+sure to include the Privoxy version, platform, browser, any pertinent log data,
+any other relevant details (please be specific) and, if possible, some way to
+reproduce the bug.
+
+-------------------------------------------------------------------------------
+
+8.3. Request new features
+
+To submit ideas on new features, use the Sourceforge feature request forum:
+
+ http://sourceforge.net/tracker/?atid=361118&group_id=11118&func=browse.
+
+-------------------------------------------------------------------------------
+
+8.4. Report ads or other filter problems
+
+You can also send feedback on websites that Privoxy has problems with. Please
+bookmark the following link: "Privoxy - Submit Filter Feedback". Once you surf
+to a page with problems, use the bookmark to send us feedback. We will look
+into the issue as soon as possible.
+
+New, improved default.action files will occasionally be made available based on
+your feedback. These will be announced on the ijbswa-announce list.
+
+-------------------------------------------------------------------------------
+
+8.5. Other
+
+For any other issues, feel free to use the mailing lists:
+
+ http://sourceforge.net/mail/?group_id=11118.
+
+Anyone interested in actively participating in development and related
+discussions can also join the appropriate mailing list. Archives are available,
+too. See the page on Sourceforge.
+
+-------------------------------------------------------------------------------
+
+9. Privoxy Copyright, License and History
+
+Copyright © 2001, 2002 by Privoxy Developers <developers@privoxy.org>
+
+Some source code is based on code Copyright © 1997 by Anonymous Coders and
+Junkbusters, Inc. and licensed under the GNU General Public License.
+
+-------------------------------------------------------------------------------
+
+9.1. License
+
+Privoxy is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License, version 2, as published by the Free
+Software Foundation.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details, which
+is available from the Free Software Foundation, Inc, 59 Temple Place - Suite
+330, Boston, MA 02111-1307, USA.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the
+
+ Free Software
+ Foundation, Inc. 59 Temple Place - Suite 330
+ Boston, MA 02111-1307
+ USA
+
+-------------------------------------------------------------------------------
+
+9.2. History
+
+Privoxy is evolved, and derived from, the Internet Junkbuster, with many
+improvments and enhancements over the original.
+
+Junkbuster was originally written by Anonymous Coders and Junkbusters
+Corporation, and was released as free open-source software under the GNU GPL.
+Stefan Waldherr made many improvements, and started the SourceForge project
+Privoxy to rekindle development. There are now several active developers
+contributing. The last stable release of Junkbuster was v2.0.2, which has now
+grown whiskers ;-).
+
+-------------------------------------------------------------------------------
+
+10. See also
+
+Other references and sites of interest to Privoxy users:
+
+http://www.privoxy.org/, The Privoxy Home page.
+
+http://sourceforge.net/projects/ijbswa, the Project Page for Privoxy on
+Sourceforge.
+
+http://p.p/, access Privoxy from your browser. Alternately, http://
+config.privoxy.org may work in some situations where the first does not.
+
+http://p.p/, and select "Privoxy - Submit Filter Feedback" to submit "misses"
+to the developers.
+
+http://www.junkbusters.com/ht/en/cookies.html
+
+http://www.waldherr.org/junkbuster/
+
+http://privacy.net/analyze/
+
+http://www.squid-cache.org/
+
+