Index: /tags/ipp-1-X/rel-0_06/DataStore/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/.cvsignore	(revision 21994)
@@ -0,0 +1,6 @@
+Build
+META.yml
+Makefile
+Makefile.PL
+_build
+blib
Index: /tags/ipp-1-X/rel-0_06/DataStore/Build.PL
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/Build.PL	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/Build.PL	(revision 21994)
@@ -0,0 +1,37 @@
+use Module::Build;
+# See perldoc Module::Build for details of how this works
+
+Module::Build->new(
+    module_name         => 'DataStore',
+    dist_version_from   => 'lib/DataStore.pm',
+    author              => 'Joshua Hoblitt <jhoblitt@cpan.org>',
+    license             => 'gpl',
+    create_makefile_pl  => 'passthrough',
+    requires            => {
+        'Carp'                  => 0,
+        'Data::Validate::URI'   => '0.01',
+        'Digest::MD5::File'     => '0.03',
+        'File::Basename'        => 0,
+        'File::Temp'            => '0.16',
+        'File::stat'            => 0,
+        'LWP::UserAgent'        => 0,
+        'Params::Validate'      => '0.77',
+        'YAML'                  => '0.58',
+    },
+    build_requires      => {
+        'CGI'                   => '3',
+        'Net::HTTPServer'       => '1.1.1',
+        'Test::Cmd'             => '1.05',
+        'Test::More'            => 0,
+        'Test::Warn'            => '0.08',
+    },
+    recommends          => {
+        'Test::Distribution'    => '1.22',
+    },
+    script_files        => [qw(
+        scripts/dsget
+        scripts/dsproductls
+        scripts/dsleech
+        scripts/dsfilesetls
+    )],
+)->create_build_script;
Index: /tags/ipp-1-X/rel-0_06/DataStore/Changes
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/Changes	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/Changes	(revision 21994)
@@ -0,0 +1,38 @@
+Revision history for Perl module DataStore
+
+0.06 Thu Feb  1 13:57:56 HST 2007
+    - fix dsleech to handle valid but empty filesets
+    - change dsfilesetls to output "extra" fields
+    - add --overwrite option to dsleech
+    - distcheck fixes
+
+0.05 Fri Sep  1 11:28:13 HST 2006
+    - add --recall, --remember, & rcfile support to dsleech
+    - add a dep on YAML 0.58
+
+0.04 Thu Aug 31 13:01:59 HST 2006
+    - allow upper & lower case characters in DataStore fields
+    - change from lower to upper case all fileset types
+    - change DataStore::File to always return a DataStore::Response (even when
+      there is a problem with the retrieved file)
+    - add dsleech script
+
+0.03 Wed Aug 30 12:46:00 HST 2006
+    - fix a bug in dsproductls where ->status was being called on a
+      DataStore::Response instead of ->status_line
+    - Added a Root object and associated Product::Parser to query the root of
+      the datastore.
+    - The 'is_success' field in a Response now gets its value carried over from
+      the HTTP::Response as intended.
+    - The 'data' field in a Response can now be undef to indicate that no
+      records were parsed.
+    - Root::request, Product::request, FileSet::request now always return a
+      Response object.
+    - FileSets and Files will now have any additional non-standard fields
+      parsed into the @extra array.
+    - Updated tests.
+
+0.01 Thu Feb 23 13:55:57 2006
+    - original version; created by ExtUtils::ModuleMaker 0.44
+
+
Index: /tags/ipp-1-X/rel-0_06/DataStore/LICENSE
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/LICENSE	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/LICENSE	(revision 21994)
@@ -0,0 +1,260 @@
+The General Public License (GPL)
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave,
+Cambridge, MA 02139, USA. Everyone is permitted to copy and distribute
+verbatim copies of this license document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it. By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to most of
+the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom
+to distribute copies of free software (and charge for this service if you wish), that
+you receive source code or can get it if you want it, that you can change the
+software or use pieces of it in new free programs; and that you know you can do
+these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights. These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a
+fee, you must give the recipients all the rights that you have. You must make
+sure that they, too, receive or can get the source code. And you must show
+them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer
+you this license which gives you legal permission to copy, distribute and/or
+modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced by
+others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish
+to avoid the danger that redistributors of a free program will individually obtain
+patent licenses, in effect making the program proprietary. To prevent this, we
+have made it clear that any patent must be licensed for everyone's free use or
+not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+GNU GENERAL PUBLIC LICENSE
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND
+MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or translated
+into another language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope. The act of running the Program is not
+restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program). Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as
+you receive it, in any medium, provided that you conspicuously and appropriately
+publish on each copy an appropriate copyright notice and disclaimer of warranty;
+keep intact all the notices that refer to this License and to the absence of any
+warranty; and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at
+your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus
+forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you also
+meet all of these conditions:
+
+a) You must cause the modified files to carry prominent notices stating that you
+changed the files and the date of any change.
+
+b) You must cause any work that you distribute or publish, that in whole or in
+part contains or is derived from the Program or any part thereof, to be licensed
+as a whole at no charge to all third parties under the terms of this License.
+
+c) If the modified program normally reads commands interactively when run, you
+must cause it, when started running for such interactive use in the most ordinary
+way, to print or display an announcement including an appropriate copyright
+notice and a notice that there is no warranty (or else, saying that you provide a
+warranty) and that users may redistribute the program under these conditions,
+and telling the user how to view a copy of this License. (Exception: if the
+Program itself is interactive but does not normally print such an announcement,
+your work based on the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Program, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to
+work written entirely by you; rather, the intent is to exercise the right to control
+the distribution of derivative or collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and 2
+above provided that you also do one of the following:
+
+a) Accompany it with the complete corresponding machine-readable source
+code, which must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange; or,
+
+b) Accompany it with a written offer, valid for at least three years, to give any
+third party, for a charge no more than your cost of physically performing source
+distribution, a complete machine-readable copy of the corresponding source
+code, to be distributed under the terms of Sections 1 and 2 above on a medium
+customarily used for software interchange; or,
+
+c) Accompany it with the information you received as to the offer to distribute
+corresponding source code. (This alternative is allowed only for noncommercial
+distribution and only if you received the program in object code or executable
+form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all the
+source code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+executable. However, as a special exception, the source code distributed need
+not include anything that is normally distributed (in either source or binary form)
+with the major components (compiler, kernel, and so on) of the operating system
+on which the executable runs, unless that component itself accompanies the
+executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source
+code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so long
+as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Program
+or its derivative works. These actions are prohibited by law if you do not accept
+this License. Therefore, by modifying or distributing the Program (or any work
+based on the Program), you indicate your acceptance of this License to do so,
+and all its terms and conditions for copying, distributing or modifying the
+Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor to copy,
+distribute or modify the Program subject to these terms and conditions. You
+may not impose any further restrictions on the recipients' exercise of the rights
+granted herein. You are not responsible for enforcing compliance by third parties
+to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent infringement
+or for any other reason (not limited to patent issues), conditions are imposed on
+you (whether by court order, agreement or otherwise) that contradict the
+conditions of this License, they do not excuse you from the conditions of this
+License. If you cannot distribute so as to satisfy simultaneously your obligations
+under this License and any other pertinent obligations, then as a consequence
+you may not distribute the Program at all. For example, if a patent license would
+not permit royalty-free redistribution of the Program by all those who receive
+copies directly or indirectly through you, then the only way you could satisfy
+both it and this License would be to refrain entirely from distribution of the
+Program.
+
+If any portion of this section is held invalid or unenforceable under any particular
+circumstance, the balance of the section is intended to apply and the section as
+a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other
+property right claims or to contest validity of any such claims; this section has
+the sole purpose of protecting the integrity of the free software distribution
+system, which is implemented by public license practices. Many people have
+made generous contributions to the wide range of software distributed through
+that system in reliance on consistent application of that system; it is up to the
+author/donor to decide if he or she is willing to distribute software through any
+other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain countries
+either by patents or by copyrighted interfaces, the original copyright holder who
+places the Program under this License may add an explicit geographical
+distribution limitation excluding those countries, so that distribution is permitted
+only in or among countries not thus excluded. In such case, this License
+incorporates the limitation as if written in the body of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the
+General Public License from time to time. Such new versions will be similar in
+spirit to the present version, but may differ in detail to address new problems or
+concerns.
+
+Each version is given a distinguishing version number. If the Program specifies a
+version number of this License which applies to it and "any later version", you
+have the option of following the terms and conditions either of that version or of
+any later version published by the Free Software Foundation. If the Program does
+not specify a version number of this License, you may choose any version ever
+published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of all
+derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS
+NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
+COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
+"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR
+IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED
+TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY
+WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS
+PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
+(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
+OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
Index: /tags/ipp-1-X/rel-0_06/DataStore/MANIFEST
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/MANIFEST	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/MANIFEST	(revision 21994)
@@ -0,0 +1,36 @@
+Build.PL
+Changes
+LICENSE
+MANIFEST
+META.yml
+Makefile.PL
+README
+Todo
+lib/DataStore.pm
+lib/DataStore/File.pm
+lib/DataStore/File/Parser.pm
+lib/DataStore/FileSet.pm
+lib/DataStore/FileSet/Parser.pm
+lib/DataStore/Product.pm
+lib/DataStore/Product/Parser.pm
+lib/DataStore/Record.pm
+lib/DataStore/Response.pm
+lib/DataStore/Root.pm
+lib/DataStore/Utils.pm
+scripts/dsfilesetls
+scripts/dsget
+scripts/dsleech
+scripts/dsproductls
+t/00_distribution.t
+t/01_load.t
+t/02_fileset_parse.t
+t/03_file_parse.t
+t/04_record.t
+t/05_product.t
+t/06_fileset.t
+t/07_file.t
+t/08_response.t
+t/09_datastore.t
+t/10_dsget.t
+t/11_dsproductls.t
+t/12_dsfilesetls.t
Index: /tags/ipp-1-X/rel-0_06/DataStore/README
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/README	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/README	(revision 21994)
@@ -0,0 +1,15 @@
+pod2text DataStore.pm > README
+
+If this is still here it means the programmer was too lazy to create the readme file.
+
+You can create it now by using the command shown above from this directory.
+
+At the very least you should be able to use this set of instructions
+to install the module...
+
+perl Build.PL
+./Build
+./Build test
+./Build install
+
+If you are on a windows box you should use 'nmake' rather than 'make'.
Index: /tags/ipp-1-X/rel-0_06/DataStore/Todo
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/Todo	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/Todo	(revision 21994)
@@ -0,0 +1,5 @@
+TODO list for Perl module DataStore
+
+- Nothing yet
+
+
Index: /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore.pm	(revision 21994)
@@ -0,0 +1,159 @@
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: DataStore.pm,v 1.9 2007-01-25 03:39:31 jhoblitt Exp $
+
+package DataStore;
+
+use strict;
+use warnings;
+
+use vars qw($VERSION);
+$VERSION = '0.06';
+
+=pod
+
+=head1 NAME
+
+DataStore - client interface to a DataStore server
+
+=head1 SYNOPSIS
+
+    use DataStore;
+
+    # equivalent to:
+
+    use DataStore::File::Parser;
+    use DataStore::File;
+    use DataStore::FileSet::Parser;
+    use DataStore::FileSet;
+    use DataStore::Product;
+    use DataStore::Response;
+    use DataStore::Utils;
+
+=head1 DESCRIPTION
+
+This is a convenience module so that that don't have to individualy load (C<use
+...;>) all of the common DataStore inteface modules.  Please see the POD of the
+individual modules for usage information.  If this is your browsing of the
+documentation you may want to start with L<DataStore::Product>.
+
+=head1 USAGE
+
+=head2 Import Parameters
+
+This module accepts no arguments to it's C<import> method and exports no
+I<symbols>.
+
+=head2 Methods
+
+None.
+
+=head1 EXAMPLE PROGRAM
+
+    #!/usr/bin/perl
+
+    use strict;
+    use warnings;
+
+    # loads DataStore::*
+    use DataStore;
+
+    my $dsp = DataStore::Product->new(
+        uri => 'http://example.org/productid/',
+        last_fileset => 'foobarbaz',
+    );
+
+    # returns a DataStore::Response object
+    my $response = $dsp->request;
+
+    unless ($response->is_success) {
+        die $response->status;
+    }
+
+    # arrayref of DataStore::FileSet objects
+    my $filesets = $response->data;
+
+    # the query could be a success but still return no filesets
+    unless ($filesets) {
+        warn "no filesets returned";
+        exit(0);
+    }
+
+    # returns a DataStore::Response object
+    my $response2 = @$filesets[0]->request;
+
+    unless ($response2->is_success) {
+        die $response2->status;
+    }
+
+    # arrayref of DataStore::File objects
+    my $files = $response->data;
+
+    # the query could be a success but still return no files (is that legal?)
+    unless (@$files) {
+        warn "no files returned";
+        exit(0);
+    }
+
+    # requires a filename
+    my $response3 = @$files[0]->request( filename => '/dev/null' );
+    unless ($response3->is_success) {
+        warn $response3->status;
+        die;
+    }
+
+    # $response3->data is '/dev/null'
+
+=cut
+
+use DataStore::File::Parser;
+use DataStore::File;
+use DataStore::FileSet::Parser;
+use DataStore::FileSet;
+use DataStore::Product::Parser;
+use DataStore::Product;
+use DataStore::Root;
+use DataStore::Response;
+use DataStore::Utils;
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2006  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the LICENSE file included with
+this module, or in the L<perlgpl> Pod as supplied with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<DataStore::File::Parser>, L<DataStore::File>, L<DataStore::FileSet::Parser>, L<DataStore::FileSet>, L<DataStore::Product>, L<DataStore::Response>
+
+=cut
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/File.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/File.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/File.pm	(revision 21994)
@@ -0,0 +1,283 @@
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: File.pm,v 1.14 2006-08-31 22:58:34 jhoblitt Exp $
+
+package DataStore::File;
+
+use strict;
+use warnings;
+
+use vars qw($VERSION);
+$VERSION = '0.03';
+
+use base qw( DataStore::Record );
+
+use Carp qw( carp );
+use DataStore::Response;
+use DataStore::Utils qw( $STD_FIELD $BYTE_FIELD $MD5_FIELD %KNOWN_FILE_TYPES );
+use Digest::MD5::File qw( file_md5_hex );
+use File::stat;
+use Params::Validate qw( validate SCALAR ARRAYREF );
+
+use vars qw( @BASE_FIELDS );
+
+@BASE_FIELDS = qw( fileid bytes md5sum type extra );
+
+__PACKAGE__->mk_accessors(@BASE_FIELDS);
+
+=pod
+
+=head1 NAME
+
+DataStore::File - represents a DataStore File
+
+=head1 SYNOPSIS
+
+    use DataStore::file;
+
+    my $dsf = DateStore::File->new(
+        uri         => 'http://example.org/foo',
+        fileid      => '12buckelyourshoe',
+        bytes       => 12345,
+        md5sum      => 'fe6a2b6564c0d4cfb3bbf1db813824ba',
+        type        => 'foo',
+    );
+
+    my $uri     = $dsf->uri;
+    my fileid   = $dsf->fileid;
+    my $bytes   = $dsf-bytes;
+    my $md5sum  = $dsf->md5sum;
+    my $type    = $dsf-type;
+    my DataStore::Response $response = $dsf->request( filename => "/foo/bar" );
+
+=head1 DESCRIPTION
+
+This class I<isa> L<DataStore::Record>
+
+=head1 USAGE
+
+=head2 Import Parameters
+
+This module accepts no arguments to it's C<import> method and exports no
+I<symbols>.
+
+=head2 Methods
+
+=head3 Constructors
+
+=over 4
+
+=item * C<new()>
+
+Basic constructor.
+
+    my $dsf = DateStore::File->new(
+        uri         => 'http://example.org/foo',
+        fileid      => '12buckelyourshoe',
+        bytes       => 12345,
+        md5sum      => 'fe6a2b6564c0d4cfb3bbf1db813824ba',
+        type        => 'foo',
+    );
+
+Accepts a mandatory hash and returns a L<DataStore::Product> object.
+
+=over 4
+
+=item * uri
+
+A valid I<HTTP> URI as a string.  I<No trailing slash is allowed.>
+
+=item * fileid
+
+The FIle ID as a string.
+
+This key is optional.
+
+=item * bytes
+
+The size of the file as an integer number of bytes.
+
+This key is optional.
+
+=item * md5sum
+
+The hex encoded md5 checksum of the file.
+
+This key is optional.
+
+=item * type
+
+The type of file as a string.
+
+This key is optional.
+
+=back
+
+=cut
+
+sub new
+{
+    my $class = shift;
+
+    # validates uri, doesn't check other params
+    my $self = $class->SUPER::new(@_);
+
+    validate(@_,
+        {
+            uri     => {
+                type        => SCALAR,
+                callbacks   => {
+                    'is valid uri filename' => sub { $_[0] !~ m|/$| },
+                },
+            },
+            fileid  => {
+                type        => SCALAR,
+                regex       => $STD_FIELD,
+                optional    => 1,
+            },
+            bytes   => {
+                type        => SCALAR,
+                regex       => $BYTE_FIELD,
+                optional    => 1,
+            },
+            md5sum  => {
+                type        => SCALAR,
+                regex       => $MD5_FIELD,
+                optional    => 1,
+            },
+            type    => {
+                type        => SCALAR,
+                callbacks   => {
+                    'is valid type' =>
+                        sub { exists $KNOWN_FILE_TYPES{$_[0]} },
+                },
+                optional    => 1,
+            },
+            extra   => {
+                type        => SCALAR | ARRAYREF,
+                optional    => 1,
+            },
+        },
+    );
+
+    return $self;
+}
+
+=back
+
+=head3 Object Methods
+
+=over 4
+
+=item * C<uri()>
+
+Basic accessor.
+
+=item * C<fileid()>
+
+Basic accessor.
+
+=item * C<bytes()>
+
+Basic accessor.
+
+=item * C<md5sum()>
+
+Basic accessor.
+
+=item * C<type()>
+
+Basic accessor.
+
+=item * C<request()>
+
+Retrieves and processes the File listing pointed to by the L<uri> of this
+object.
+
+XXX writing the file into memory or to a filehandle will be implemented upon
+request.
+
+    my $response = $dsf->request( filename => "/foo/bar" );
+
+Accepts a mandatory hash and returns a L<DataStore::Response> object.
+
+=over 4
+
+=item * filename
+
+The filename/path to save the file to disk as.  It is the user's responsibility
+to make sure that this is a valid filename/path.
+
+=back
+
+=cut
+
+sub request 
+{
+    my $self = shift;
+
+    my %p = validate(@_,
+        {
+            filename    => {
+                type        => SCALAR,
+                regex       => qr/\S+/, # string with at least 1 non WS char
+            },
+        },
+    );
+
+    # make request
+    my $ua = LWP::UserAgent->new;
+    my $request = HTTP::Request->new(GET => $self->uri);
+    my $filename = $p{filename};
+    my $response = $ua->request($request, $filename);
+
+    if ($response->is_success) {
+        # check size
+        if (defined $self->bytes) {
+            my $size = stat($filename)->size;
+            if (! $self->bytes == $size) {
+                unlink $filename;
+                carp "uri: ", $self->uri,
+                     " - expected size: ", $self->bytes,
+                     " got: ", $size;
+                # set the filename to undef to indicate an error
+                $filename = undef;
+                last;
+            }
+        }
+
+        if (defined $self->md5sum) {
+            my $md5 = file_md5_hex($filename);
+            if (! $self->md5sum eq $md5) {
+                unlink $filename;
+                carp "uri: ", $self->uri,
+                     " - expected md5: ", $self->md5sum,
+                     " got: ", $md5;
+                # set the filename to undef to indicate an error
+                $filename = undef;
+                last;
+            }
+        }
+    }
+
+    # return DS::Response object
+    my $dsr = DataStore::Response->new(
+        is_success  => $response->is_success,
+        code        => $response->code,
+        status_line => $response->status_line,
+        data        => $filename,
+        request     => $self,
+    );
+}
+
+=back
+
+=head1 SEE ALSO
+
+L<DataStore::Response>
+
+=cut
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/File/Parser.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/File/Parser.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/File/Parser.pm	(revision 21994)
@@ -0,0 +1,221 @@
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: Parser.pm,v 1.11 2006-07-22 01:17:33 smalle Exp $
+
+package DataStore::File::Parser;
+
+use strict;
+use warnings;
+
+use vars qw($VERSION);
+$VERSION = '0.01';
+
+use base qw( Class::Accessor::Fast );
+
+use Carp qw( carp );
+use Data::Validate::URI qw( is_uri ); 
+use DataStore::Utils qw( $STD_FIELD $BYTE_FIELD $MD5_FIELD %KNOWN_FILE_TYPES );
+use DataStore::File;
+use Params::Validate qw( validate validate_pos SCALAR );
+
+__PACKAGE__->mk_ro_accessors(qw(base_uri));
+
+=pod
+
+=head1 NAME
+
+DataStore::File::Parser - parses the DataStore 'File' list format
+
+=head1 SYNOPSIS
+
+    use DataStore::File::Parser;
+
+    my $parser = DataStore::File::Parser->new(
+        base_uri => 'http://example.org/',
+    );
+
+    my @data = $parser->parse($str);
+        or
+    my $data = $parser->parse($str);
+
+
+=head1 DESCRIPTION
+
+This class parses a DataStore listing of I<File>s into an array of L<DataStore::File> objects.
+
+=head1 USAGE
+
+=head2 Import Parameters
+
+This module accepts no arguments to it's C<import> method and exports no
+I<symbols>.
+
+=head2 Methods
+
+=head3 Constructors
+
+=over 4
+
+=item * C<new()>
+
+Basic constructor.
+
+    my $parser = DataStore::File::Parser->new(
+        base_uri => 'http://example.org/',
+    );
+
+Accepts an optional hash and returns a L<DataStore::FileSet::Parser> object.
+
+=over 4
+
+=item * base_uri
+
+The base of the URI to set in the created L<DataStore::File> objects.
+
+This key is optional and defaults to C<http://example.org/>.
+
+=back
+
+=cut
+
+sub new
+{
+    my $class = shift;
+
+    my %p = validate(@_,
+        {
+            base_uri => {
+                type        => SCALAR,
+                callbacks   => {
+                    'is valid http uri' =>
+                        sub { is_uri($_[0]) and $_[0] =~ /^http:/ },
+                     'uri ends with /'   => sub { $_[0] =~ m|/$| },
+                },
+                default =>  'http://example.org/',
+            },
+        },
+    );
+
+    my $self = bless \%p, ref $class || $class;
+
+    return $self;
+}
+
+
+=back
+
+=head3 Object Methods
+
+=over 4
+
+=item * C<base_uri()>
+
+Basic accessor.
+
+=item * C<parse()>
+
+Accepts a string and returns a list in list context or an arrayref is scalar
+context.  An empty list or undef is returned if the string contained no rows.
+
+=cut
+
+sub parse
+{
+    my $self = shift;
+
+    my ($doc) = validate_pos(@_,
+        {
+            type    => SCALAR,
+            regex   => qr/\S+/, # string with at least 1 non WS char
+        }
+    );
+
+    my @data;
+    my $lineno = 1;
+LINE: foreach my $line (split /\n/, $doc) {
+        # blank lines
+        next LINE if $line =~ /^\s*$/;
+
+        # comment lines   
+        next LINE if $line =~ /^\s*\#/;
+
+        my @fields = split /\|/, $line;
+
+        # at least fileid, bytes, md5sum, and type fields are required
+        if (scalar @fields < 4) {
+            carp "line $lineno: not enough fields: $line";
+            next LINE;
+        }
+
+        foreach my $field (@fields) {
+            # fields are not allowed to contain \#
+            if ($field =~ /\#/) {
+                carp "line $lineno: field $field: contains #: $line";
+                next LINE;
+            }
+
+            # strip leading and trailing whitespace
+            $field =~ s/^\s+//;
+            $field =~ s/\s+$//;
+        }
+
+        my ($fileid, $bytes, $md5sum, $type) = @fields;
+
+        # validate format of fileid and type
+        foreach my $field ($fileid, $type) {
+            unless ($field =~ $STD_FIELD) {
+                carp "line $lineno: field $field:"
+                   . " does not conform to $STD_FIELD: $line";
+                next LINE;
+            }
+        }
+
+        # validate format of bytes
+        unless ($bytes =~ $BYTE_FIELD) {
+            carp "line $lineno: field $bytes:"
+               . " does not conform to $BYTE_FIELD: $line";
+            next LINE;
+        }
+
+        # validate format of md5sum, hex encoded
+        unless ($md5sum =~ $MD5_FIELD) {
+            carp "line $lineno: field $md5sum:"
+               . " does not conform to $MD5_FIELD: $line";
+            next LINE;
+        }
+
+        unless (exists $KNOWN_FILE_TYPES{$type}) {
+            carp "line $lineno: type $type unknown: $line";
+            next LINE;
+        }
+
+	my @extra = @fields[4 .. $#fields] if $#fields >= 4;
+
+        # fifo  
+        push @data, DataStore::File->new({
+            fileid  => $fileid,
+            bytes   => $bytes,
+            md5sum  => $md5sum,
+            type    => $type,
+            extra   => \@extra, 
+            uri     => $self->base_uri . $fileid,
+        });
+    } continue {
+        $lineno++;
+    }
+
+    return unless @data;
+    return wantarray ? @data : \@data;
+}
+
+=back
+
+=head1 SEE ALSO
+
+L<DataStore::File>, L<DataStore::FileSet::Parser>
+
+=cut
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/FileSet.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/FileSet.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/FileSet.pm	(revision 21994)
@@ -0,0 +1,224 @@
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: FileSet.pm,v 1.11 2006-07-22 01:17:33 smalle Exp $
+
+package DataStore::FileSet;
+
+use strict;
+use warnings;
+
+use vars qw($VERSION);
+$VERSION = '0.02';
+
+use base qw( DataStore::Record );
+
+use Carp qw( carp );
+use DataStore::File::Parser;
+use DataStore::Response;
+use DataStore::Utils qw( $STD_FIELD $TIME_FIELD %KNOWN_FILESET_TYPES );
+use LWP::UserAgent;
+use Params::Validate qw( validate SCALAR ARRAYREF );
+
+use vars qw( @BASE_FIELDS );
+
+@BASE_FIELDS = qw( fileset datetime type extra );
+
+__PACKAGE__->mk_accessors(@BASE_FIELDS);
+
+=pod
+
+=head1 NAME
+
+DataStore::FileSet - represents a DataStore FileSet 
+
+=head1 SYNOPSIS
+
+    use DataStore::FileSet;
+
+    my $dsfs = DateStore::FileSet->new(
+        uri         => 'http://example.org/',
+        fileset     => '12buckelyourshoe',
+        datetime    => '2042-01-01T00:00:00Z',
+        type        => 'foo',
+    );
+
+    my $uri         = $dsfs->uri;
+    my $fileset     = $dsfs->fileset;
+    my $datatime    = $dsfs->datetime;
+    my $type        = $dsfs->type;
+    my DataStore::Response $response = $dsfs->request;
+
+=head1 DESCRIPTION
+
+This class I<isa> L<DataStore::Record>
+
+=head1 USAGE
+
+=head2 Import Parameters
+
+This module accepts no arguments to it's C<import> method and exports no
+I<symbols>.
+
+=head2 Methods
+
+=head3 Constructors
+
+=over 4
+
+=item * C<new()>
+
+Basic constructor.
+
+    my $dsfs = DateStore::FileSet->new(
+        uri         => 'http://example.org/',
+        fileset     => '12buckelyourshoe',
+        datetime    => '2042-01-01T00:00:00Z',
+        type        => 'foo',
+    );
+
+Accepts a mandatory hash and returns a L<DataStore::FileSet> object.
+
+=over 4
+
+=item * uri
+
+A valid I<HTTP> URI as a string.  I<A trailing slash is required.>
+
+=item * fileset
+
+The FileSet ID as a string.
+
+This key is optional.
+
+=item * datetime
+
+The time and date as a string.
+
+This key is optional.
+
+=item * type
+
+The I<type> of record as a string.
+
+This key is optional.
+
+=back
+
+=cut
+
+sub new
+{
+    my $class = shift;
+
+    # validates uri, doesn't check other params
+    my $self = $class->SUPER::new(@_);
+
+    validate(@_,
+        {
+            uri         => {
+                type        => SCALAR,
+                callbacks   => {
+                    'is valid uri dirname'   => sub { $_[0] =~ m|/$| },
+                }
+            },
+            fileset     => {
+                type        => SCALAR,
+                regex       => $STD_FIELD,
+                optional    => 1,
+            },
+            datetime    => {
+                type        => SCALAR,
+                regex       => $TIME_FIELD,
+                optional    => 1,
+            },
+            type        => {
+                type        => SCALAR,
+                callbacks   => {
+                    'is valid type' => 
+                        sub { exists $KNOWN_FILESET_TYPES{$_[0]} },
+                },
+                optional    => 1,
+            },
+            extra       => {
+                type        => SCALAR | ARRAYREF,
+                optional    => 1,
+            },
+        },
+    );
+
+    return $self;
+}
+
+=back
+
+=head3 Object Methods
+
+=over 4
+
+=item * C<uri()>
+
+Basic accessor.
+
+=item * C<fileset()>
+
+Basic accessor.
+
+=item * C<datetime()>
+
+Basic accessor.
+
+=item * C<type()>
+
+Basic accessor.
+
+=item * C<request()>
+
+Retrieves and processes the File listing pointed to by the L<uri> of this
+object.
+
+Accepts no parameters and returns a L<DataStore::Response> object.
+
+=cut
+
+sub request 
+{
+    my $self = shift;
+
+    # no params
+    validate(@_, {});
+
+    # make request
+    my $ua = LWP::UserAgent->new;
+    my $request = HTTP::Request->new(GET => $self->uri);
+    my $response = $ua->request($request);
+
+    my $data;
+
+    if ($response->is_success) {
+        # parse document
+        my $parser = DataStore::File::Parser->new(base_uri => $self->uri);
+
+        $data = $parser->parse($response->content);
+    }
+
+    # return DS::Response object
+    my $dsr = DataStore::Response->new(
+        is_success  => $response->is_success,
+        code        => $response->code,
+        status_line => $response->status_line,
+        data        => $data,
+        request     => $self,
+    );
+}
+
+=back
+
+=head1 SEE ALSO
+
+L<DataStore::Response>
+
+=cut
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/FileSet/Parser.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/FileSet/Parser.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/FileSet/Parser.pm	(revision 21994)
@@ -0,0 +1,211 @@
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: Parser.pm,v 1.13 2006-07-22 01:17:33 smalle Exp $
+
+package DataStore::FileSet::Parser;
+
+use strict;
+use warnings;
+
+use vars qw($VERSION);
+$VERSION = '0.01';
+
+use base qw( Class::Accessor::Fast );
+
+use Carp qw( carp );
+use Data::Validate::URI qw( is_uri );
+use DataStore::FileSet;
+use DataStore::Utils qw( $STD_FIELD $TIME_FIELD %KNOWN_FILESET_TYPES );
+use Params::Validate qw( validate validate_pos SCALAR);
+
+__PACKAGE__->mk_ro_accessors(qw(base_uri));
+
+=pod
+
+=head1 NAME
+
+DataStore::FileSet::Parser - parses the DataStore 'FileSet' list format
+
+=head1 SYNOPSIS
+
+    use DataStore::FileSet::Parser;
+
+    my $parser = DataStore::FileSet::Parser->new(
+        base_uri => 'http://example.org/',
+    );
+
+    my @data = $parser->parse($str);
+        or
+    my $data = $parser->parse($str);
+
+=head1 DESCRIPTION
+
+This class parses a DataStore listing of I<FileSet>s into an array of L<DataStore::FileSet> objects.
+
+=head1 USAGE
+
+=head2 Import Parameters
+
+This module accepts no arguments to it's C<import> method and exports no
+I<symbols>.
+
+=head2 Methods
+
+=head3 Constructors
+
+=over 4
+
+=item * C<new()>
+
+Basic constructor.
+
+    my $parser = DataStore::FileSet::Parser->new(
+        base_uri => 'http://example.org/',
+    );
+
+Accepts an optional hash and returns a L<DataStore::FileSet::Parser> object.
+
+=over 4
+
+=item * base_uri
+
+The base of the URI to set in the created L<DataStore::FileSet> objects.
+
+This key is optional and defaults to C<http://example.org/>.
+
+=back
+
+=cut
+
+sub new
+{
+    my $class = shift;
+
+    my %p = validate(@_,
+        {
+            base_uri => {
+                type        => SCALAR,
+                callbacks   => {
+                    'is valid http uri' =>
+                        sub { is_uri($_[0]) and $_[0] =~ /^http:/ },
+                    'uri ends with /'   => sub { $_[0] =~ m|/$| },
+                },
+                default =>  'http://example.org/',
+            },
+        },
+    );
+
+    my $self = bless \%p, ref $class || $class;
+
+    return $self;
+}
+
+=back
+
+=head3 Object Methods
+
+=over 4
+
+=item * C<base_uri()>
+
+Basic accessor.
+
+=item * C<parse()>
+
+Accepts a string and returns a list in list context or an arrayref is scalar
+context.  An empty list or undef is returned if the string contained no rows.
+
+=cut
+
+sub parse
+{
+    my $self = shift;
+
+    my ($doc) = validate_pos(@_,
+        {
+            type    => SCALAR,
+            regex   => qr/\S+/, # string with at least 1 non WS char
+        }
+    );
+
+    my @data;
+    my $lineno = 1;
+LINE: foreach my $line (split /\n/, $doc) {
+        # blank lines
+        next LINE if $line =~ /^\s*$/;
+
+        # comment lines   
+        next LINE if $line =~ /^\s*\#/;
+
+        my @fields = split /\|/, $line;
+
+        # at least fileset, datatime, and type fields are required
+        if (scalar @fields < 3) {
+            carp "line $lineno: not enough fields: $line";
+            next LINE;
+        }
+
+        foreach my $field (@fields) {
+            # fields are not allowed to contain #
+            if ($field =~ /\#/) {
+                carp "line $lineno: field $field: contains #: $line";
+                next LINE;
+            }
+
+            # strip leading and trailing whitespace
+            $field =~ s/^\s+//;
+            $field =~ s/\s+$//;
+        }
+
+        my ($fileset, $datetime, $type) = @fields;
+
+        # validate format of fileset and type
+        foreach my $field ($fileset, $type) {
+            unless ($field =~ $STD_FIELD) {
+                carp "line $lineno: field $field:"
+                   . " does not conform to $STD_FIELD: $line";
+                next LINE;
+            }
+        }
+
+        # validate format of datetime
+        unless ($datetime =~ $TIME_FIELD) {
+            carp "line $lineno: field $datetime:"
+               . " does not conform to $TIME_FIELD";
+            next LINE;
+        }
+
+        unless (exists $KNOWN_FILESET_TYPES{$type}) {
+            carp "line $lineno: type $type unknown: $line";
+            next LINE;
+        } 
+
+        my @extra = @fields[3 .. $#fields] if $#fields >= 3;
+
+        # fifo
+        push @data, DataStore::FileSet->new({
+            fileset     => $fileset,
+            datetime    => $datetime,
+            type        => $type,
+            extra       => \@extra, 
+            uri         => $self->base_uri . $fileset . '/',
+        });
+    } continue {
+        $lineno++;
+    }
+
+    return unless @data;
+    return wantarray ? @data : \@data;
+}
+
+=back
+
+=head1 SEE ALSO
+
+L<DataStore::FileSet>, L<DataStore::File:Parser>
+
+=cut
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Product.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Product.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Product.pm	(revision 21994)
@@ -0,0 +1,212 @@
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: Product.pm,v 1.8 2006-07-22 01:17:33 smalle Exp $
+
+package DataStore::Product;
+
+use strict;
+use warnings;
+
+use vars qw($VERSION);
+$VERSION = '0.01';
+
+use base qw( DataStore::Record );
+
+use Carp qw( carp );
+use DataStore::FileSet::Parser;
+use DataStore::Record;
+use DataStore::Response;
+use DataStore::Utils qw( $STD_FIELD $TIME_FIELD %KNOWN_PRODUCT_TYPES );
+use LWP::UserAgent;
+use Params::Validate qw( validate SCALAR);
+
+use vars qw( @BASE_FIELDS );
+
+@BASE_FIELDS = qw( product last_fileset last_datetime type desc );
+
+__PACKAGE__->mk_ro_accessors(@BASE_FIELDS);
+
+=pod
+
+=head1 NAME
+
+DataStore::Product - represents a DataStore Product ID
+
+=head1 SYNOPSIS
+
+    use DataStore::Product;
+
+    my $dsp = DataStore::Product->new(
+        uri             => 'http://example.com/productid/',
+        last_fileset    => 'foobar',
+    );
+
+    my $uri     = $dsp->uri;
+    my $fileset = $dsp_fileset;
+    my DataStore::Response $response = $dsp->request;
+
+=head1 DESCRIPTION
+
+This class I<isa> L<DataStore::Record>
+
+=head1 USAGE
+
+=head2 Import Parameters
+
+This module accepts no arguments to it's C<import> method and exports no
+I<symbols>.
+
+=head2 Methods
+
+=head3 Constructors
+
+=over 4
+
+=item * C<new()>
+
+Basic constructor.
+
+    my $dsp = DataStore::Product->new(
+        uri             => 'http://example.com/productid/',
+        last_fileset    => 'foobar',
+    );
+
+Accepts a mandatory hash and returns a L<DataStore::Product> object.
+
+=over 4
+
+=item * uri
+
+A valid I<HTTP> URI as a string.  I<A trailing slash is required.>
+
+=item * last_fileset
+
+The last FileSet ID that was requested as a string.
+
+This key is optional.
+
+=back
+
+=cut
+
+sub new
+{
+    my $class = shift;
+
+    # validates uri, doesn't check other params
+    my $self = $class->SUPER::new(@_);
+
+    validate(@_,
+        {
+            uri             => {
+                type        => SCALAR,
+                callbacks   => {
+                    'is valid uri dirname'   => sub { $_[0] =~ m|/$| },
+                }
+            },
+            product         => {
+                type        => SCALAR,
+                optional    => 1,
+            },
+            last_fileset    => { 
+                type        => SCALAR,
+                callbacks   => {
+                    'is valid fileset ID' => sub { $_[0] =~ $STD_FIELD },
+                },
+                optional    => 1,
+            },
+            last_datetime    => {
+                type        => SCALAR,
+                regex       => $TIME_FIELD,
+                optional    => 1,
+            },
+            type        => {
+                type        => SCALAR,
+                callbacks   => {
+                    'is valid type' =>
+                        sub { exists $KNOWN_PRODUCT_TYPES{$_[0]} },
+                },
+                optional    => 1,
+            },
+            desc        => {
+                 type       => SCALAR,
+                 optional   => 1,
+            },
+        },
+    );
+
+    return $self;
+}
+
+=back
+
+=head3 Object Methods
+
+=over 4
+
+=item * C<uri()>
+
+Basic accessor.
+
+=item * C<last_fileset()>
+
+Basic accessor.
+
+=item * C<request()>
+
+Retrieves and processes the FileSet listing pointed to by the L<uri> of this
+object.
+
+Accepts no parameters and returns a L<DataStore::Response> object.
+
+=cut
+
+sub request 
+{
+    my $self = shift;
+
+    # no params
+    validate(@_, {});
+
+    # make request
+    my $ua = LWP::UserAgent->new;
+    my $request;
+    if ($self->last_fileset) {
+        $request = HTTP::Request->new(
+            GET => $self->uri . "?" . $self->last_fileset,
+        );
+    } else {
+        $request = HTTP::Request->new(GET => $self->uri);
+    }
+    my $response = $ua->request($request);
+
+    my $data;
+
+    if ($response->is_success) {
+        # parse document
+        my $parser = DataStore::FileSet::Parser->new(base_uri => $self->uri);
+
+        $data = $parser->parse($response->content);
+    }
+
+    # return DS::Response object
+    my $dsr = DataStore::Response->new(
+        is_success  => $response->is_success,
+        code        => $response->code,
+        status_line => $response->status_line,
+        data        => $data,
+        request     => $self,
+    );
+}
+
+=back
+
+=head1 SEE ALSO
+
+L<DataStore::Response>
+
+=cut
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Product/Parser.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Product/Parser.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Product/Parser.pm	(revision 21994)
@@ -0,0 +1,210 @@
+# Adapted from FileSet/Parser.pm
+#
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: Parser.pm,v 1.1 2006-07-22 01:17:34 smalle Exp $
+
+package DataStore::Product::Parser;
+
+use strict;
+use warnings;
+
+use vars qw($VERSION);
+$VERSION = '0.01';
+
+use base qw( Class::Accessor::Fast );
+
+use Carp qw( carp );
+use Data::Validate::URI qw( is_uri );
+use DataStore::Product;
+use DataStore::Utils qw( $STD_FIELD $TIME_FIELD %KNOWN_PRODUCT_TYPES );
+use Params::Validate qw( validate validate_pos SCALAR);
+
+__PACKAGE__->mk_ro_accessors(qw(base_uri));
+
+=pod
+
+=head1 NAME
+
+DataStore::Product::Parser - parses the DataStore 'Product' list format
+
+=head1 SYNOPSIS
+
+    use DataStore::Product::Parser;
+
+    my $parser = DataStore::Product::Parser->new(
+        base_uri => 'http://example.org/',
+    );
+
+    my @data = $parser->parse($str);
+        or
+    my $data = $parser->parse($str);
+
+=head1 DESCRIPTION
+
+This class parses a root DataStore listing into an array of L<DataStore::Product> objects.
+
+=head1 USAGE
+
+=head2 Import Parameters
+
+This module accepts no arguments to it's C<import> method and exports no
+I<symbols>.
+
+=head2 Methods
+
+=head3 Constructors
+
+=over 4
+
+=item * C<new()>
+
+Basic constructor.
+
+    my $parser = DataStore::Product::Parser->new(
+        base_uri => 'http://example.org/',
+    );
+
+Accepts an optional hash and returns a L<DataStore::Product::Parser> object.
+
+=over 4
+
+=item * base_uri
+
+The base of the URI to set in the created L<DataStore::Product> objects.
+
+This key is optional and defaults to C<http://example.org/>.
+
+=back
+
+=cut
+
+sub new
+{
+    my $class = shift;
+
+    my %p = validate(@_,
+        {
+            base_uri => {
+                type        => SCALAR,
+                callbacks   => {
+                    'is valid http uri' =>
+                        sub { is_uri($_[0]) and $_[0] =~ /^http:/ },
+                    'uri ends with /'   => sub { $_[0] =~ m|/$| },
+                },
+                default =>  'http://example.org/',
+            },
+        },
+    );
+
+    my $self = bless \%p, ref $class || $class;
+
+    return $self;
+}
+
+=back
+
+=head3 Object Methods
+
+=over 4
+
+=item * C<base_uri()>
+
+Basic accessor.
+
+=item * C<parse()>
+
+Accepts a string and returns a list in list context or an arrayref is scalar
+context.  An empty list or undef is returned if the string contained no rows.
+
+=cut
+
+sub parse
+{
+    my $self = shift;
+
+    my ($doc) = validate_pos(@_,
+        {
+            type    => SCALAR,
+            regex   => qr/\S+/, # string with at least 1 non WS char
+        }
+    );
+
+    my @data;
+    my $lineno = 1;
+LINE: foreach my $line (split /\n/, $doc) {
+        # blank lines
+        next LINE if $line =~ /^\s*$/;
+
+        # comment lines   
+        next LINE if $line =~ /^\s*\#/;
+
+        my @fields = split /\|/, $line;
+
+        # at least fileset, datatime, and type fields are required
+        if (scalar @fields < 5) {
+            carp "line $lineno: not enough fields: $line";
+            next LINE;
+        }
+
+        foreach my $field (@fields) {
+            # fields are not allowed to contain #
+            if ($field =~ /\#/) {
+                carp "line $lineno: field $field: contains #: $line";
+                next LINE;
+            }
+        
+            # strip leading and trailing whitespace
+            $field =~ s/^\s+//;
+            $field =~ s/\s+$//;
+        }
+
+        my ($product, $last_fileset, $last_datetime, $type, $desc) = @fields;
+
+        # validate format of fileset
+        unless ($last_fileset =~ $STD_FIELD) {
+            carp "line $lineno: field $last_fileset:"
+               . " does not conform to $STD_FIELD: $line";
+            next LINE;
+        }
+
+        # validate format of datetime
+        unless ($last_datetime =~ $TIME_FIELD) {
+            carp "line $lineno: field $last_datetime:"
+               . " does not conform to $TIME_FIELD";
+            next LINE;
+        }
+
+        unless (exists $KNOWN_PRODUCT_TYPES{$type}) {
+            carp "line $lineno: type $type unknown: $line";
+            next LINE;
+        } 
+
+        # fifo
+        push @data, DataStore::Product->new({
+            product       => $product,
+            last_fileset  => $last_fileset,
+            last_datetime => $last_datetime,
+            type          => $type,
+            desc          => $desc,
+            uri           => $self->base_uri . $product . '/',
+        });
+    } continue {
+        $lineno++;
+    }
+
+    return unless @data;
+    return wantarray ? @data : \@data;
+}
+
+=back
+
+=head1 SEE ALSO
+
+L<DataStore::Product>, L<DataStore::FileSet::Parser>
+
+=cut
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Record.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Record.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Record.pm	(revision 21994)
@@ -0,0 +1,118 @@
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: Record.pm,v 1.7 2006-03-16 22:03:53 jhoblitt Exp $
+
+package DataStore::Record;
+
+use strict;
+use warnings;
+
+use vars qw($VERSION);
+$VERSION = '0.01';
+
+use base qw( Class::Accessor::Fast );
+
+use Carp qw( carp croak );
+use Data::Validate::URI qw( is_uri );
+use Params::Validate qw( validate_with validate SCALAR );
+
+use vars qw( @BASE_FIELDS );
+
+@BASE_FIELDS = qw( uri );
+
+__PACKAGE__->mk_ro_accessors(@BASE_FIELDS);
+
+=pod
+
+=head1 NAME
+
+DataStore::Record - base class of DataStore list records or rows
+
+=head1 SYNOPSIS
+
+    use base qw( DataStore::Record );
+
+=head1 DESCRIPTION
+
+=head1 USAGE
+
+=head2 Import Parameters
+
+This module accepts no arguments to it's C<import> method and exports no
+I<symbols>.
+
+=head2 Methods
+
+=head3 Constructors
+
+=over 4
+
+=item * C<new()>
+
+Basic constructor.
+
+    my $dsp = DataStore::Record->new(
+        uri => 'http://example.com/',
+    );
+
+Accepts a mandatory hash and returns a L<DataStore::Record> object.
+
+=over 4
+
+=item * uri
+
+A valid I<HTTP> URI as a string. 
+
+=back
+
+=cut
+
+sub new
+{
+    my $class = shift;
+
+    my %p = validate_with(
+        params  => \@_,
+        spec    => {
+            uri => {
+                type        => SCALAR,
+                callbacks   => {
+                    'is valid http uri' =>
+                        sub { is_uri($_[0]) and $_[0] =~ /^http:/ },
+                },
+                default =>  'http://example.org/',
+            },
+        },
+        allow_extra => 1,
+    );
+
+    my $self = bless \%p, ref $class || $class;
+
+    return $self;
+}
+
+=back
+
+=head3 Object Methods
+
+=over 4
+
+=item * C<uri()>
+
+=cut
+
+=item * C<request()>
+
+This method must be overloaded in sub-classes.
+
+=cut
+
+sub request
+{
+    croak "sub classes of " . __PACKAGE__
+        . " must override the ->request() method";
+}
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Response.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Response.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Response.pm	(revision 21994)
@@ -0,0 +1,173 @@
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: Response.pm,v 1.4 2006-07-22 01:17:33 smalle Exp $
+
+package DataStore::Response;
+
+use strict;
+use warnings;
+
+use vars qw($VERSION);
+$VERSION = '0.01';
+
+use base qw( Class::Accessor::Fast );
+
+use Params::Validate qw( validate ARRAYREF BOOLEAN SCALAR UNDEF );
+
+use vars qw( @BASE_FIELDS );
+
+@BASE_FIELDS = qw( is_success code status_line data request );
+
+__PACKAGE__->mk_accessors(@BASE_FIELDS);
+
+=pod
+
+=head1 NAME
+
+DataStore::Response - represents a DataStore response
+
+=head1 SYNOPSIS
+
+    use DataStore::Response;
+
+    my $dsr = DateStore::Response->new(
+        is_success  => undef,
+        code        => 500,
+        status_line => 'foo',
+        data        => 'bar',
+        request     => DataStore::Product->new( uri => 'http://example.org/' ),
+    );
+
+    if ($data) {
+        my $success     = $dsr->is_success;
+        my $code        = $dsr->code;
+        my $status_line = $dsr->status_line;
+        my $data        = $dsr->data;
+        my DataStore::Response $response = $dsp->request;
+    }
+
+=head1 DESCRIPTION
+
+This class represent the return state of the C<request()> method in
+L<DataStore::Record> sub-classes.
+
+=head1 USAGE
+
+=head2 Import Parameters
+
+This module accepts no arguments to it's C<import> method and exports no
+I<symbols>.
+
+=head2 Methods
+
+=head3 Constructors
+
+=over 4
+
+=item * C<new()>
+
+Basic constructor.
+
+    my $dsr = DateStore::Response->new(
+        is_success  => undef,
+        code        => 500,
+        status_line => 'foo',
+        data        => 'bar',
+        request     => DataStore::Product->new( uri => 'http://example.org/' ),
+    );
+
+Accepts a mandatory hash and returns a L<DataStore::Product> object.
+
+=over 4
+
+=item * uri
+
+A vvalid I<HTTP> URI as a string.
+
+=item * code
+
+An HTTP status code.
+
+=item * status_line
+
+An HTTP status line.
+
+=item * data
+
+A scalar value, an arrayref of scalar data, or undef.
+
+=item * request
+
+An object that I<isa> L<DataStore::Record>.
+
+=back
+
+=cut
+
+sub new
+{
+    my $class = shift;
+
+    my %p = validate(@_,
+        {
+            is_success  => {
+                type        => BOOLEAN,
+                callbacks   => {
+                    'is 0, 1, or undef' =>
+                        sub { ! defined( $_[0] ) || $_[0] == 0 || $_[0] == 1 },
+                },
+            },
+            code        => {
+                type        => SCALAR,
+                regex       => qr/^\d{3}$/,
+            },
+            status_line => {
+                type        => SCALAR,
+                regex       => qr/\S+/, # string with atleast 1 non WS char
+
+            },
+            data        => {
+                type        => SCALAR | ARRAYREF | UNDEF,
+            },
+            request     => {
+                isa         => qw( DataStore::Record ),
+            },
+        }
+    );
+
+    my $self = bless \%p, ref $class || $class;
+
+    return $self;
+}
+
+=back
+
+=head3 Object Methods
+
+=over 4
+
+=item * C<uri()>
+
+Basic accessor.
+
+=item * C<code()>
+
+Basic accessor.
+
+=item * C<status_line()>
+
+Basic accessor.
+
+=item * C<data()>
+
+Basic accessor.
+
+=item * C<request()>
+
+Basic accessor.
+
+=cut
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Root.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Root.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Root.pm	(revision 21994)
@@ -0,0 +1,169 @@
+# Adapted from Product.pm
+#
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: Root.pm,v 1.3 2006-08-04 22:18:04 smalle Exp $
+
+package DataStore::Root;
+
+use strict;
+use warnings;
+
+use vars qw($VERSION);
+$VERSION = '0.01';
+
+use base qw( DataStore::Record );
+
+use Carp qw( carp );
+use DataStore::FileSet::Parser;
+use DataStore::Record;
+use DataStore::Response;
+use DataStore::Utils qw( $STD_FIELD );
+use LWP::UserAgent;
+use Params::Validate qw( validate SCALAR);
+
+use vars qw( @BASE_FIELDS );
+
+@BASE_FIELDS = qw( last_fileset );
+
+__PACKAGE__->mk_ro_accessors(@BASE_FIELDS);
+
+=pod
+
+=head1 NAME
+
+DataStore::Root - container for root DataStore index
+
+=head1 SYNOPSIS
+
+    use DataStore::Root;
+
+    my $dsp = DataStore::Root->new(
+        uri             => 'http://example.com/productid/',
+    );
+
+    my DataStore::Response $response = $dsp->request;
+
+=head1 DESCRIPTION
+
+This class I<isa> L<DataStore::Record>
+
+=head1 USAGE
+
+=head2 Import Parameters
+
+This module accepts no arguments to it's C<import> method and exports no
+I<symbols>.
+
+=head2 Methods
+
+=head3 Constructors
+
+=over 4
+
+=item * C<new()>
+
+Basic constructor.
+
+    my $dsp = DataStore::Root->new(
+        uri             => 'http://example.com/productid/',
+    );
+
+Accepts a mandatory hash and returns a L<DataStore::Root> object.
+
+=over 4
+
+=item * uri
+
+A valid I<HTTP> URI as a string.  I<A trailing slash is required.>
+
+=back
+
+=cut
+
+sub new
+{
+    my $class = shift;
+
+    # validates uri, doesn't check other params
+    my $self = $class->SUPER::new(@_);
+
+    validate(@_,
+        {
+            uri             => {
+                type        => SCALAR,
+                callbacks   => {
+                    'is valid uri dirname'   => sub { $_[0] =~ m|/$| },
+                }
+            },
+       },
+    );
+
+    return $self;
+}
+
+=back
+
+=head3 Object Methods
+
+=over 4
+
+=item * C<uri()>
+
+Basic accessor.
+
+=item * C<last_fileset()>
+
+Basic accessor.
+
+=item * C<request()>
+
+Retrieves and processes the FileSet listing pointed to by the L<uri> of this
+object.
+
+Accepts no parameters and returns a L<DataStore::Response> object.
+
+=cut
+
+sub request 
+{
+    my $self = shift;
+
+    # no params
+    validate(@_, {});
+
+    # make request
+    my $ua = LWP::UserAgent->new;
+    my $request = HTTP::Request->new(GET => $self->uri);
+    my $response = $ua->request($request);
+
+    my $data;
+
+    if ($response->is_success) {
+        # parse document
+        my $parser = DataStore::Product::Parser->new(base_uri => $self->uri);
+
+        $data = $parser->parse($response->content);
+    }
+
+    # return DS::Response object
+    my $dsr = DataStore::Response->new(
+        is_success  => $response->is_success,
+        code        => $response->code,
+        status_line => $response->status_line,
+        data        => $data,
+        request     => $self,
+    );
+}
+
+=back
+
+=head1 SEE ALSO
+
+L<DataStore::Response>
+
+=cut
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Utils.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Utils.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/lib/DataStore/Utils.pm	(revision 21994)
@@ -0,0 +1,104 @@
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: Utils.pm,v 1.3 2006-08-31 22:58:34 jhoblitt Exp $
+
+package DataStore::Utils;
+
+use strict;
+use warnings;
+
+use vars qw( $VERSION );
+$VERSION = '0.02';
+
+use base qw( Exporter );
+
+use Carp qw( carp );
+use Data::Validate::URI qw( is_uri );
+
+use vars qw(
+    @EXPORT_OK
+    $STD_FIELD
+    $TIME_FIELD
+    $BYTE_FIELD
+    $MD5_FIELD
+    %KNOWN_FILE_TYPES
+    %KNOWN_FILESET_TYPES
+    %KNOWN_PRODUCT_TYPES
+);
+
+@EXPORT_OK = qw(
+    @EXPORT_OK
+    $STD_FIELD
+    $TIME_FIELD
+    $BYTE_FIELD
+    $MD5_FIELD
+    %KNOWN_FILE_TYPES
+    %KNOWN_FILESET_TYPES
+    %KNOWN_PRODUCT_TYPES
+);
+
+$STD_FIELD = qr/^[A-z0-9-_.]+$/;
+$TIME_FIELD = qr/^(\d{4})-(\d\d)-(\d\d) T (\d\d):(\d\d):(\d\d) Z$/x;
+$BYTE_FIELD = qr/^\d+$/;
+$MD5_FIELD = qr/^[0-9a-f]{32}$/;
+%KNOWN_FILE_TYPES = map { $_ => 1 } qw( chip );
+%KNOWN_FILESET_TYPES = map { $_ => 1 } qw( OBJECT BIAS DARK SKYFLAT DOMEFLAT );
+%KNOWN_PRODUCT_TYPES = map { $_ => 1 } qw( image dump );
+
+=pod
+
+=head1 NAME
+
+DataStore::Utils - functions and/or regexs common to DataStore::* modules
+
+=head1 SYNOPSIS
+
+    use DataStore::Utils qw( ... );
+
+=head1 DESCRIPTION
+
+This class parses a DataStore listing of I<FileSet>s into an array of L<DataStore::FileSet> objects.
+
+=head1 USAGE
+
+=head2 Import Parameters
+
+This module exports no I<symbols> by default. It will export these symbols upon request:
+
+=over 4
+
+=item * C<$STD_FIELD>
+
+A C<qr> for the standard DataStore list field type.
+
+=item * C<$TIME_FIELD>
+
+A C<qr> for the standard DataStore time field type.
+
+=item * C<$BYTE_FIELD>
+
+A C<qr> for the standard DataStore byte field type.
+
+=item * C<$MD5_FIELD>
+
+A C<qr> for the standard DataStore hex encoded md5 field type.
+
+=item * C%<KNOWN_FILE_TYPES>
+
+A a hash of the known I<File> types.
+
+=item * C%<KNOWN_FILESET_TYPES>
+
+A a hash of the known I<FileSet> types.
+
+=back
+
+=head2 Methods
+
+None.
+
+=cut
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/DataStore/scripts/dsfilesetls
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/scripts/dsfilesetls	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/scripts/dsfilesetls	(revision 21994)
@@ -0,0 +1,116 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: dsfilesetls,v 1.4 2006-11-29 01:26:57 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.02';
+
+use DataStore;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
+use Pod::Usage qw( pod2usage );
+
+my ($uri);
+
+GetOptions(
+    'uri|u=s'           => \$uri,
+) or pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage(
+    -msg => "Required options: --uri",
+    -exitval => 3,
+) unless defined $uri;
+
+my $response = DataStore::FileSet->new( uri => $uri )->request;
+
+die "request failed" unless defined $response;
+die "request failed: ", $response->status unless $response->is_success;
+
+# file retreival succeed
+
+my $data = $response->data;
+
+unless ($data) {
+    warn "no files found";
+    exit(0);
+}
+
+print "# uri fileid bytes md5sum type \n";
+foreach my $fs (@$data) {
+    print 
+        $fs->uri, " ",
+        $fs->fileid, " ",
+        $fs->bytes, " ",
+        $fs->md5sum, " ",
+        $fs->type;
+    print " ", join(" ", @{$fs->extra}) if defined $fs->extra;   
+    print "\n";
+}
+
+__END__
+
+=pod
+
+=head1 NAME
+
+dsfilesetls - list all the Files under a FileSet from a DataStore server
+
+=head1 SYNOPSIS
+
+    dsfilesetls --uri <uri> 
+
+=head1 DESCRIPTION
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --uri|-u <uri>
+
+The URI of the file to be retrieved.
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2006  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<DataStore>, L<DataStore::FileSet>, L<DataStore::File>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/DataStore/scripts/dsget
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/scripts/dsget	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/scripts/dsget	(revision 21994)
@@ -0,0 +1,154 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: dsget,v 1.1 2006-03-17 03:42:32 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use DataStore;
+use File::Temp ();
+use File::Basename qw( basename dirname );
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
+use Pod::Usage qw( pod2usage );
+
+my ($uri, $bytes, $md5, $filename);
+
+GetOptions(
+    'uri|u=s'       => \$uri,
+    'bytes|m=s'     => \$bytes,
+    'md5|m=s'       => \$md5,
+    'filename|f=s'  => \$filename,
+) or pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage(
+    -msg => "Required options: --uri --filename",
+    -exitval => 3,
+) unless defined $uri and defined $filename;
+
+my %p = (
+    uri     => $uri,
+    type    => 'chip',
+);
+
+$p{bytes} = $bytes if defined $bytes; 
+$p{md5sum} = $md5 if defined $md5;
+
+# can we truely write to filename?
+{
+    # open file for ready/write but not create
+    my $fh;
+    if (open($fh, '+<', $filename)) {
+        # do nothing and fall through
+    } elsif (open($fh, '>>', $filename)) {
+        unlink $filename or die "can't unlink $filename: $!";
+    } else {
+        die "can't write to $filename";
+    }
+}
+
+my $tmp = File::Temp->new(
+    DIR         => dirname($filename),
+    TEMPLATE    => '.' . basename($filename) . 'XXXX',
+    SUFFIX      => '.tmp',
+    UNLINK      => 1,
+);
+
+my $tmpfilename = $tmp->filename;
+
+my $response = DataStore::File->new(%p)->request( filename => $tmpfilename );
+
+die "request failed" unless defined $response;
+die "request failed: ", $response->status unless $response->is_success;
+
+# file retreival succeed
+
+# this can't cross a file system boundry so we can assume that a move will
+# always be a rename operation instead of a copy and delete.
+
+rename $tmpfilename, $filename
+    or die "renaming $tmpfilename to $filename failed: $!";
+
+__END__
+
+=pod
+
+=head1 NAME
+
+gsget - download a file from a DataStore server
+
+=head1 SYNOPSIS
+
+    dsget --uri <uri> --filename <filename> [--bytes <nbytes>] [--md5 <hex>]
+
+=head1 DESCRIPTION
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --uri|-u <uri>
+
+The URI of the file to be retrieved.
+
+=item * --filename|-f <filename>
+
+The name to use when writing the file to disk.
+
+=item * --bytes|-s <nbytes>
+
+The size of the file in bytes.
+
+Optional, the size check is skipped if no value is specified.
+
+=item * --md5|-m <hex>
+
+The md5 checksum of the file in hex.
+
+Optional, the md5check is skipped if no value is specified.
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2006  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<DataStore>, L<DataStore::File>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/DataStore/scripts/dsleech
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/scripts/dsleech	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/scripts/dsleech	(revision 21994)
@@ -0,0 +1,295 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: dsleech,v 1.6 2007-01-25 03:41:29 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.02';
+
+use DataStore;
+use File::Spec;
+use YAML ();
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
+use Pod::Usage qw( pod2usage );
+
+my ($dir, $uri, $last_fileset, $overwrite, $recall, $remember, $verbose);
+
+GetOptions(
+    'dir|d=s'           => \$dir,
+    'uri|u=s'           => \$uri,
+    'last_fileset|l=s'  => \$last_fileset,
+    'overwrite|o'       => \$overwrite,
+    'recall'            => \$recall,
+    'remember'          => \$remember,
+    'verbose|v'         => \$verbose,
+) or pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage(
+    -msg => "Required options: --uri",
+    -exitval => 3,
+) unless defined $uri;
+
+my %p = (
+    uri     => $uri,
+);
+
+# rc file path
+my $rcfilename = File::Spec->catfile($ENV{'HOME'}, '.dsleechrc');
+
+# load rc file
+my $rc = load_rc($rcfilename) or die "failed to load rcfile";
+
+$p{last_fileset} = $last_fileset if defined $last_fileset; 
+if ($recall) {
+    # if --last_fileset was specified it's value should override --recall
+    if (defined $last_fileset) {
+        warn "--last_fileset overriding --recall" if defined $verbose;
+    } elsif (defined $rc->{$uri}) {
+        $p{last_fileset} = $rc->{$uri};
+    } else {
+        warn "--recall couldn't find a previous fileset ID"
+            if defined $verbose;
+    }
+}
+
+my $response = DataStore::Product->new(%p)->request;
+unless (defined $response->is_success) {
+    die "request failed: ", $response->status_line;
+}
+
+# file retreival succeed
+
+my $filesets = $response->data;
+unless ($filesets) {
+    warn "no filesets found";
+    exit(0);
+}
+
+process_filesets($filesets, $dir, $overwrite, $verbose) or die "failed to process filesets";
+
+# if we got this far we're assuming that the downloads completed and we can
+# save the last fileset 
+if ($remember) {
+    my $lowest_fileset = $filesets->[-1];
+    if (defined $lowest_fileset) {
+        $rc->{$uri} = $lowest_fileset->fileset;
+    }
+
+    save_rc($rcfilename, $rc) or die "failed to save rcfile";
+}
+
+sub process_filesets
+{
+    my ($filsets, $dir, $overwrite, $verbose) = @_;
+
+    foreach my $fileset (@$filesets) {
+        my $response = $fileset->request;
+        unless (defined $response->is_success) {
+            warn "request failed: ", $response->status_line;
+            return;
+        }
+
+        my $files = $response->data;
+        # if we get an empty fileset ->request will sucessed but ->data will
+        # return undef   
+        next unless defined $files;
+        unless (@$files) {
+            print "no files in fileset ", $fileset->set, "\n" if $verbose;
+            next;
+        }
+
+        if (!process_files($files, $dir, $overwrite, $verbose)) {
+            warn "failed to process files";
+            return;
+        }
+    }
+
+    return 1;
+}
+
+sub process_files
+{
+    my ($files, $dir, $overwrite, $vebose) = @_;
+
+    foreach my $file (@$files) {
+        # generate the filename to downloda too
+        my $filename;
+        if (defined $dir) {
+            if (!-e $dir) {
+                print "creating dir $dir\n" if $verbose;
+                mkdir $dir or die "can't create dir: $!";
+            }
+            if (!-d $dir) {
+                warn "$dir is not a directory";
+                return;
+            }
+
+            $filename = File::Spec->catfile($dir, $file->fileid);
+        } else {
+            $filename = $file->fileid;
+        }
+
+        # make sure that filename doesn't already exist
+        if (-e $filename) {
+            if ($overwrite) {
+                warn "file $filename already exists, overwriting...";
+            } else {
+                warn "file $filename already exists, skipping...";
+                next;
+            }
+        }
+
+        # use the short version of the filename (with out the path) 
+        print "fetching ", $file->fileid, "..." if $verbose;
+
+        my $response = $file->request( filename => $filename );
+        unless (defined $response->is_success) {
+            warn "request failed: ", $response->status_line;
+            return;
+        }
+
+        unless ($response->data) {
+            warn "there was a problem retreiving ", $file->fileid;
+            return;
+        }
+
+        print "    ok\n" if $verbose;
+    }
+
+    return 1;
+}
+
+sub load_rc {
+    my $rcfilename = shift;
+
+    # initalize $sums with an empty hash so if there isn't a pre-existing
+    # database we still end up with a hashref instead of an undef scalar
+    my $rc;
+    if (-e $rcfilename) {
+        if (-f $rcfilename) {
+            $rc = YAML::LoadFile($rcfilename) or die "failed to load rc file";
+        } else {
+            warn "$rcfilename is not a plain file";
+            return;
+        }
+    }
+
+    # if the rcfile exists but is empty YAML will return undef
+    $rc ||= {};
+
+    return $rc;
+}
+
+sub save_rc {
+    my ($rcfilename, $rc) = @_;
+
+    my $yaml = YAML::DumpFile($rcfilename, $rc)
+            or die "failed to write rc file";
+
+    return 1;
+}
+
+__END__
+
+=pod
+
+=head1 NAME
+
+dsleech - batch retrieve files from a DataStore server product
+
+=head1 SYNOPSIS
+
+    dsproductls --uri <uri> [--dir <dir>] [--last_fileset <filesetid>]
+                [--recall] [--remember] [--verbose]
+
+=head1 DESCRIPTION
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --uri|-u <uri>
+
+The URI of the DataStore product to retrive files from.
+
+=item * --dir|-d <dir>
+
+This flag is optional.
+
+The directory to download retrived files into.  The default is to fetch files into the current directory.
+
+=item * --last_fileset|-l <filesetid>
+
+The FileSet ID of the last FileSet that you've seen.  Only filesets registered after C<filesetid> will be polled for files to retreive.
+
+This flag is optional.
+
+=item * --overwrite
+
+If a file already exists, overwrite it.
+
+This flag is optional.
+
+=item * --recall
+
+Load the last fileset ID seen for C<--uri> from the I<rcfile>, if it exists.
+
+This flag is optional.
+
+=item * --remember
+
+Store the last fileset ID seen for C<--uri> in the I<rcfile>.
+
+This flag is optional.
+
+=item * --verbose|-v
+
+Be more verbose in reporting actions.
+
+This flag is optional.
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2006  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<dsproductls>, L<dsfilesetls>, L<dsget>, L<DataStore>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/DataStore/scripts/dsproductls
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/scripts/dsproductls	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/scripts/dsproductls	(revision 21994)
@@ -0,0 +1,122 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: dsproductls,v 1.3 2006-08-30 22:45:53 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.02';
+
+use DataStore;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
+use Pod::Usage qw( pod2usage );
+
+my ($uri, $last_fileset);
+
+GetOptions(
+    'uri|u=s'           => \$uri,
+    'last_fileset|l=s'  => \$last_fileset,
+) or pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage(
+    -msg => "Required options: --uri",
+    -exitval => 3,
+) unless defined $uri;
+
+my %p = (
+    uri     => $uri,
+);
+
+$p{last_fileset} = $last_fileset if defined $last_fileset; 
+
+my $response = DataStore::Product->new(%p)->request;
+
+die "request failed" unless defined $response;
+die "request failed: ", $response->status_line unless $response->is_success;
+
+# file retreival succeed
+
+my $data = $response->data;
+
+unless ($data) {
+    warn "no filesets found";
+    exit(0);
+}
+
+print "# uri fileset datetime type\n";
+foreach my $fs (@$data) {
+    print $fs->uri, " ", $fs->fileset, " ", $fs->datetime, " ", $fs->type, "\n";
+}
+
+__END__
+
+=pod
+
+=head1 NAME
+
+dsproductls - list all the FileSets under a product from a DataStore server
+
+=head1 SYNOPSIS
+
+    dsproductls --uri <uri> [--last_fileset <filesetid>]
+
+=head1 DESCRIPTION
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --uri|-u <uri>
+
+The URI of the file to be retrieved.
+
+=item * --lst_fileset|-l <filesetid>
+
+The FileSet ID of the last FileSet that you've seen.
+
+This flag is optional.
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2006  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<DataStore>, L<DataStore::Product>, L<DataStore::FileSet>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/DataStore/t/00_distribution.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/t/00_distribution.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/t/00_distribution.t	(revision 21994)
@@ -0,0 +1,25 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2005  Joshua Hoblitt
+#
+# $Id: 00_distribution.t,v 1.2 2006-03-16 22:04:38 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use lib qw( ./lib ./t );
+
+use Test::More;
+
+# example taken from Test::Distribution Pod
+
+BEGIN {
+    eval {
+        require Test::Distribution;
+    };
+    if($@) {
+        plan skip_all => 'Test::Distribution not installed';
+    } else {
+        import Test::Distribution; # not => qw( podcover );
+    }
+}
Index: /tags/ipp-1-X/rel-0_06/DataStore/t/01_load.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/t/01_load.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/t/01_load.t	(revision 21994)
@@ -0,0 +1,19 @@
+# -*- perl -*-
+
+# t/001_load.t - check module loading and create testing directory
+
+use lib qw( ./lib ./t );
+
+use Test::More tests => 11;
+
+BEGIN { use_ok('DataStore'); }
+BEGIN { use_ok('DataStore::File'); }
+BEGIN { use_ok('DataStore::File::Parser'); }
+BEGIN { use_ok('DataStore::FileSet'); }
+BEGIN { use_ok('DataStore::FileSet::Parser'); }
+BEGIN { use_ok('DataStore::Product'); }
+BEGIN { use_ok('DataStore::Product::Parser'); }
+BEGIN { use_ok('DataStore::Root'); }
+BEGIN { use_ok('DataStore::Record'); }
+BEGIN { use_ok('DataStore::Response'); }
+BEGIN { use_ok('DataStore::Utils'); }
Index: /tags/ipp-1-X/rel-0_06/DataStore/t/02_fileset_parse.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/t/02_fileset_parse.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/t/02_fileset_parse.t	(revision 21994)
@@ -0,0 +1,188 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: 02_fileset_parse.t,v 1.8 2006-08-31 22:58:34 jhoblitt Exp $
+
+use strict;
+use warnings;
+
+use lib qw( ./lib ./t );
+
+use Test::More tests => 43;
+use Test::Warn;
+
+=head1 NAME
+
+t/02_fileset_parse.t - tests DataStore::FileSet::Parser
+
+=head1 SYNOPSIS
+    
+    prove t/02_fileset_parse.t
+
+=cut
+
+use DataStore::FileSet::Parser;
+#use Test::Warn;
+
+can_ok('DataStore::FileSet::Parser', qw(
+    new
+    parse
+));
+
+# ->new()
+
+{
+    my $parser = DataStore::FileSet::Parser->new;
+
+    isa_ok($parser, 'DataStore::FileSet::Parser');
+}
+
+# ->parse()
+
+eval {
+    my $parser = DataStore::FileSet::Parser->new;
+
+    $parser->parse(undef);
+};
+like($@, qr/is not one of the allowed types/,
+    '->parse() fails when passed undef');
+
+eval {
+    my $parser = DataStore::FileSet::Parser->new;
+
+    $parser->parse('');
+};
+like($@, qr/ did not pass regex check/,
+    '->parse() fails when passed a zero length string');
+
+warning_like {
+    my $parser = DataStore::FileSet::Parser->new;
+
+    is($parser->parse('asdf|asdf'), undef,
+        '->parse() returns undef on failure');
+} qr/not enough fields/,
+    '->parse() fails when there are too few fields';
+
+warning_like {
+    my $parser = DataStore::FileSet::Parser->new;
+
+    is($parser->parse('|2006-01-01T00:03:04Z|OBJECT'), undef,
+        '->parse() returns undef on failure');
+} qr/does not conform /,
+    '->parse() fails when the fileset field is not in the proper format';
+
+warning_like {
+    my $parser = DataStore::FileSet::Parser->new;
+
+    is($parser->parse('foobar|2006-01-0100:03:04Z|OBJECT'), undef,
+        '->parse() returns undef on failure');
+} qr/does not conform /,
+    '->parse() fails when the datetime field is not in the proper format';
+
+warning_like {
+    my $parser = DataStore::FileSet::Parser->new;
+
+    is($parser->parse('foobar|2006-01-01T00:03:04Z| '), undef,
+        '->parse() returns undef on failure');
+} qr/does not conform /,
+    '->parse() fails when the type field is not in the proper format';
+
+warning_like {
+    my $parser = DataStore::FileSet::Parser->new;
+
+    is($parser->parse('foo#bonkbar|2006-01-01T00:03:04Z|baz'), undef,
+        '->parse() returns undef on failure');
+} qr/contains #/,
+    '->parse() fails when a field contains #';
+
+warning_like {
+    my $parser = DataStore::FileSet::Parser->new;
+
+    is($parser->parse('foobar|2006-01-01T00:03:04Z|baz # foo'), undef,
+        '->parse() returns undef on failure');
+} qr/contains #/,
+    '->parse() comments are not allowed after the last field';
+
+{
+    # multi-row example
+my $example1 =<<END;
+# filesetID|time registered    |type   |telescope pointing         |etime|f|airmass|
+otis0123456|2006-01-01T00:03:04Z|OBJECT|11:00:10.33 68:26:59.6 2000|30.0 |r|1.23   |
+otis0123456|2006-01-01T00:03:04Z|OBJECT|11:00:10.33 68:26:59.6 2000|30.0 |r|1.23   |
+otis0123456|2006-01-01T00:03:04Z|OBJECT|11:00:10.33 68:26:59.6 2000|30.0 |r|1.23   |
+otis0123456|2006-01-01T00:03:04Z|OBJECT|11:00:10.33 68:26:59.6 2000|30.0 |r|1.23   |
+END
+    my $parser  = DataStore::FileSet::Parser->new(
+        base_uri => 'http://foo.com/'
+    );
+    my @results = $parser->parse($example1);
+
+    is(scalar @results, 4, "correct number of item returned in list context");
+}
+
+{
+    # multi-row example
+my $example1 =<<END;
+# filesetID|time registered    |type   |telescope pointing         |etime|f|airmass|
+otis0123456|2006-01-01T00:03:04Z|OBJECT|11:00:10.33 68:26:59.6 2000|30.0 |r|1.23   |
+otis0123456|2006-01-01T00:03:04Z|OBJECT|11:00:10.33 68:26:59.6 2000|30.0 |r|1.23   |
+otis0123456|2006-01-01T00:03:04Z|OBJECT|11:00:10.33 68:26:59.6 2000|30.0 |r|1.23   |
+otis0123456|2006-01-01T00:03:04Z|OBJECT|11:00:10.33 68:26:59.6 2000|30.0 |r|1.23   |
+END
+    my $parser  = DataStore::FileSet::Parser->new(
+        base_uri => 'http://foo.com/'
+    );
+    my $results = $parser->parse($example1);
+
+    is(scalar @$results, 4,
+        "correct number of item returned in scalar context");
+
+    isa_ok(@$results[0], 'DataStore::FileSet');
+    is(@$results[0]->fileset, 'otis0123456', 'correct fileset');
+    is(@$results[0]->datetime, '2006-01-01T00:03:04Z', 'correct datetime');
+    is(@$results[0]->type, 'OBJECT', 'correct type');
+    is(@$results[0]->uri, 'http://foo.com/otis0123456/', 'correct uri');
+
+    isa_ok(@$results[1], 'DataStore::FileSet');
+    is(@$results[1]->fileset, 'otis0123456', 'correct fileset');
+    is(@$results[1]->datetime, '2006-01-01T00:03:04Z', 'correct datetime');
+    is(@$results[1]->type, 'OBJECT', 'correct type');
+    is(@$results[1]->uri, 'http://foo.com/otis0123456/', 'correct uri');
+
+    isa_ok(@$results[2], 'DataStore::FileSet');
+    is(@$results[2]->fileset, 'otis0123456', 'correct fileset');
+    is(@$results[2]->datetime, '2006-01-01T00:03:04Z', 'correct datetime');
+    is(@$results[2]->type, 'OBJECT', 'correct type');
+    is(@$results[2]->uri, 'http://foo.com/otis0123456/', 'correct uri');
+
+    isa_ok(@$results[3], 'DataStore::FileSet');
+    is(@$results[3]->fileset, 'otis0123456', 'correct fileset');
+    is(@$results[3]->datetime, '2006-01-01T00:03:04Z', 'correct datetime');
+    is(@$results[3]->type, 'OBJECT', 'correct type');
+    is(@$results[3]->uri, 'http://foo.com/otis0123456/', 'correct uri');
+}
+
+{
+    # example with blank lines & comments
+my $example1 =<<END;
+
+
+# filesetID|time registered    |type   |telescope pointing         |etime|f|airmass|
+
+                            # random comment
+otis0123456|2006-01-01T00:03:04Z|OBJECT|11:00:10.33 68:26:59.6 2000|30.0 |r|1.23   |
+
+                            # random comment
+
+# foo
+END
+    my $results = DataStore::FileSet::Parser->new->parse($example1);
+
+    is(scalar @$results, 1, "correct number of item returned");
+
+    isa_ok(@$results[0], 'DataStore::FileSet');
+    is(@$results[0]->fileset, 'otis0123456', 'correct fileset');
+    is(@$results[0]->datetime, '2006-01-01T00:03:04Z', 'correct datetime');
+    is(@$results[0]->type, 'OBJECT', 'correct type');
+}
Index: /tags/ipp-1-X/rel-0_06/DataStore/t/03_file_parse.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/t/03_file_parse.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/t/03_file_parse.t	(revision 21994)
@@ -0,0 +1,196 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: 03_file_parse.t,v 1.4 2006-03-16 21:51:46 jhoblitt Exp $
+
+use strict;
+use warnings;
+
+use lib qw( ./lib ./t );
+
+use Test::More tests => 46;
+use Test::Warn;
+
+=head1 NAME
+
+t/03_file_parse.t - tests DataStore::File::Parser
+
+=head1 SYNOPSIS
+    
+    prove t/03_file_parse.t
+
+=cut
+
+use DataStore::File::Parser;
+#use Test::Warn;
+
+can_ok('DataStore::File::Parser', qw(
+    new
+    parse
+));
+
+# ->new()
+
+{
+    my $parser = DataStore::File::Parser->new;
+
+    isa_ok($parser, 'DataStore::File::Parser');
+}
+
+# ->parse()
+
+eval {
+    my $parser = DataStore::File::Parser->new;
+
+    $parser->parse(undef);
+};
+like($@, qr/is not one of the allowed types/,
+    '->parse() fails when passed undef');
+
+eval {
+    my $parser = DataStore::File::Parser->new;
+
+    $parser->parse('');
+};
+like($@, qr/ did not pass regex check/,
+    '->parse() fails when passed a zero length string');
+
+warning_like {
+    my $parser = DataStore::File::Parser->new;
+
+    is($parser->parse('asdf|asdf'), undef,
+        '->parse() returns undef on failure');
+} qr/not enough fields/,
+    '->parse() fails when there are too few fields';
+
+warning_like {
+    my $parser = DataStore::File::Parser->new;
+
+    is($parser->parse(
+    'foo+++bar|83002312|fe6a2b6564c0d4cfb3bbf1db813824ba|chip|'), undef,
+        '->parse() returns undef on failure');
+} qr/does not conform/,
+    '->parse() fails when the fileID field is not in the proper format';
+
+warning_like {
+    my $parser = DataStore::File::Parser->new;
+
+    is($parser->parse(
+    'otis0123456.01|a83002312|fe6a2b6564c0d4cfb3bbf1db813824ba|chip|'), undef,
+        '->parse() returns undef on failure');
+} qr/does not conform/,
+    '->parse() fails when the bytes field is not in the proper format';
+
+warning_like {
+    my $parser = DataStore::File::Parser->new;
+
+    is($parser->parse(
+    'otis0123456.01|83002312|zfe6a2b6564c0d4cfb3bbf1db813824ba|chip|'), undef,
+        '->parse() returns undef on failure');
+} qr/does not conform/,
+    '->parse() fails when the md5sum field is not in the proper format';
+
+warning_like {
+    my $parser = DataStore::File::Parser->new;
+
+    is($parser->parse(
+    'otis0123456.01|83002312|fe6a2b6564c0d4cfb3bbf1db813824ba|c+hip|'), undef,
+        '->parse() returns undef on failure');
+} qr/does not conform/,
+    '->parse() fails when the fileID field is not in the proper format';
+
+warning_like {
+    my $parser = DataStore::File::Parser->new;
+
+    is($parser->parse(
+    'otis012#3456.01|83002312|fe6a2b6564c0d4cfb3bbf1db813824ba|chip|'), undef,
+        '->parse() returns undef on failure');
+} qr/contains #/,
+    '->parse() fails when a field contains #';
+
+warning_like {
+    my $parser = DataStore::File::Parser->new;
+
+    is($parser->parse(
+    'otis0123456.01|83002312|fe6a2b6564c0d4cfb3bbf1db813824ba|chip| # foo'), undef,
+        '->parse() returns undef on failure');
+} qr/contains #/,
+    '->parse() comments are not allowed after the last field';
+
+{
+    # multi-row example
+my $example1 =<<END;
+# fileID      |bytes   |md5sum                          |type|chipname|
+otis0123456.01|83002312|fe6a2b6564c0d4cfb3bbf1db813824ba|chip|ota01   |
+otis0123456.02|83002312|a2b4a7d7b94dc6076c5f3f67239a48c6|chip|ota02   |
+otis0123456.03|83002312|a39b1510484c7833e27454b181f13981|chip|ota03   |
+otis0123456.04|83002312|7bb35e1e30f3f833c0416aea75f90304|chip|ota04   |
+END
+    my @results = DataStore::File::Parser->new->parse($example1);
+    is(scalar @results, 4, "correct number of item returned in list context");
+}
+
+{
+    # multi-row example
+my $example1 =<<END;
+# fileID      |bytes   |md5sum                          |type|chipname|
+otis0123456.01|83002312|fe6a2b6564c0d4cfb3bbf1db813824ba|chip|ota01   |
+otis0123456.02|83002312|a2b4a7d7b94dc6076c5f3f67239a48c6|chip|ota02   |
+otis0123456.03|83002312|a39b1510484c7833e27454b181f13981|chip|ota03   |
+otis0123456.04|83002312|7bb35e1e30f3f833c0416aea75f90304|chip|ota04   |
+END
+    my $results = DataStore::File::Parser->new->parse($example1);
+
+    is(scalar @$results, 4,
+        "correct number of item returned in scalar context");
+
+    isa_ok(@$results[0], 'DataStore::File');
+    is(@$results[0]->fileid, 'otis0123456.01', 'correct fileid');
+    is(@$results[0]->bytes, '83002312', 'correct datetime');
+    is(@$results[0]->md5sum, 'fe6a2b6564c0d4cfb3bbf1db813824ba', 'correct md5');
+    is(@$results[0]->type, 'chip', 'correct type');
+
+    isa_ok(@$results[1], 'DataStore::File');
+    is(@$results[1]->fileid, 'otis0123456.02', 'correct fileid');
+    is(@$results[1]->bytes, '83002312', 'correct datetime');
+    is(@$results[1]->md5sum, 'a2b4a7d7b94dc6076c5f3f67239a48c6', 'correct md5');
+    is(@$results[1]->type, 'chip', 'correct type');
+
+    isa_ok(@$results[2], 'DataStore::File');
+    is(@$results[2]->fileid, 'otis0123456.03', 'correct fileid');
+    is(@$results[2]->bytes, '83002312', 'correct datetime');
+    is(@$results[2]->md5sum, 'a39b1510484c7833e27454b181f13981', 'correct md5');
+    is(@$results[2]->type, 'chip', 'correct type');
+
+    isa_ok(@$results[3], 'DataStore::File');
+    is(@$results[3]->fileid, 'otis0123456.04', 'correct fileid');
+    is(@$results[3]->bytes, '83002312', 'correct datetime');
+    is(@$results[3]->md5sum, '7bb35e1e30f3f833c0416aea75f90304', 'correct md5');
+    is(@$results[3]->type, 'chip', 'correct type');
+}
+
+{
+    # example with blank lines & comments
+my $example1 =<<END;
+
+
+# fileID      |bytes   |md5sum                          |type|chipname|
+
+                            # random comment
+otis0123456.01|83002312|fe6a2b6564c0d4cfb3bbf1db813824ba|chip|ota01   |
+
+                            # random comment
+
+# foo
+END
+    my $results = DataStore::File::Parser->new->parse($example1);
+
+    is(scalar @$results, 1, "correct number of item returned");
+
+    isa_ok(@$results[0], 'DataStore::File');
+    is(@$results[0]->fileid, 'otis0123456.01', 'correct fileid');
+    is(@$results[0]->bytes, '83002312', 'correct datetime');
+    is(@$results[0]->md5sum, 'fe6a2b6564c0d4cfb3bbf1db813824ba', 'correct md5');
+    is(@$results[0]->type, 'chip', 'correct type');
+}
Index: /tags/ipp-1-X/rel-0_06/DataStore/t/04_record.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/t/04_record.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/t/04_record.t	(revision 21994)
@@ -0,0 +1,81 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: 04_record.t,v 1.1 2006-02-28 03:56:46 jhoblitt Exp $
+
+use strict;
+use warnings;
+
+use lib qw( ./lib ./t );
+
+use Test::More tests => 7;
+use DataStore::Record;
+
+=head1 NAME
+
+t/04_record.t - tests DataStore::Record
+
+=head1 SYNOPSIS
+    
+    prove t/04_record.t
+
+=cut
+
+can_ok('DataStore::Record', qw(
+    new
+    uri
+    request
+));
+
+# ->new()
+
+{
+    my $rec = DataStore::Record->new;
+
+    isa_ok($rec, 'DataStore::Record');
+}
+
+{
+    # w/o trailing slash
+    my $rec = DataStore::Record->new(
+        uri => 'http://example.org/foo'
+    );
+
+    isa_ok($rec, 'DataStore::Record');
+}
+
+{
+    # w/ trailing slash
+    my $rec = DataStore::Record->new(
+        uri => 'http://example.org/foo/'
+    );
+
+    isa_ok($rec, 'DataStore::Record');
+}
+
+# ->uri()
+
+{
+    # default value
+    my $rec = DataStore::Record->new;
+    is($rec->uri, 'http://example.org/', '->uri() returned default uri');
+}
+
+{
+    # default value
+    my $rec = DataStore::Record->new(
+        uri => 'http://example.org/foo/'
+    );
+    is($rec->uri, 'http://example.org/foo/', '->uri() returned correct uri');
+}
+
+# ->request()
+
+eval {
+    my $rec = DataStore::Record->new;
+
+    $rec->request;
+};
+like($@, qr/must override the ->request\(\) method/,
+    '->request() dies when not overridden');
Index: /tags/ipp-1-X/rel-0_06/DataStore/t/05_product.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/t/05_product.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/t/05_product.t	(revision 21994)
@@ -0,0 +1,175 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: 05_product.t,v 1.5 2006-08-31 22:58:34 jhoblitt Exp $
+
+use strict;
+use warnings;
+
+use lib qw( ./lib ./t );
+
+use Test::More tests => 22;
+
+=head1 NAME
+
+t/05_product.t - tests DataStore::Product
+
+=head1 SYNOPSIS
+    
+    prove t/05_product.t
+
+=cut
+
+use DataStore::Product;
+
+can_ok('DataStore::Product', qw(
+    new
+    request
+));
+
+# ->new()
+
+{
+    my $dsp = DataStore::Product->new( uri => 'http://example.org/' );
+
+    isa_ok($dsp, 'DataStore::Product');
+}
+
+{
+    my $dsp = DataStore::Product->new(
+        uri             => 'http://example.org/',
+        last_fileset    => '12buckelyourshoe',
+    );
+
+    isa_ok($dsp, 'DataStore::Product');
+}
+
+eval {
+    my $dsp = DataStore::Product->new( uri => 'http://example.org/', foo => 1 );
+};
+like($@, qr/not listed in the validation options/,
+    '->new() fails whe passed extra params');
+
+eval {
+    my $dsp = DataStore::Product->new(
+        uri             => 'http://example.org/',
+        last_fileset    => '12buckelyourshoe',
+        foo => 1,
+    );
+};
+like($@, qr/not listed in the validation options/,
+    '->new() fails whe passed extra params');
+
+eval {
+    my $dsp = DataStore::Product->new( uri => 'http://example.org' );
+};
+like($@, qr/is valid uri dirname/,
+    '->new() fails when uri param does not end with /');
+
+eval {
+    my $dsp = DataStore::Product->new( uri => '://example.org' );
+};
+like($@, qr/is valid http uri/,
+    '->new() fails when uri param is not http protocol');
+
+eval {
+    my $dsp = DataStore::Product->new(
+        uri             => 'http://example.org/',
+        last_fileset    => '++12buckelyourshoe',
+    );
+};
+like($@, qr/is valid fileset ID/,
+    '->new() fails when last_fileset param is not a valid fileset ID');
+
+eval {
+    my $dsp = DataStore::Product->new;
+};
+like($@, qr/Mandatory parameter 'uri'/,
+    '->new() fails when not passed a uri param');
+
+eval {
+    my $dsp = DataStore::Product->new(
+        last_fileset    => '12buckelyourshoe',
+    );
+};
+like($@, qr/Mandatory parameter 'uri'/,
+    '->new() fails when not passed a uri param');
+
+# ->request()
+
+use Net::HTTPServer;
+
+sub bar 
+{
+    my $req = shift;             # Net::HTTPServer::Request object
+    my $res = $req->Response();  # Net::HTTPServer::Response object
+
+    my $string = <<END;
+# filesetID|time registered    |type   |telescope pointing         |etime|f|airmass|
+otis0123456|2006-01-01T00:03:04Z|OBJECT|11:00:10.33 68:26:59.6 2000|30.0 |r|1.23   |
+otis0123456|2006-01-01T00:03:04Z|OBJECT|11:00:10.33 68:26:59.6 2000|30.0 |r|1.23   |
+otis0123456|2006-01-01T00:03:04Z|OBJECT|11:00:10.33 68:26:59.6 2000|30.0 |r|1.23   |
+otis0123456|2006-01-01T00:03:04Z|OBJECT|11:00:10.33 68:26:59.6 2000|30.0 |r|1.23   |
+END
+
+    $res->Print($string);
+
+    return $res;
+}
+
+$|++;
+
+$SIG{CHLD} = 'IGNORE';
+my $pid = open(my $child, "-|");
+
+unless ($pid) {
+    my $server = new Net::HTTPServer( port => 'scan', log => '/dev/null' );
+
+    # send port number to parent
+    print $server->Start(), "\n";
+
+    $server->RegisterURL('/', \&bar);
+    $server->Process();  # Run forever
+
+    exit -1;
+}
+
+my $port = <$child>;
+chomp $port;
+
+{
+    my $dsp = DataStore::Product->new( uri => "http://localhost:$port/" );
+
+    isa_ok($dsp->request, 'DataStore::Response');
+}
+
+{
+    my $dsp = DataStore::Product->new( uri => "http://localhost:$port/" );
+
+    my $dsr = $dsp->request;
+
+    ok($dsr->is_success, "response->is_success() is correct");
+    is($dsr->code, 200, "response->code() is correct");
+    is($dsr->status_line, "200 OK", "response->status_line() is correct");
+    is(ref $dsr->data, 'ARRAY', "response->data is arrayref is correct");
+    isa_ok($dsr->request, 'DataStore::Record');
+
+    my $data = $dsr->data;
+    is(scalar @$data, 4, "data has the correct number of rows");
+    isa_ok(@$data[0], 'DataStore::FileSet', "data has correct type of rows");
+    isa_ok(@$data[1], 'DataStore::FileSet', "data has correct type of rows");
+    isa_ok(@$data[2], 'DataStore::FileSet', "data has correct type of rows");
+    isa_ok(@$data[3], 'DataStore::FileSet', "data has correct type of rows");
+}
+
+# cleanup HTTP server
+kill 9, $pid;
+
+eval {
+    my $dsp = DataStore::Product->new( uri => 'http://example.org/' );
+
+    $dsp->request( foo => 1 );
+};
+like($@, qr/not listed in the validation options/,
+    '->request() fails whe passed extra params');
Index: /tags/ipp-1-X/rel-0_06/DataStore/t/06_fileset.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/t/06_fileset.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/t/06_fileset.t	(revision 21994)
@@ -0,0 +1,166 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: 06_fileset.t,v 1.8 2006-08-31 22:58:34 jhoblitt Exp $
+
+use strict;
+use warnings;
+
+use lib qw( ./lib ./t );
+
+use Test::More tests => 18;
+
+=head1 NAME
+
+t/06_fileset.t - tests DataStore::FileSet
+
+=head1 SYNOPSIS
+    
+    prove t/06_fileset.t
+
+=cut
+
+use DataStore::FileSet;
+
+can_ok('DataStore::FileSet', qw(
+    new
+    request
+));
+
+# ->new()
+
+{
+    my $dsf = DataStore::FileSet->new(
+        uri         => 'http://example.org/',
+        fileset     => '12buckelyourshoe',
+        datetime    => '2042-01-01T00:00:00Z',
+        type        => 'OBJECT',
+    );
+
+    isa_ok($dsf, 'DataStore::FileSet');
+}
+
+eval {
+    my $dsf = DataStore::FileSet->new(
+        uri         => 'http://example.org/',
+        fileset     => '12buckelyourshoe',
+        datetime    => '2042-01-01T00:00:00Z',
+        type        => 'OBJECT',
+        foo         => 1,
+    );
+};
+like($@, qr/not listed in the validation options/,
+    '->new() fails whe passed extra params');
+
+eval {
+    my $dsf = DataStore::FileSet->new( uri => 'http://example.org' );
+};
+like($@, qr/is valid uri dirname/,
+    '->new() fails when uri param does not end with /');
+
+eval {
+    my $dsf = DataStore::FileSet->new( uri => '://example.org' );
+};
+like($@, qr/is valid http uri/,
+    '->new() fails when uri param is not http protocol');
+
+eval {
+    my $dsp = DataStore::FileSet->new;
+};
+like($@, qr/Mandatory parameter/,
+    '->new() fails when not passed all manadator params');
+
+# ->request()
+
+use Net::HTTPServer;
+
+sub bar 
+{
+    my $req = shift;             # Net::HTTPServer::Request object
+    my $res = $req->Response();  # Net::HTTPServer::Response object
+
+    my $string = <<END;
+# fileID      |bytes   |md5sum                          |type|chipname|
+otis0123456.01|83002312|fe6a2b6564c0d4cfb3bbf1db813824ba|chip|ota01   |
+otis0123456.02|83002312|a2b4a7d7b94dc6076c5f3f67239a48c6|chip|ota02   |
+otis0123456.03|83002312|a39b1510484c7833e27454b181f13981|chip|ota03   |
+otis0123456.04|83002312|7bb35e1e30f3f833c0416aea75f90304|chip|ota04   |
+END
+
+    $res->Print($string);
+
+    return $res;
+}
+
+$|++;
+
+$SIG{CHLD} = 'IGNORE';
+my $pid = open(my $child, "-|");
+
+unless ($pid) {
+    my $server = new Net::HTTPServer( port => 'scan', log => '/dev/null' );
+
+    # send port number to parent
+    print $server->Start(), "\n";
+
+    $server->RegisterURL('/', \&bar);
+    $server->Process();  # Run forever
+
+    exit -1;
+}
+
+my $port = <$child>;
+chomp $port;
+
+{
+    my $dsp = DataStore::FileSet->new(
+        uri         => "http://localhost:$port/",
+        fileset     => '12buckelyourshoe',
+        datetime    => '2042-01-01T00:00:00Z',
+        type        => 'OBJECT',
+    );
+
+    isa_ok($dsp->request, 'DataStore::Response');
+}
+
+{
+    my $dsp = DataStore::FileSet->new(
+        uri         => "http://localhost:$port/",
+        fileset     => '12buckelyourshoe',
+        datetime    => '2042-01-01T00:00:00Z',
+        type        => 'OBJECT',
+    );
+
+    my $dsr = $dsp->request;
+
+    ok($dsr->is_success, "response->is_success() is correct");
+    is($dsr->code, 200, "response->code() is correct");
+    is($dsr->status_line, "200 OK", "response->status_line() is correct");
+    is(ref $dsr->data, 'ARRAY', "response->data is arrayref is correct");
+    isa_ok($dsr->request, 'DataStore::Record');
+
+    my $data = $dsr->data;
+    is(scalar @$data, 4, "data has the correct number of rows");
+    isa_ok(@$data[0], 'DataStore::File', "data has correct type of rows");
+    isa_ok(@$data[1], 'DataStore::File', "data has correct type of rows");
+    isa_ok(@$data[2], 'DataStore::File', "data has correct type of rows");
+    isa_ok(@$data[3], 'DataStore::File', "data has correct type of rows");
+}
+
+# cleanup HTTP server
+kill 9, $pid;
+
+eval {
+    my $dsf = DataStore::FileSet->new(
+        uri         => 'http://example.org/',
+        fileset     => '12buckelyourshoe',
+        datetime    => '2042-01-01T00:00:00Z',
+        type        => 'OBJECT',
+    );
+
+    $dsf->request( foo => 1 );
+};
+like($@, qr/not listed in the validation options/,
+    '->request() fails whe passed extra params');
+
Index: /tags/ipp-1-X/rel-0_06/DataStore/t/07_file.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/t/07_file.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/t/07_file.t	(revision 21994)
@@ -0,0 +1,180 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: 07_file.t,v 1.5 2006-03-17 23:54:35 jhoblitt Exp $
+
+use strict;
+use warnings;
+
+use lib qw( ./lib ./t );
+
+use Test::More tests => 14;
+
+=head1 NAME
+
+t/07_file.t - tests DataStore::File
+
+=head1 SYNOPSIS
+    
+    prove t/07_file.t
+
+=cut
+
+use DataStore::File;
+use File::Temp ();
+
+can_ok('DataStore::File', qw(
+    new
+    request
+));
+
+# ->new()
+
+{
+    my $dsf = DataStore::File->new(
+        uri         => 'http://example.org/foo',
+        fileid      => '12buckelyourshoe',
+        bytes       => 12345,
+        md5sum      => 'fe6a2b6564c0d4cfb3bbf1db813824ba',
+        type        => 'chip',
+    );
+
+    isa_ok($dsf, 'DataStore::File');
+}
+
+eval {
+    my $dsf = DataStore::File->new(
+        uri         => 'http://example.org/foo',
+        fileid      => '12buckelyourshoe',
+        bytes       => 12345,
+        md5sum      => 'fe6a2b6564c0d4cfb3bbf1db813824ba',
+        type        => 'chip',
+        foo         => 1,
+    );
+};
+like($@, qr/not listed in the validation options/,
+    '->new() fails whe passed extra params');
+
+eval {
+    my $dsf = DataStore::File->new( uri => 'http://example.org/' );
+};
+like($@, qr/is valid uri filename/,
+    '->new() fails when uri param does not end with /');
+
+eval {
+    my $dsf = DataStore::File->new( uri => '://example.org' );
+};
+like($@, qr/is valid http uri/,
+    '->new() fails when uri param is not http protocol');
+
+eval {
+    my $dsf = DataStore::File->new;
+};
+like($@, qr/Mandatory parameter/,
+    '->new() fails when not passed all manadator params');
+
+# ->request()
+
+use Net::HTTPServer;
+
+sub bar 
+{
+    my $req = shift;             # Net::HTTPServer::Request object
+    my $res = $req->Response();  # Net::HTTPServer::Response object
+
+    my $string = "foobarbaz"; 
+
+    $res->Print($string);
+
+    return $res;
+}
+
+$|++;
+
+$SIG{CHLD} = 'IGNORE';
+my $pid = open(my $child, "-|");
+
+unless ($pid) {
+    my $server = new Net::HTTPServer( port => 'scan', log => '/dev/null' );
+
+    # send port number to parent
+    print $server->Start(), "\n";
+
+    $server->RegisterURL('/somefile', \&bar);
+    $server->Process();  # Run forever
+
+    exit -1;
+}
+
+my $port = <$child>;
+chomp $port;
+
+{
+    my $dsf = DataStore::File->new(
+        uri         => "http://localhost:$port/somefile",
+        fileid      => '12buckelyourshoe',
+        bytes       => 9,
+        md5sum      => 'a0a6e1a375117c58d77221f10c5ce12e',
+        type        => 'chip',
+    );
+
+    my $fh = File::Temp->new( UNLINK => 1 );
+    $fh->autoflush(1);
+    isa_ok($dsf->request( filename => $fh->filename ), 'DataStore::Response');
+}
+
+{
+    my $dsf = DataStore::File->new(
+        uri         => "http://localhost:$port/somefile",
+        fileid      => '12buckelyourshoe',
+        bytes       => 9,
+        md5sum      => 'a0a6e1a375117c58d77221f10c5ce12e',
+        type        => 'chip',
+    );
+
+    my $fh = File::Temp->new( UNLINK => 1 );
+    $fh->autoflush(1);
+    my $dsr = $dsf->request( filename => $fh->filename );
+
+    ok($dsr->is_success, "response->is_success() is correct");
+    is($dsr->code, 200, "response->code() is correct");
+    is($dsr->status_line, "200 OK", "response->status_line() is correct");
+    is($dsr->data, $fh->filename, "response->data is arrayref is correct");
+    isa_ok($dsr->request, 'DataStore::Record');
+}
+
+# stop HTTP server
+kill 9, $pid;
+
+eval {
+    my $dsf = DataStore::File->new(
+        uri         => 'http://example.org/foo',
+        fileid      => '12buckelyourshoe',
+        bytes       => 12345,
+        md5sum      => 'fe6a2b6564c0d4cfb3bbf1db813824ba',
+        type        => 'chip',
+    );
+    
+    $dsf->request;
+};
+like($@, qr/Mandatory parameter/,
+    '->request() fails when passed no params');
+
+eval {
+    my $dsf = DataStore::File->new(
+        uri         => 'http://example.org/foo',
+        fileid      => '12buckelyourshoe',
+        bytes       => 12345,
+        md5sum      => 'fe6a2b6564c0d4cfb3bbf1db813824ba',
+        type        => 'chip',
+    );
+    
+    my $fh = File::Temp->new( UNLINK => 1 );
+    $dsf->request(
+        filename => $fh->filename,
+        foo => 1,
+    );
+};
+like($@, qr/not listed in the validation options/,
+    '->request() fails whe passed extra params');
Index: /tags/ipp-1-X/rel-0_06/DataStore/t/08_response.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/t/08_response.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/t/08_response.t	(revision 21994)
@@ -0,0 +1,96 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: 08_response.t,v 1.2 2006-07-22 01:17:34 smalle Exp $
+
+use strict;
+use warnings;
+
+use lib qw( ./lib ./t );
+
+use Test::More tests => 8;
+
+=head1 NAME
+
+t/08_response.t - tests DataStore::Response
+
+=head1 SYNOPSIS
+    
+    prove t/08_response.t
+
+=cut
+
+use CGI;
+use DataStore::Product;
+use DataStore::Response;
+
+can_ok('DataStore::Response', qw(
+    new
+    is_success
+    code
+    status_line
+    data
+    request
+));
+
+# ->new()
+
+{
+    my $dsr = DataStore::Response->new(
+        is_success  => undef,
+        code        => 500,
+        status_line => 'foo',
+        data        => 'bar',
+        request     => DataStore::Product->new( uri => 'http://example.org/' ),
+    );
+
+    isa_ok($dsr, 'DataStore::Response');
+}
+
+eval {
+    my $dsr = DataStore::Response->new(
+        is_success   => undef,
+        code        => 500,
+        status_line => 'foo',
+        data        => 'bar',
+        request     => DataStore::Product->new( uri => 'http://example.org/' ),
+        foo         => 1,
+    );
+};
+like($@, qr/not listed in the validation options/,
+    '->new() fails whe passed extra params');
+
+eval {
+    my $dsr = DataStore::Response->new( is_success => 2 );
+};
+like($@, qr/is 0, 1, or undef/,
+    '->new() fails when is_success is not valid');
+
+eval {
+    my $dsr = DataStore::Response->new( code => 5000 );
+};
+like($@, qr/did not pass regex check/,
+    '->new() fails when code is not valid');
+
+eval {
+    my $dsr = DataStore::Response->new( status_line => '' );
+};
+like($@, qr/did not pass regex check/,
+    '->new() fails when status_line is not valid');
+
+eval {
+    my $dsr = DataStore::Response->new(
+        request => CGI->new,
+    );
+};
+like($@, qr/was not a 'DataStore::Record' /,
+    '->new() fails when response is not valid');
+
+eval {
+    my $dsr = DataStore::Response->new;
+};
+like($@, qr/Mandatory parameters/,
+    '->new() fails when not passed all manadator params');
+
+# accessor tests unneeded as they are all generated by Class::Accessor::Fast
Index: /tags/ipp-1-X/rel-0_06/DataStore/t/09_datastore.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/t/09_datastore.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/t/09_datastore.t	(revision 21994)
@@ -0,0 +1,33 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: 09_datastore.t,v 1.2 2006-03-16 01:23:10 jhoblitt Exp $
+
+use strict;
+use warnings;
+
+use lib qw( ./lib ./t );
+
+use Test::More tests => 7;
+
+=head1 NAME
+
+t/09_datastore.t - tests DataStore
+
+=head1 SYNOPSIS
+    
+    prove t/09_datastore.t
+
+=cut
+
+use DataStore;
+
+ok(%DataStore::, "DataStore is loaded");
+ok(%DataStore::File::Parser::, "DataStore::File::Parser is loaded");
+ok(%DataStore::File::, "DataStore::File is loaded");
+ok(%DataStore::FileSet::Parser::, "DataStore::FileSet::Parser is loaded");
+ok(%DataStore::FileSet::, "DataStore::Set is loaded");
+ok(%DataStore::Product::, "DataStore::Product is loaded");
+ok(%DataStore::Response::, "DataStore::Response is loaded");
+
Index: /tags/ipp-1-X/rel-0_06/DataStore/t/10_dsget.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/t/10_dsget.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/t/10_dsget.t	(revision 21994)
@@ -0,0 +1,53 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: 10_dsget.t,v 1.2 2006-03-17 21:58:23 jhoblitt Exp $
+
+use strict;
+use warnings;
+
+use lib qw( ./lib ./t );
+
+use Test::Cmd;
+use Test::More tests => 7;
+
+=head1 NAME
+
+t/10_dsget.t - tests dsget
+
+=head1 SYNOPSIS
+    
+    prove t/10_dsget.t
+
+=cut
+
+# last ditch effort to make sure dsget is executable
+chmod 0755, 'scripts/dsget';
+
+my $test = Test::Cmd->new(prog => 'scripts/dsget', workdir => '');
+isa_ok($test, 'Test::Cmd');
+
+{
+    $test->run(args => '');
+    missing_args(3, "Required options: --uri --filename");
+}
+
+{
+    $test->run(args => '--uri http://example.org/foo');
+    missing_args(3, "Required options: --uri --filename");
+}
+
+{
+    $test->run(args => '--filename /foo/bar/baz');
+    missing_args(3, "Required options: --uri --filename");
+}
+
+sub missing_args
+{
+    my ($exit, $errstr) = @_;
+
+    is($? >> 8, $exit, "error code is: $exit");
+    like($test->stderr, qr/$errstr/, "error string is: $errstr");
+}
+
Index: /tags/ipp-1-X/rel-0_06/DataStore/t/11_dsproductls.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/t/11_dsproductls.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/t/11_dsproductls.t	(revision 21994)
@@ -0,0 +1,48 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: 11_dsproductls.t,v 1.1 2006-03-18 04:02:35 jhoblitt Exp $
+
+use strict;
+use warnings;
+
+use lib qw( ./lib ./t );
+
+use Test::Cmd;
+use Test::More tests => 5;
+
+=head1 NAME
+
+t/11_dsproductls.t - tests dsproductls
+
+=head1 SYNOPSIS
+    
+    prove t/11_dsproductls.t
+
+=cut
+
+# last ditch effort to make sure dsproductls is executable
+chmod 0755, 'scripts/dsproductls';
+
+my $test = Test::Cmd->new(prog => 'scripts/dsproductls', workdir => '');
+isa_ok($test, 'Test::Cmd');
+
+{
+    $test->run(args => '');
+    missing_args(3, "Required options: --uri");
+}
+
+{
+    $test->run(args => '--last_fileset foobar');
+    missing_args(3, "Required options: --uri");
+}
+
+sub missing_args
+{
+    my ($exit, $errstr) = @_;
+
+    is($? >> 8, $exit, "error code is: $exit");
+    like($test->stderr, qr/$errstr/, "error string is: $errstr");
+}
+
Index: /tags/ipp-1-X/rel-0_06/DataStore/t/12_dsfilesetls.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/DataStore/t/12_dsfilesetls.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/DataStore/t/12_dsfilesetls.t	(revision 21994)
@@ -0,0 +1,45 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: 12_dsfilesetls.t,v 1.1 2006-03-20 22:03:53 jhoblitt Exp $
+
+use strict;
+use warnings;
+
+use lib qw( ./lib ./t );
+
+use Test::Cmd;
+use Test::More tests => 3;
+
+=head1 NAME
+
+t/12_dsfilesetls.t - tests dsfilesetls
+
+=head1 SYNOPSIS
+    
+    prove t/12_dsfilesetls.t
+
+=cut
+
+my $prog = 'scripts/dsfilesetls';
+
+# last ditch effort to make sure dsproductls is executable
+chmod 0755, $prog;
+
+my $test = Test::Cmd->new( prog => $prog, workdir => '' );
+isa_ok($test, 'Test::Cmd');
+
+{
+    $test->run( args => '' );
+    missing_args(3, "Required options: --uri");
+}
+
+sub missing_args
+{
+    my ($exit, $errstr) = @_;
+
+    is($? >> 8, $exit, "error code is: $exit");
+    like($test->stderr, qr/$errstr/, "error string is: $errstr");
+}
+
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/.cvsignore	(revision 21994)
@@ -0,0 +1,6 @@
+Build
+META.yml
+Makefile
+Makefile.PL
+_build
+blib
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/Build.PL
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/Build.PL	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/Build.PL	(revision 21994)
@@ -0,0 +1,120 @@
+use Module::Build;
+# See perldoc Module::Build for details of how this works
+
+my $build_pkg   = eval { require Apache::TestMB }
+                ? 'Apache::TestMB'
+                : 'Module::Build';
+
+my $class = $build_pkg->subclass(code => <<'EOF');
+use Cwd;
+
+my $pkg_dir = "./nebclient";
+
+sub ACTION_code {
+    my $self = shift;
+
+    $self->SUPER::ACTION_code(@_);
+
+    my $old_pwd = getcwd();
+    chdir $pkg_dir;
+
+    unless (-e "configure") {
+        system("./autogen.sh") == 0 or die "install failed: $?";
+    }
+
+    chdir $old_pwd;
+}
+
+sub ACTION_build {
+    my $self = shift;
+
+    $self->SUPER::ACTION_build(@_);
+
+    my $old_pwd = getcwd();
+    chdir $pkg_dir;
+
+    unless (-e "Makefile") {
+        system("sh ./configure") == 0 or die "build failed: $?";
+    }
+
+    system("make") == 0 or die "build failed: $?";
+
+    chdir $old_pwd;
+}
+
+# Do not attempt to install nebclient.  It is bundled in this package for
+# testing only.
+#
+# sub ACTION_install {
+#     my $self = shift;
+# 
+#     $self->SUPER::ACTION_install(@_);
+# 
+#     my $old_pwd = getcwd();
+#     chdir $pkg_dir;
+# 
+#     system("make install") == 0 or die "install failed: $?";
+# 
+#     chdir $old_pwd;
+# }
+
+sub ACTION_clean {
+    my $self = shift;
+
+    $self->SUPER::ACTION_clean(@_);
+
+    my $old_pwd = getcwd();
+    chdir $pkg_dir;
+
+    system("make clean") == 0 or die "install failed: $?";
+
+    chdir $old_pwd;
+}
+EOF
+
+$class->new(
+    module_name         => 'Nebulous',
+    dist_version_from   => 'lib/Nebulous/Server.pm',
+    author              => 'Joshua Hoblitt <jhoblitt@cpan.org>',
+    license             => 'gpl',
+    create_makefile_pl  => 'passthrough',
+    requires            => {
+        'Class::Accessor::Fast' => 0,
+        'Config::YAML'          => '1.42',
+        'DBD::mysql'            => '3.0007',
+        'DBI'                   => '1.53',
+        'File::ExtAttr'         => '1.03',
+        'File::Spec::Functions' => 0,
+        'Log::Log4perl'         => '0.48',
+        'Net::Server::Daemonize'=> '0.05',
+        'Params::Validate'      => '0.73',
+        'SOAP::Lite'            => '0.69',
+        'Sys::Statistics::Linux::DiskUsage' => '0.02',
+        'URI'                   => '1.30',
+    },
+    build_requires      => {
+        'Apache2::SOAP'         => 0,
+        'Apache::DBI'           => '1.05',
+        'Apache::Test'          => '1.27',  # bundles Apache::TestMB
+        'Apache::TestMB'        => 0,
+        'File::Temp'            => 0,
+        'Test::More'            => '0.49',
+        'Test::URI'             => '1.06',
+    },
+    recommends          => {
+        'Test::Distribution'    => '1.22',
+    },
+    script_files        => [qw(
+        bin/neb-addvol
+        bin/neb-cat
+        bin/neb-cp
+        bin/neb-df
+        bin/neb-locate
+        bin/neb-initdb
+        bin/neb-ls
+        bin/neb-mv
+        bin/neb-rm
+        bin/neb-touch
+        bin/nebdiskd
+    )],
+)->create_build_script;
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/Changes
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/Changes	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/Changes	(revision 21994)
@@ -0,0 +1,95 @@
+Revision history for Nebulous
+
+0.06 Fri Jan 25 10:55:59 HST 2008
+    - define Nebulous::Client::find_objects() as returning [] when NO keys are
+      found
+    - change neb-touch to use Nebulous::Client::find_objects() instead of
+      ::find()
+    - add Nebulous::Sever:: neb key/uri support
+    - add Nebulous::Util::parse_neb_key()
+    - change bin/* scripts to conistently use --volume instead of --node,
+      etc.
+    - pod cleanups
+    - add neb-replicate & neb-cull
+
+0.05 2007-05-04 16:59:31(???)
+    - make filesystem xattr support optional & disabled by default
+    - generate instance filenames that leave the "key" at the end so as to not
+      break a pplications that expect a certain "extension" on the filename
+    - set an xattr on all created files of "user.nebulous_key"
+    - add neb-locate
+    - change all Nebulous::Client public methods to behave in list context
+    - rework the getmountedvol() stored procedure to attempt to work around
+      what appears to be some nasty transacational isolation leak throught that
+      was causing getmountedvol() to randomly hang when nebdiskd changed the
+      mount table.
+    - fix a nasty logic bug in Nebulous::Client->replicate()
+    - break 1:1 relationship between key names and on disk file names
+    - overhaul Nebulous::Client->cull()
+    - add the number of instances to ->stat_object()
+    - SQL cleanup
+    - better paramter checking
+    - overhaul instance table
+    - add ->_is_valid_object_key() method
+    - change ->find_instances() to check it's params and only return instances
+      on mounted & available volumes
+    - add volume.available field and logic to use it
+    - add volume.allocate field and logic to use it
+    - add instance.vol_id field
+    - remove $class_id & $comment params from Nebulous::Server->create() and
+      Nebulous::Client->create*() and all supporting functions and tests
+    - add Nebulous::Server->{setxattr_object, listxattr_object,
+      getxattr_object, removexattr_object}()
+    - add neb-cat
+    - add neb-mv
+    - change Nebulous::Client->move() to use ->rename_object()
+    - add Nebulous::Server->rename_object()
+    - add neb-rm
+    - add neb-cp
+    - add neb-ls
+    - add Nebulous::Client->find_objects()
+    - add Nebulous::Server->find_objects()
+    - add neb-touch
+    - add neb-df
+    - change neb-addvol to properly mangle URIs into paths
+
+0.04 Mon Apr 23 13:33:16 HST 2007
+    - include autogen.sh in the tarball
+    - add nebdiskd
+    - [nebclient] VERSION to '0.0.3'
+    - change API to generally return true URIs instead of file paths
+    - add support for some what intelligent volume allocations
+    - minor code & build fixes, ws changes
+
+0.03 Mon Dec 11 14:19:45 HST 2006
+    - change Nebulous::Server instantiate objects (init -> new) instead of
+      working with class data
+    - add a DESTROY method to Nebulous::Server to tear down the database
+      connection
+    - add a Nebulous::Server->config() accessor
+    - make Nebulous::Server->db() Apache::DBI aware
+    - make SQL syntax MySQL 5 compatible
+    - update SOAP, DBI & DBD, and Apache::* deps
+    - change Nebulous::Server::SOAP to be mod_perl aware
+    - change Nebulous::Server::SOAP install stub methods to bypass AUTOLOAD on
+      successive calls to the same method
+    - make Nebulous::Server::Log mod_perl aware
+    - change Nebulous::Server::Log to accept a Nebulous::Server::Config object
+      as a parameter instead of fetching it as a singleton
+    - make Nebulous::Server::Config no longer a singleton
+
+0.02 Fri Dec  2 17:36:59 HST 2005
+    - recommend Test::Distribution 1.22
+    - add t/00_distribution.t
+    - rename test files
+    - [nebclient] VERSION to '0.0.2'
+    - Nebulous::Client, Nebulous::Server, & Nebulous::Server::SQL
+        VERSION to '0.02'
+    - add Nebulous::Client->open_create()
+    - change Nebulous::Client->create() to return just a filename
+    - [nebclient] add nebOpenCreate()
+    - [nebclient] change nebCreate() to return just a filename
+
+0.01 Fri Sep  3 10:23:31 2004
+    - first working version
+	- original version; created by ExtUtils::ModuleMaker 0.32
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/LICENSE
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/LICENSE	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/LICENSE	(revision 21994)
@@ -0,0 +1,260 @@
+The General Public License (GPL)
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave,
+Cambridge, MA 02139, USA. Everyone is permitted to copy and distribute
+verbatim copies of this license document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it. By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to most of
+the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom
+to distribute copies of free software (and charge for this service if you wish), that
+you receive source code or can get it if you want it, that you can change the
+software or use pieces of it in new free programs; and that you know you can do
+these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights. These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a
+fee, you must give the recipients all the rights that you have. You must make
+sure that they, too, receive or can get the source code. And you must show
+them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer
+you this license which gives you legal permission to copy, distribute and/or
+modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced by
+others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish
+to avoid the danger that redistributors of a free program will individually obtain
+patent licenses, in effect making the program proprietary. To prevent this, we
+have made it clear that any patent must be licensed for everyone's free use or
+not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+GNU GENERAL PUBLIC LICENSE
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND
+MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or translated
+into another language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope. The act of running the Program is not
+restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program). Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as
+you receive it, in any medium, provided that you conspicuously and appropriately
+publish on each copy an appropriate copyright notice and disclaimer of warranty;
+keep intact all the notices that refer to this License and to the absence of any
+warranty; and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at
+your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus
+forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you also
+meet all of these conditions:
+
+a) You must cause the modified files to carry prominent notices stating that you
+changed the files and the date of any change.
+
+b) You must cause any work that you distribute or publish, that in whole or in
+part contains or is derived from the Program or any part thereof, to be licensed
+as a whole at no charge to all third parties under the terms of this License.
+
+c) If the modified program normally reads commands interactively when run, you
+must cause it, when started running for such interactive use in the most ordinary
+way, to print or display an announcement including an appropriate copyright
+notice and a notice that there is no warranty (or else, saying that you provide a
+warranty) and that users may redistribute the program under these conditions,
+and telling the user how to view a copy of this License. (Exception: if the
+Program itself is interactive but does not normally print such an announcement,
+your work based on the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Program, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to
+work written entirely by you; rather, the intent is to exercise the right to control
+the distribution of derivative or collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and 2
+above provided that you also do one of the following:
+
+a) Accompany it with the complete corresponding machine-readable source
+code, which must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange; or,
+
+b) Accompany it with a written offer, valid for at least three years, to give any
+third party, for a charge no more than your cost of physically performing source
+distribution, a complete machine-readable copy of the corresponding source
+code, to be distributed under the terms of Sections 1 and 2 above on a medium
+customarily used for software interchange; or,
+
+c) Accompany it with the information you received as to the offer to distribute
+corresponding source code. (This alternative is allowed only for noncommercial
+distribution and only if you received the program in object code or executable
+form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all the
+source code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+executable. However, as a special exception, the source code distributed need
+not include anything that is normally distributed (in either source or binary form)
+with the major components (compiler, kernel, and so on) of the operating system
+on which the executable runs, unless that component itself accompanies the
+executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source
+code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so long
+as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Program
+or its derivative works. These actions are prohibited by law if you do not accept
+this License. Therefore, by modifying or distributing the Program (or any work
+based on the Program), you indicate your acceptance of this License to do so,
+and all its terms and conditions for copying, distributing or modifying the
+Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor to copy,
+distribute or modify the Program subject to these terms and conditions. You
+may not impose any further restrictions on the recipients' exercise of the rights
+granted herein. You are not responsible for enforcing compliance by third parties
+to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent infringement
+or for any other reason (not limited to patent issues), conditions are imposed on
+you (whether by court order, agreement or otherwise) that contradict the
+conditions of this License, they do not excuse you from the conditions of this
+License. If you cannot distribute so as to satisfy simultaneously your obligations
+under this License and any other pertinent obligations, then as a consequence
+you may not distribute the Program at all. For example, if a patent license would
+not permit royalty-free redistribution of the Program by all those who receive
+copies directly or indirectly through you, then the only way you could satisfy
+both it and this License would be to refrain entirely from distribution of the
+Program.
+
+If any portion of this section is held invalid or unenforceable under any particular
+circumstance, the balance of the section is intended to apply and the section as
+a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other
+property right claims or to contest validity of any such claims; this section has
+the sole purpose of protecting the integrity of the free software distribution
+system, which is implemented by public license practices. Many people have
+made generous contributions to the wide range of software distributed through
+that system in reliance on consistent application of that system; it is up to the
+author/donor to decide if he or she is willing to distribute software through any
+other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain countries
+either by patents or by copyrighted interfaces, the original copyright holder who
+places the Program under this License may add an explicit geographical
+distribution limitation excluding those countries, so that distribution is permitted
+only in or among countries not thus excluded. In such case, this License
+incorporates the limitation as if written in the body of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the
+General Public License from time to time. Such new versions will be similar in
+spirit to the present version, but may differ in detail to address new problems or
+concerns.
+
+Each version is given a distinguishing version number. If the Program specifies a
+version number of this License which applies to it and "any later version", you
+have the option of following the terms and conditions either of that version or of
+any later version published by the Free Software Foundation. If the Program does
+not specify a version number of this License, you may choose any version ever
+published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of all
+derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS
+NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
+COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
+"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR
+IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED
+TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY
+WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS
+PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
+(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
+OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/MANIFEST
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/MANIFEST	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/MANIFEST	(revision 21994)
@@ -0,0 +1,131 @@
+Build.PL
+Changes
+LICENSE
+MANIFEST
+META.yml
+Makefile.PL
+README
+Todo
+autogen.sh
+bin/neb-addvol
+bin/neb-cat
+bin/neb-cp
+bin/neb-cull
+bin/neb-df
+bin/neb-initdb
+bin/neb-locate
+bin/neb-ls
+bin/neb-mv
+bin/neb-replicate
+bin/neb-rm
+bin/neb-touch
+bin/nebdiskd
+docs/c_api.h
+docs/database_setup.txt
+docs/design.txt
+docs/requirements.txt
+docs/setup.txt
+docs/tmp.txt
+examples/Makefile
+examples/nebexample.c
+examples/nebexample.pl
+lib/Nebulous/Client.pm
+lib/Nebulous/Client.pod
+lib/Nebulous/Client/HTTP.pm
+lib/Nebulous/Client/Log.pm
+lib/Nebulous/Client/QuickStart.pod
+lib/Nebulous/Server.pm
+lib/Nebulous/Server.pod
+lib/Nebulous/Server/Apache.pm
+lib/Nebulous/Server/Config.pm
+lib/Nebulous/Server/Log.pm
+lib/Nebulous/Server/SOAP.pm
+lib/Nebulous/Server/SQL.pm
+lib/Nebulous/Util.pm
+nebclient/Doxyfile.in
+nebclient/Makefile.am
+nebclient/Makefile.in
+nebclient/aclocal.m4
+nebclient/autogen.sh
+nebclient/compile
+nebclient/config.guess
+nebclient/config.h.in
+nebclient/config.sub
+nebclient/configure
+nebclient/configure.ac
+nebclient/depcomp
+nebclient/install-sh
+nebclient/ltmain.sh
+nebclient/missing
+nebclient/nebclient.pc.in
+nebclient/nebulous.wsdl
+nebclient/src/Makefile.am
+nebclient/src/Makefile.in
+nebclient/src/SOAP.nsmap
+nebclient/src/nebclient.c
+nebclient/src/nebclient.h
+nebclient/src/soapC.c
+nebclient/src/soapClient.c
+nebclient/src/soapH.h
+nebclient/src/soapStub.h
+nebclient/src/stdsoap2.c
+nebclient/src/stdsoap2.h
+nebclient/src/xmalloc.c
+nebclient/src/xmalloc.h
+nebclient/test/tap/INSTALL
+nebclient/test/tap/Makefile.am
+nebclient/test/tap/Makefile.in
+nebclient/test/tap/README
+nebclient/test/tap/aclocal.m4
+nebclient/test/tap/compile
+nebclient/test/tap/configure
+nebclient/test/tap/configure.in
+nebclient/test/tap/src/
+nebclient/test/tap/src/Makefile.am
+nebclient/test/tap/src/Makefile.in
+nebclient/test/tap/src/config.h.in
+nebclient/test/tap/src/tap.c
+nebclient/test/tap/src/tap.h
+nebclient/tests/Makefile.am
+nebclient/tests/Makefile.in
+nebclient/tests/tests.c
+scripts/bench_test.pl
+scripts/nebulous.cgi
+scripts/ptest.pl
+t/00_distribution.t 
+t/01_load.t
+t/02_server_setup.t
+t/03_server_create_object.t
+t/04_server_replicate_object.t
+t/05_server_lock_object.t
+t/06_server_unlock_object.t
+t/07_server_find_instances.t
+t/08_server_delete_instance.t
+t/09_server_stat_object.t
+t/10_server_is_valid_volume_name.t
+t/11_server_is_valid_object_key.t
+t/12_server_find_objects.t
+t/13_server_rename_object.t
+t/14_server_xattr.t
+t/50_client_new.t
+t/51_client_create.t
+t/51_client_open_create.t
+t/52_client_replicate.t
+t/53_client_cull.t
+t/54_client_lock.t
+t/55_client_unlock.t
+t/56_client_find_instances.t
+t/57_client_find.t
+t/58_client_open.t
+t/59_client_delete.t
+t/60_client_copy.t
+t/61_client_move.t
+t/62_client_delete_instance.t
+t/63_client_stat.t
+t/64_client_find_objects.t
+t/75_parse_neb_key.t
+t/90_nebclient.t
+t/TEST.PL
+t/Test/Nebulous.pm
+t/conf/extra.conf.in
+t/conf/startup.pl.in
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/README
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/README	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/README	(revision 21994)
@@ -0,0 +1,16 @@
+pod2text Poi::PixelData.pm > README
+
+If this is still here it means the programmer was too lazy to create the readme file.
+
+You can create it now by using the command shown above from this directory.
+
+At the very least you should be able to use this set of instructions
+to install the module...
+
+perl Build.PL
+./Build
+./Build test
+./Build install
+
+
+If you are on a windows box you should use 'nmake' rather than 'make'.
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/Todo
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/Todo	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/Todo	(revision 21994)
@@ -0,0 +1,42 @@
+TODO list for Perl module Nebulous
+
+- make nebclient lib thread safe
+- handle/check for storage volumes being offline
+- move storage 'classes' into the database, cache at startup?
+- use specific storage volume requests instead of ignoring them
+- admin interface to control volumes (enable/disable, add/remove)
+- add zeroconf support
+- add support for SQL and/or Apache logging
+- make copy replicate source attributes, implement as replicate/reparent?
+- implement proper storage object rename support (same volume move w/o copy)
+- redo database schema with foreign keys
+- validation of URIs
+- test that client->delete_instance removes the storage object too
+- review caching of database statement handles
+- code tiding/consistency
+- file creation retrying
+- server config file
+- make Apache::DBI behave
+- split SOAP out of Client.pm
+- Perl client error string support with DBI like 'AutoRaise' exceptions
+- CLI utilities
+- write neb-fsck utility
+- write Linux::statfs module so that statfs.f_bavail can be obtained (not available via df)
+- change neb-ls to have a limit number of keys shown (-n) param and default to
+  something reasonable (say 20)
+- add multiple regex and/or glob support to neb-ls, eg. neb-ls -r 'foo.*' -r 'bar$'
+- store the key name as an xattr on the actual on disk file
+- add an neb-locate --reverse option to map uri/paths into keys
+
+distant future
+--
+- cache some database tables (updated at some interval) 
+- volume size/% in-use discovery
+- server side per client lock tracking
+- per client authentication
+- client side lookup table of filehandles/locks
+- Perl only?, scoped lock release/filehandle destruction
+- restructure database so that storage objects are more like inodes
+- add support for directories
+- FUSE interface
+- hot-spot analysis
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/autogen.sh
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/autogen.sh	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/autogen.sh	(revision 21994)
@@ -0,0 +1,1 @@
+perl Build.PL -apxs /usr/sbin/apxs2 
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/bin/neb-addvol
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/bin/neb-addvol	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/bin/neb-addvol	(revision 21994)
@@ -0,0 +1,176 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2005-2008  Joshua Hoblitt
+#
+# $Id: neb-addvol,v 1.7 2008-01-22 21:40:39 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use DBI;
+use Nebulous::Server::SQL;
+use URI;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ($db, $dbuser, $dbpass, $volume, $uri);
+
+$db     = $ENV{'NEB_DB'} unless $db;
+$dbuser = $ENV{'NEB_USER'} unless $dbuser;
+$dbpass = $ENV{'NEB_PASS'} unless $dbpass;
+
+GetOptions(
+    'db=s'      => \$db,
+    'user=s'    => \$dbuser,
+    'pass=s'    => \$dbpass,
+    'volume=s'  => \$volume,
+    'uri|u=s'   => \$uri,
+) || pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required options: --db --user --pass", -exitval => 2 )
+    unless $db && $dbuser && $dbpass && $volume && $uri;
+
+my $dbh = DBI->connect(
+    "DBI:mysql:database=$db:host=localhost",
+    $dbuser,
+    $dbpass,
+    {
+        RaiseError => 1,
+        PrintError => 0,
+        AutoCommit => 1,
+    },
+);
+
+my $sql = Nebulous::Server::SQL->new();
+
+print "Checking URI...";
+
+my $path = URI->new($uri)->file;
+unless (-d $path) {
+    die "path: $path dirived from URI: $uri does not exist";
+}
+
+print " OK\n";
+
+print "Adding volume...";
+
+my $query = $dbh->prepare( $sql->new_volume );
+$query->execute( $volume, $path );
+
+print " OK\n";
+
+__END__
+
+=pod
+
+=head1 NAME
+
+neb-addvol - add a storage volume to a Nebulous server
+
+=head1 SYNOPSIS
+
+    neb-addvol --volume <volume name> --uri <volume uri>
+        [--db <database>] [--user <username>] [--pass <password>]
+
+=head1 DESCRIPTION
+
+This program initialize a database for use by L<Nebulous::Server> by creating
+the appropriate set of tables.  Any pre-existing tables with conflicting names
+are first removed.
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --volume <volume name>
+
+Symbolic name of volume being added.
+
+=item * --uri|-u <volume uri>
+
+URI to the volume being added.
+
+=item * --db|-d <database>
+
+Name of database (C<namespace>) to create tables in.
+
+Optional if the appropriate environment variable is set.
+
+=item * --user|-u <username>
+
+Username to authenticate with.
+
+Optional if the appropriate environment variable is set.
+
+=item * --pass|-p <password>
+
+Password to authenticate with.
+
+Optional if the appropriate environment variable is set.
+
+=back
+
+=head1 ENVIRONMENT
+
+These environment variables may be used in place of the specified command line
+options.  All command line option will override the corresponding environment
+value.
+
+=over 4
+
+=item * C<NEB_DB>
+
+Equivalent to --db|-d
+
+=item * C<NEB_USER>
+
+Equivalent to --user|-u
+
+=item * C<NEB_PASS>
+
+Equivalent to --pass|-p 
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2005-2008  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Server>, L<neb-initdb>, L<neb-df>, L<nebdiskd>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/bin/neb-initdb
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/bin/neb-initdb	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/bin/neb-initdb	(revision 21994)
@@ -0,0 +1,162 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2005-2007  Joshua Hoblitt
+#
+# $Id: neb-initdb,v 1.7 2007-04-28 01:19:59 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.02';
+
+use DBI;
+use Nebulous::Server::SQL;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ($db, $dbuser, $dbpass);
+
+$db     = $ENV{'NEB_DB'} unless $db;
+$dbuser = $ENV{'NEB_USER'} unless $dbuser;
+$dbpass = $ENV{'NEB_PASS'} unless $dbpass;
+
+GetOptions(
+    'db=s'      => \$db,
+    'user=s'    => \$dbuser,
+    'pass=s'    => \$dbpass,
+) || pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required options: --db --user --pass", -exitval => 2 )
+    unless $db && $dbuser && $dbpass;
+
+my $dbh = DBI->connect(
+    "DBI:mysql:database=$db:host=localhost",
+    $dbuser,
+    $dbpass,
+    {
+        RaiseError => 1,
+        PrintError => 0,
+        AutoCommit => 1,
+    },
+);
+
+my $sql = Nebulous::Server::SQL->new();
+
+print "Dropping any existing tables...";
+
+foreach my $statement (@{ $sql->get_db_clear }) {
+    $dbh->do( $statement );
+}
+
+print " OK\nCreating new tables...";
+
+foreach my $statement (@{ $sql->get_db_schema }) {
+    $dbh->do( $statement );
+}
+
+print " OK\n";
+
+__END__
+
+=pod
+
+=head1 NAME
+
+neb-initdb - initialize a Nebulous server database
+
+=head1 SYNOPSIS
+
+    neb-initdb [--db <database>] [--user <username>] [--pass <password>]
+
+=head1 DESCRIPTION
+
+This program initialize a database for use by L<Nebulous::Server> by creating
+the appropriate set of tables.  Any pre-existing tables with conflicting names
+are first removed.
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --db|-d <database>
+
+Name of database (C<namespace>) to create tables in.
+
+Optional if the appropriate environment variable is set.
+
+=item * --user|-u <username>
+
+Username to authenticate with.
+
+Optional if the appropriate environment variable is set.
+
+=item * --pass|-p <password>
+
+Password to authenticate with.
+
+Optional if the appropriate environment variable is set.
+
+=back
+
+=head1 ENVIRONMENT
+
+These environment variables may be used in place of the specified command line
+options.  All command line option will override the corresponding environment
+value.
+
+=over 4
+
+=item * C<NEB_DB>
+
+Equivalent to --db|-d
+
+=item * C<NEB_USER>
+
+Equivalent to --user|-u
+
+=item * C<NEB_PASS>
+
+Equivalent to --pass|-p 
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2005-2007  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Server>, L<neb-addvol>, L<neb-df>, L<nebdiskd>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/bin/nebdiskd
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/bin/nebdiskd	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/bin/nebdiskd	(revision 21994)
@@ -0,0 +1,412 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2007  Joshua Hoblitt
+# 
+# $Id: nebdiskd,v 1.4 2007-05-04 23:36:46 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.02';
+
+use Config::YAML;
+use DBI;
+use File::Spec;
+use Nebulous::Server::SQL;
+use Net::Server::Daemonize qw( daemonize unlink_pid_file );
+use Sys::Statistics::Linux::DiskUsage;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ($debug, $db, $dbuser, $dbpass, $pidfile, $stop, $restart, $verbose);
+GetOptions(
+    'debug'     => \$debug,
+    'db|d=s'    => \$db,
+    'user|u=s'  => \$dbuser,
+    'pass|p=s'  => \$dbpass,
+    'pidfile=s' => \$pidfile,
+    'stop|s'    => \$stop,
+    'restart|r' => \$restart,
+    'verbose|v' => \$verbose,
+) || pod2usage( 2 );
+
+my $rcfile = "$ENV{HOME}/.nebdiskrc";
+$rcfile = File::Spec->canonpath($rcfile);
+
+my $c = read_rcfile($rcfile);
+
+$db     ||= $c->get_db      || $ENV{'NEB_DB'};
+$dbuser ||= $c->get_dbuser  || $ENV{'NEB_USER'};
+$dbpass ||= $c->get_dbpass  || $ENV{'NEB_PASS'};
+$pidfile ||= $c->get_pidfile || "/var/tmp/nebdiskd";
+my $mounts = $c->get_mounts;
+my $poll_interval = $c->get_poll_interval || 5;
+
+if ($restart || $stop) {
+    my $status = kill_pid_file($pidfile);
+    exit($status) if $stop;
+}
+
+$c->set_db($db);
+$c->set_dbuser($dbuser);
+$c->set_dbpass($dbpass);
+$c->set_pidfile($pidfile);
+$c->set_poll_interval($poll_interval);
+$c->write;
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required options: --db --user --pass", -exitval => 2 )
+    unless $db && $dbuser && $dbpass;
+
+daemonize(
+    $<,     # User
+    $),     # Group
+    $pidfile,  # PID file
+) unless $debug;
+
+$SIG{TERM} = sub { unlink_pid_file($pidfile); exit(); };
+$SIG{INT}  = $SIG{TERM};
+$SIG{HUP}  = sub { $c = read_rcfile($rcfile) }; 
+
+my $dbh = setup_db(
+        db      => $db,
+        dbuser  => $dbuser,
+        dbpass  => $dbpass,
+    );
+
+poll_mounts(
+        dbh             => $dbh,
+        poll_interval   => $poll_interval,
+        debug           => $debug,
+    ) or die "poll_mounts() should not have returned";
+
+sub poll_mounts
+{
+    my %p = @_;
+
+    my $dbh             = $p{dbh} or return;
+    my $poll_interval   = $p{poll_interval} || 60;
+    my $debug           = $p{debug} || 0;
+
+    my $lxs = Sys::Statistics::Linux::DiskUsage->new;
+
+    while (1) {
+        # list of mount points to stat so that the automounter will mount these
+        # volumes if they have been unmounted.
+        stat_dirs($mounts);
+
+        eval {
+            my $query = $dbh->prepare_cached("INSERT INTO mount VALUES(?, ?, ?)");
+            $dbh->do("DELETE FROM mount");
+
+            print "flushed mount table\n" if $debug;
+
+            my $stats = $lxs->get;
+            foreach my $dev (keys %$stats) {
+                my $mnt = $stats->{$dev};
+                my %mount;
+                $query->execute(@$mnt{qw( mountpoint total usage )});
+                print "adding $mnt->{mountpoint} to db\n" if $debug;
+            }
+
+            $dbh->do("call getmountedvol()");
+
+            $dbh->commit;
+        };
+        if ($@) {
+            $db->rollback;
+            warn $@;
+        }
+
+        sleep $poll_interval;
+    }
+}
+
+sub read_rcfile
+{
+    my $rcfile = shift;
+
+    return unless defined $rcfile;
+
+    if (!-f $rcfile) {
+        open(my $fh, '>', $rcfile) or die "can't open file: $!";
+        close($fh) or die "can't close file:$!";
+    }
+
+    return Config::YAML->new(
+            config => $rcfile,
+            output => $rcfile,
+    );
+}
+
+
+sub setup_db
+{
+    my %p = @_;
+
+    return unless defined $p{db}
+              and defined $p{dbuser}
+              and defined $p{dbpass};
+
+    my $sql = Nebulous::Server::SQL->new;
+
+    my $dbh = DBI->connect(
+        "DBI:mysql:database=$p{db}:host=localhost",
+        $p{dbuser},
+        $p{dbpass},
+        {
+            RaiseError => 1,
+            PrintError => 1,
+            AutoCommit => 0,
+        },
+    );
+
+    eval {
+        $dbh->do( $sql->set_transaction_model );
+        $dbh->commit;
+    };
+    if ($@) { 
+        $db->rollback;
+        die $@;
+    }
+
+    return $dbh;
+}
+
+
+sub stat_dirs
+{
+    my $mounts = shift;
+
+    return unless defined $mounts;
+
+    foreach my $path (@$mounts) {
+        stat File::Spec->canonpath($path) or warn "can not stat path: $path";
+        print "stated $path\n" if $debug;
+    }
+}
+
+#
+# This function, originally named check_pid_file() was copied from
+# Net::Server::Daemonize '0.05' licensed under the Perl license.  It has been
+# renamed and modified to kill off process who's PID value is stored in pidfile.
+#
+
+sub kill_pid_file {
+  my $pid_file = shift;
+
+  ### no pid_file = return success
+  return 1 unless -e $pid_file;
+
+  ### get the currently listed pid
+  if( ! open(_PID,$pid_file) ){
+    die "Couldn't open existant pid_file \"$pid_file\" [$!]\n";
+  }
+  my $_current_pid = <_PID>;
+  close _PID;
+  my $current_pid = $_current_pid =~ /^(\d{1,10})/ ? $1 : die "Couldn't find pid in existing pid_file";
+
+  my $exists = undef;
+
+  ### try a proc file system
+  if( -d '/proc' ) {
+    $exists = -e "/proc/$current_pid";
+
+  ### try ps
+  #}elsif( -x '/bin/ps' ){ # not as portable
+  # the ps command itself really isn't portable
+  # this follows BSD syntax ps (BSD's and linux)
+  # this will fail on Unix98 syntax ps (Solaris, etc)
+  }elsif( `ps h o pid p $$` =~ /^\s*$$\s*$/ ){ # can I play ps on myself ?
+    $exists = `ps h o pid p $current_pid`;
+
+  }
+
+  ### running process exists, ouch
+    if( $exists ){
+
+        if( $current_pid == $$ ){
+            warn "Pid_file created by this same process. Doing nothing.\n";
+            return 1;
+        }else{
+            kill 'TERM', $current_pid
+                or die "Failed to signal process ($current_pid)";
+            unlink $pid_file || die "Couldn't remove pid_file \"$pid_file\" [$!]\n";
+            return 1;
+
+        }
+    }
+}
+
+__END__
+
+=pod
+
+=head1 NAME
+
+nebdiskd - Nebulous mounted volume capacity monitoring daemon
+
+=head1 SYNOPSIS
+
+    nebdiskd [--db <db name>] [--user <db username>] [--pass <db password>] [--debug] [--pidfile <filename>] [--stop] [--restart] [--verbose]
+
+=head1 DESCRIPTION
+
+This program looks for mounted volumes, at a configurable interval, and records
+statistics about them into a database.
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --db|-d <db name>
+
+Name of database (C<namespace>) to write too.
+
+Optional if defined in the F<.nebdiskdrc> file or the appropriate environment
+variable is set.
+
+=item * --user|-u <db username>
+
+Username to authenticate with.
+
+Optional if defined in the F<.nebdiskdrc> file or the appropriate environment
+variable is set.
+
+=item * --pass|-p <db password>
+
+Password to authenticate with.
+
+Optional if defined in the F<.nebdiskdrc> file or the appropriate environment
+variable is set.
+
+=item * --debug
+
+This flag prevents the program from "daemonizing" so output can be sent to
+C<stdout>/C<stderr> and a debugger used on the running process.
+
+=item * --pidfile <filename>
+
+Filename to log the running daemon's PID too.
+
+Optional, if this option is omitted and no value is defined in the
+F<.nebdiskrc> then no pidfile is created.
+
+=item * --stop|-s
+
+Uses the pidfile to kill an already running daemon.
+
+=item * --restart|-r
+
+Uses the pidfile to kill an already running daemon and then starts a new
+instance.
+
+=item * --verbose|-r
+
+Turns on informational/debugging messages to be sent to the
+C<stderr>/C<stdout>.  This option is probably not very usefully unless combined
+with C<--debug>.
+
+=back
+
+=head1 ENVIRONMENT
+
+These environment variables may be used in place of the specified command line
+options.  All command line option will override the corresponding environment
+value.
+
+=over 4
+
+=item * C<NEB_DB>
+
+Equivalent to --db|-d
+
+=item * C<NEB_USER>
+
+Equivalent to --user|-u
+
+=item * C<NEB_PASS>
+
+Equivalent to --pass|-p 
+
+=back
+
+=head1 RCFILE
+
+This program will attempt to read an C<rcfile> from F<$HOME/.nebdiskrc> and if
+found will use it's values to override program defaults.  Please not that the
+precedence for values is: command line, rcfile, environment variables.
+
+The format of the C<rcfile> is in L<YAML> format and uses the following values:
+
+    ---
+    db: nebulous
+    dbpass: '@neb@'
+    dbuser: nebulous
+    mounts:
+      - /mnt
+      - /tmp
+      - /usr
+    pidfile: /var/tmp/nebdiskd
+    poll_interval: 5
+
+The values C<db>, C<dbpass>, C<dbuser>, and C<pidfile> have the same semantics
+as their command line and/or environment variable equivalents.
+
+=over 4
+
+=item * C<mounts>
+
+A list of "paths" to C<stat(2)> before mounted volumes are polled.  The propose
+of this option is to attempt to keep "automounted" volumes mounted while this
+program is running.
+
+This value may be omitted or left blank.
+
+=item * C<poll_interval>
+
+The number of seconds to wait between checks for mounted volumes.
+
+This value may be omitted or left blank.  The default value is C<60>s.
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2007  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Server>, L<YAML>, L<neb-addvol>, L<neb-df>, L<neb-initdb>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/c_api.h
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/c_api.h	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/c_api.h	(revision 21994)
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2004 Joshua Hoblitt
+ *
+ * $Id: c_api.h,v 1.1.1.1 2004-12-22 02:16:23 jhoblitt Exp $
+ */
+
+// should there be an argument for "suggested" storage location?
+int add( const char *ext_id, const char *data, int size )
+
+int delete( const char *ext_id )
+
+// should there be an argument for "suggested" storage location?
+int update( const char *ext_id, const char *data, int size )
+
+// should there be an argument for "suggested" storage location?
+int move( const char *old_ext_id, const char *new_ext_id )
+
+// open returns a fd 
+int open( const char *ext_id )
+
+int close( const char *ext_id )
+
+// maybe open and close are a bad idea, perhaps...
+int read( const char *ext_id, char *data )
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/database_setup.txt
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/database_setup.txt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/database_setup.txt	(revision 21994)
@@ -0,0 +1,59 @@
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id: database_setup.txt,v 1.7 2005-11-09 00:49:44 jhoblitt Exp $
+
+### Database Setup
+
+### MySQL 4.1
+
+DROP DATABASE IF EXISTS nebulous;
+CREATE DATABASE nebulous;
+GRANT ALL PRIVILEGES ON *.* TO 'nebulous'@'localhost'
+    IDENTIFIED BY 'pixel' WITH GRANT OPTION;
+FLUSH PRIVILEGES;
+USE nebulous;
+
+### Initialization
+
+# localhost
+
+$ mkdir /tmp/po01 /tmp/po02
+INSERT INTO volume VALUES (1,'po01','file:/tmp/po01');
+INSERT INTO volume VALUES (1,'po02','file:/tmp/po02');
+
+# NFS
+
+INSERT INTO volume VALUES (1,'po01','file:/netdisks/po01');
+INSERT INTO volume VALUES (2,'po02','file:/netdisks/po02');
+INSERT INTO volume VALUES (3,'po03','file:/netdisks/po03');
+INSERT INTO volume VALUES (4,'po04','file:/netdisks/po04');
+INSERT INTO volume VALUES (5,'po05','file:/netdisks/po05');
+INSERT INTO volume VALUES (6,'po06','file:/netdisks/po06');
+INSERT INTO volume VALUES (7,'po07','file:/netdisks/po07');
+INSERT INTO volume VALUES (8,'po08','file:/netdisks/po08');
+
+INSERT INTO class VALUES (1,3,0,'raw image data');
+
+### Example queries
+
+LOAD DATA INFILE '/home/moa/jhoblitt/tmp/storage_objects.txt' INTO TABLE storage_object; 
+LOAD DATA INFILE '/home/moa/jhoblitt/tmp/instances.txt' INTO TABLE instance; 
+
+SELECT * FROM storage_object LEFT JOIN instance ON storage_object.so_id=instance.so_id WHERE storage_object.ext_id = "foobarbaz1.fits";
+SELECT * FROM storage_object LEFT JOIN instance USING (so_id) WHERE storage_object.ext_id = "foobarbaz1.fits";
+
+SET AUTOCOMMIT = 0;
+BEGIN;
+UPDATE instance SET read_lock=read_lock+1 WHERE ins_id=1;
+INSERT INTO lock_record values (1, 'read', NULL);
+COMMIT;
+
+SET AUTOCOMMIT = 0;
+BEGIN;
+INSERT INTO storage_object values (NULL, 'myfooedbar.fits', 'mr. wizard made this', NULL);
+INSERT INTO instance values (NULL, LAST_INSERT_ID(), 'file://tmp/bat/man/12345a', 'da39a3ee5e6b4b0d3255bfef95601890afd80709',0, NULL, NULL);
+COMMIT;
+
+IF select write_lock from instance WHERE id=1 THEN
+ELSE
+ENDIF
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/design.txt
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/design.txt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/design.txt	(revision 21994)
@@ -0,0 +1,283 @@
+# Copyright (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: design.txt,v 1.6 2005-11-05 01:13:35 jhoblitt Exp $
+
+Abstract
+--
+
+Nebulous is a user-space distributed object (file) storage system.  It is much
+more of a database of objects locations then a file system in the traditional
+sense.  Nebulous is considered distributed because of it's data storage model,
+where objects are stored across a number of storage volumes and may have one
+or more redundant copies.  While IPC is done in the traditional client/server
+model with a single[1] centralized server containing all storage object
+meta-data.  This system was designed, unlike most distributed storage system,
+specifically so that clients have the option of hosting one or more storage
+volumes and that data may be stored and accessed locally on a node.  This
+allows network I/O to be dramatically reduced if the end user does simple data
+locality optimizations.  Although, if you so choose, clients and storage
+volumes can reside on independent hardware.  Above all else, Nebulous is
+designed to make efficient use of both disk and network bandwidth.
+
+Data model
+--
+
+In Nebulous terminology a file is refereed to as a a resource.  Each resource
+is represented inside the Nebulous Server as a "Storage Object".  There is one
+Storage Object per resource (a file) that is being managed by the Nebulous
+Server.  A Storage Object maps an External Identifier (eg. filename) to a
+Storage ID.  In addition, creation time and comments may be stored in a
+Storage Object.  Storage Objects /do not/ contain the storage location of a
+resource as we need to allow for N copies of a resource to be stored.  The
+actual storage location of a resource is held in a Storage Object Instance,
+which maps to a Storage ID in a many-to-one relationship.
+
+A Storage Object Instance, or just Instance, represents a single copy of a
+resource being managed by the Nebulous Server. An Instance contains an
+Instance ID, the parent Storage ID, the location of the resource as a URI, and
+other assorted meta-data.
+
+Storage IDs are a signed 64-bit integer.  Negative values are considered
+reserved for future use.  Allocation should be incremental and, as we are
+unlikely to exceed 2^63 Storage Objects in the life time of the project, never
+reused. Instance IDs follow the same scheme as Storage IDs but exists in a
+unique namespace.
+
+Database record relationships
+--
+* All Storage Objects must have at least once associated Instance.
+
+* All Instances must be associated with a Storage Object.
+
+* All Instances must be associated with a valid URI (file exists).
+
+* All Storage Objects with locks set must have the correct number of
+corresponding Lock Records.
+
+* All Lock Records must be associated with a Storage Object.
+
+Data transport
+--
+XXX
+
+Data Storage
+--
+XXX
+
+
+Components
+--
+
+There are 4 principle components required for a working Nebulous system;
+server, client, data transport, and data storage.  The Nebulous software
+distribution provides only the server and the client software.  Data
+transport[2] and Data storage are left to 3rd party software packages.  As
+those functionalities are typically included with most operating systems.
+Nebulous build upon and benefits from advances made in those technologies.
+
+Server
+--
+
+The server is responsible for keeping track of storage objects, all instances
+of that object, and enforcing locking semantics.  Extensive logging and
+tracing support is provided for debug and to allow for statics generation and
+possible X<hotspot> optimization.
+
+Nebulous uses a centralized server model.  This model was choosen because it
+allows efficient X<pattern matching> of storage object names.  The current
+'best' technique for a distributed metadata store is with distributed hash
+tables.  Unfortunately, no widely available DHT implementation allows efficient
+I<pattern matching> of key names.
+
+
+[1] Multiple Nebulous servers should be possible via database replication.
+[2] A future version of Nebulous may include it's own data transport layer
+based on the WEB DAV protocol.
+
+Client <-> Server IPC
+--
+
+The Nebulous Server and clients communicate via the SOAP protocol.  Since SOAP
+is platform independent this allows native Nebulous clients to be written in a
+variety of languages.  With in the Nebulous Server itself the IPC mechanism is
+abstracted to allow ether multi-protocol support or complete replacement of
+SOAP by another protocol.
+
+XXX SOAP namespace
+
+
+Storage volume state tracking.
+
+Nebulous itself does not attempt to determine the state of storage volumes.
+Instead, it relies on some 3rd party to determine both the state
+(available/not) and capacity (total size + % utilized).  This information is
+then feed into Nebulous via either the administrative API or CLI management
+tools.
+
+XXX Storage Location determination
+
+
+Locking semantics
+--
+Nebulous uses 'advisory locking' where clients are excepted to check for the
+existence of locks but this policy is not enforced.  Locks are set on a
+Storage Object and apply to all Instances of that object.
+
+Two types of locks can be set; 'read' locks and 'write' locks.  Read locks are
+implemented as a semaphore while write locks use an exclusive mutex.
+
+    - Read lock
+In order to obtain a Read Lock on a Storage Object the Write Lock mutex must
+be in the state of 'free'.  When a Read Lock is acquire the Read semaphore is
+incremented by one.  When a Read Lock is released the Read semaphore is
+decremented by one.  This must happen atomically with the
+creation/destruction of a Lock Record.
+
+    - Write lock
+In order to obtain a Write lock on a Storage Object the Write Lock mutex must
+be in the state of 'free' and the Read lock semaphore must have a value of
+zero.  When a Write Lock is acquired the Write mutex is set to 'write'.  When a
+Write Lock is released the Write mutex is set to to 'free'.  This must happen
+atomically with the creation/destruction of a Lock Record.  As an extension, a
+sate of 'wait' may be implemented such that clients waiting on Read Locks to
+be released may prevent any additional Read Locks from being acquired.
+
+XXX Lock Records are currently unimplemented
+    - Lock Records A Lock Record is used to double check the indicated lock
+      state of a Storage Object and can be used to identify logical system
+errors.  A Lock Record contains the Storage ID of the object and the type of
+lock set.  eg, enum( 'read', 'write').
+
+    - Client best practices
+When attempting to acquire a lock a client should either "spin lock" with a
+reasonable pause between lock attempts or fail completely.  Aggressive "spin
+locking" is considered antisocial and may eventually require the Nebulous
+Server to identify and ignore such clients.
+
+
+House keeping
+--
+    - Lock sweeping
+In the event that a Storage Object operation fails to complete successfully
+stale locks will have to be identified and removed from the IPP Pixel Data
+Server Database.  This should be done periodically by comparing the entries
+in the Lock table to the list of active nodes maintained by the IPP
+Controller.  It should also happen as soon as possible after a node goes
+offline (triggered by the IPP Controller marking a node as offline?).  A sweep
+must be /completed/ before an offline node can be marked on-line.
+
+Once a node is determined to be offline all entries in the Lock table set by
+that node should be identified.   The locks on the Storage Object
+Instances pointed to by those entries should then be rolled back and Lock
+Record entries themselves must be removed from the lock table.
+
+    - Consistency sweeping
+Periodically the IPP Pixel Data Server meta-data and Storage Object will need
+to be checked for sanity.  This would be similar to running fsck on a modern
+filesystem.  Consistency sweeping should include Lock sweeping and should be
+considered a super-set.
+
+
+Server Operations
+--
+    - setup
+    - create_object
+    - rename_object
+        XXX unimplemented
+    - link_object
+        XXX unimplemented
+    - replicate object
+    - lock_object
+    - unlock_object
+    - find_objects
+        XXX unimplemented
+    - find_instances
+    - delete_instance
+    - fission_object
+        XXX unimplemented
+    - fuse_objects
+        XXX unimplemented
+    - stat_object
+    - stat_instance
+        XXX unimplemented
+
+Client Operations
+--
+    - create
+Creates and opens new Storage Object
+
+    - replicate
+Adds an Instance to a Storage Object
+
+    - cull
+Removes an Instance from a Storage Object
+
+This operation can not remove the last Instance of a Storage Object.
+
+    - lock
+Trys to acquire a lock on a storage object
+
+This operation times out after a default interval of 10s.
+
+    - unlock
+Trys to release a lock on a storage object
+    
+    - find_instances
+Find all instances of a storage object
+
+Only Instances on active storage volumes are found.
+
+    - find
+Find any instance of a storage object
+
+Only Instances on active storage volumes are found.
+
+    - open
+Open a storage object for read or write
+
+Opening a storage object as 'write' will remove all but one Instance to
+prevent Instances from becoming inconsistent.
+
+    - delete
+Delete a storage object and all of it's instances
+
+Removes a storage object and all of it's instances by sequentially deleting each
+Instance.  When a Storage Object has no more associated instances it is
+automatically removed by the Nebulous server.
+
+    - copy
+Copy a storage object
+
+The new storage object will be created with only one Instance.  Most properties
+of the source Storage Object will be preserved.
+
+    - move
+Rename a storage object
+
+Currently this operation will remove all but one instance of the storage
+object and may change it's storage location.
+
+    - delete_instance
+    
+Remove a storage object instance
+
+Removing the last Instance of a Storage Object will destroy the Storage
+Object.
+
+    - stat
+View the properties of a storage object
+
+
+    - import
+        XXX unimplemented
+Import a file into Nebulous
+
+Creates a new Storage Object with the specified External Identifier.  The
+source file will then be "copied" into the Nebulous system leaving the original
+file unmodified.
+
+    - fission
+        XXX unimplemented
+Create a new Storage Object from an existing one by either splitting off an
+Instance and re-parenting it or by cloning an existing Instance and associating
+it with the new Storage Object.
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/requirements.txt
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/requirements.txt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/requirements.txt	(revision 21994)
@@ -0,0 +1,28 @@
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id: requirements.txt,v 1.2 2005-09-14 00:46:01 jhoblitt Exp $
+
+- store all image data aquired during the first two years of PS1's
+  operations.  Approximately 10^8 files (OTA level).
+
+- injest new data from the summit at the same rate it is produced when
+  operating at a cadence of 40s between integrations.  Approximately 400Mb/s
+  and 64 files/integration.
+
+- support phase 1 & 2 processing. x files per t_min
+
+- support phase 3 & 4 processing. x files per t_min
+
+- support accessing small blocks of a file (ie., seek)
+
+- tolerate partal system failures without data loss
+
+- execeedly efficent use of both disk and network I/O
+
+what are the science drivers for these 3?
+--
+- data corruption is guarenteed to be detectable.
+
+- relibably store xx.x% of files 
+
+- xx.x% of stored images must be retreivable in xs.
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/setup.txt
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/setup.txt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/setup.txt	(revision 21994)
@@ -0,0 +1,369 @@
+=pod
+
+=head1 Installing a Nebulous Server
+
+=head2 Create a UNIX group for Nebulous
+
+All Nebulous user's need to be in the same UNIX group as the Nebulous server.
+
+    groupadd -g 877 nebulous
+
+This is a silly hack to generate a gid.
+
+    perl -le 'map { $gid += ord } split //, shift; print $gid' nebulous
+
+=head2 Add the users that you want to be able to access Nebulous to that group
+
+    usermod -G nebulous foouser
+
+=head2 Setup directory permissions for the nebulous group
+
+As root:
+
+    mkdir /data/ipp000.0/nebulous
+    mkdir /data/ipp000.1/nebulous
+    mkdir /data/ipp002.0/nebulous
+    mkdir /data/ipp003.0/nebulous
+
+    # note that this is just an example, this won't work over NFS with
+    # root_squash enablded
+    chown nobody:nebulous /data/ipp00?.?/nebulous
+
+    chmod 0770 /data/ipp00?.?/nebulous
+    ls -lad /data/ipp00?.?/nebulous
+
+=head2 Build and install the Nebulous Perl modules (see: README)
+
+=head2 Create and initialize the database
+
+    mysql -u root mysql -p
+    (enter your MySQL root password)
+
+    DROP DATABASE IF EXISTS nebulous;
+    CREATE DATABASE nebulous;
+    GRANT ALL PRIVILEGES ON nebulous.* TO 'nebulous'@'localhost'
+        IDENTIFIED BY '@neb@';
+    FLUSH PRIVILEGES;
+    exit
+
+    export NEB_DB=nebulous
+    export NEB_USER=nebulous
+    export NEB_PASS=@neb@
+
+    neb-initdb
+    neb-addvol --name ipp000.0 --uri file:///data/ipp000.0/nebulous
+    neb-addvol --name ipp000.1 --uri file:///data/ipp000.1/nebulous
+    neb-addvol --name ipp002.0 --uri file:///data/ipp002.0/nebulous
+    neb-addvol --name ipp003.0 --uri file:///data/ipp003.0/nebulous
+
+#    perl -e 'for (1..24) { $i = sprintf "po%02d", $_ ; system "neb-addvol --name $i --uri file:/$i/nebulous" }'
+    .
+    .
+
+If you get an error similar to this while initializing the database it means
+that the creation of the Nebulous's stored procedures failed:
+
+    ERROR 1146 (42S02): Table 'mysql.proc' doesn't exist
+
+It probably means that your instance of MySQL has been upgraded for an older
+version that did not support stored precedures.  You can fix this by running
+the C<mysql_fix_privilege_tables> script that you should have received with
+MySQL.
+
+In order for the test suite to pass the "test" account needs have the
+appropriate permissions to create and modify stored procedures.
+
+    update user set Create_routine_priv = 'Y', Alter_routine_priv = 'Y', Execute_priv = 'Y' where user = 'test';
+    update db set Create_routine_priv = 'Y', Alter_routine_priv = 'Y', Execute_priv = 'Y' where db = 'test';
+
+    flush privileges;
+
+Please see this webpage for further details:
+
+http://dev.mysql.com/doc/refman/5.0/en/stored-procedure-privileges.html
+
+
+=head2 Setup nebdiskd daemon
+
+Create the .netdiskrc file in the home directory of the user that nebdiskd
+will run as.  This does not need to be/should not be the root user.  Merely a
+user with permissions to see all of the approparite volumes.
+
+Example F<.netdiskrc>:
+
+    db: nebulous
+    dbpass: '@neb@'
+    dbuser: nebulous
+    mounts:
+      - /data/ipp000.0
+      - /data/ipp000.1
+      - /data/ipp002.0
+      - /data/ipp003.0
+    pidfile: /var/tmp/nebdiskd
+    poll_interval: 5
+
+Start the daemon by running the command C<nebdiskd>.  Use this command to
+verify that the daemon is working correclty.
+
+    neb-volstat
+
+nebdiskd should always been running when nebulous is use.  This command is an
+example of how to startup the daemon running as another user.  This could be
+use to start the daemon from the root account while the system init scripts
+are running.
+
+    sudo -H -u jhoblitt nebdiskd
+
+See the nebdiskd POD/man page for further details
+
+=head2 Install Apache2 with mod_perl
+
+=head3 Minimum software requirements:
+
+Nebulous will work with both Apache 1.3 & 2.x.  However, this guide will only
+cover configuraton with Apache 2.x and mod_perl 2.x.
+
+=over 4
+
+=item * Apache2 >= 2.0.54
+
+=item * mod_perl >= 2.0.0
+
+=item * Apache::DBI >= '0.97' [*]
+
+=back
+
+[*] required for connect_on_init() to work under mod_perl >= 2.0.1
+
+=head3 Apache 1.x 
+
+=item * building mod_perl-1.29 from source:
+
+    perl Makefile.PL USE_APXS=1 INSTALLDIRS=vendor WITH_APXS=/usr/sbin/apxs EVERYTHING=1 PERL_DEBUG=1
+
+    #MP_TRACE = 1 MP_DEBUG = 1 MP_USE_DSO = 1 MP_INST_APACHE2 = 1 MP_APXS = /usr/sbin/apxs2
+
+=head3 Apache 2.x 
+
+=head4 removing Apache on RHEl3
+
+On RHEL3 I had to remove these packages in order to fully remove MySQL.
+
+As C<root>:
+
+    rpm -e \
+    httpd-2.0.46-46.2.ent \
+    httpd-devel-2.0.46-46.2.ent \
+    redhat-config-httpd-1.1.0-4.30.2 \
+    mod_perl-1.99_09-10.ent \
+    mod_authz_ldap-0.22-5 \
+    mod_auth_pgsql-2.0.1-4.ent \
+    mod_python-3.0.3-5.ent \
+    mod_auth_mysql-20030510-2.ent \
+    mod_ssl-2.0.46-46.2.ent \
+    webalizer-2.01_10-15.ent \
+    mod_perl-1.99_09-10.ent \
+    mod_auth_pgsql-2.0.1-4.ent \
+    mod_python-3.0.3-5.ent \
+    mod_auth_mysql-20030510-2.ent \
+    mod_ssl-2.0.46-46.2.ent \
+    squirrelmail-1.4.3a-11.EL3 \
+    php-4.3.2-25.ent \
+    php-imap-4.3.2-25.ent \
+    php-ldap-4.3.2-25.ent \
+    php-mysql-4.3.2-25.ent \
+    php-odbc-4.3.2-25.ent \
+    php-pgsql-4.3.2-25.ent 
+
+    rm -rf /etc/httpd
+
+=head4 installing Apache2 from source
+
+    tar -jxvf httpd-2.0.54.tar.bz2
+    cd httpd-2.0.54
+    ./configure \
+    --disable-suexec \
+    --with-perl=/usr/bin/perl \
+    --with-port=80 \
+    --with-program-name=apache2 \
+    --with-devrandom=/dev/urandom \
+    --prefix           /usr \
+    --exec_prefix      /usr \
+    --bindir           /usr/bin \
+    --sbindir          /usr/sbin \
+    --libdir           /usr/lib \
+    --libexecdir       /usr/lib/apache2/modules \
+    --mandir           /usr/share/man \
+    --infodir          /usr/share/info \
+    --includedir       /usr/include/apache2 \
+    --datadir          /var/www/localhost \
+    --sysconfdir       /etc/apache2/conf \
+    --localstatedir    /var
+    make
+    su
+    make install
+    exit
+    cd ..
+
+=head4 installing mod_perl 2.x
+
+    tar -zxvf mod_perl-2.0.1.tar.gz
+    cd mod_perl-2.0.1
+    perl Makefile.PL
+    (apxs = /usr/sbin/apxs)
+    make
+    su
+    make install
+    echo "LoadModule perl_module /usr/lib/apache2/modules/mod_perl.so" >> /etc/apache2/conf/apache2.conf
+    exit
+
+    apachectl configtest
+    Syntax OK
+
+=head4 installing and configuring Nebulous
+
+    tar -zvxf Nebulous-0.01.tar.gz
+    cd Nebulous-0.01
+    perl Build.PL -axps /usr/sbin/apxs
+    ./Build
+    ./Build test
+    su
+    ./Build install
+
+
+    vi /etc/apache2/conf/startup.pl
+    (change Group to "Group nebulous")
+
+    cp fooconf /etc/apache2/conf/startup.pl
+    echo "PerlPostConfigRequire /etc/apache2/conf/startup.pl" >> /etc/apache2/conf/apache2.conf
+
+
+=head3 configurating Apache to act as a Nebulous/SOAP server
+
+=item * add the "nebulous" group to /etc/group
+=item * configure Apache to run as the nebulous group. 
+
+    Group nebulous
+
+Note that in theory the C<perchild> MPM can run vhosts as differenet
+users/groups but this module is currently non-funcitonal.
+
+L<http://httpd.apache.org/docs/trunk/mod/perchild.html>
+
+=item * configure a path for Neublous
+
+Make sure mod_perl is being loaded into Apache.  In order to do this on
+gentoo, you must edit /etc/config.d/apache2 and add C<-DPERL> to
+C<APACHE2_OTPS>.
+
+    cat <<END >> /etc/apache2/conf/apache2.conf
+    <Location /nebulous>
+        SetHandler perl-script
+        PerlResponseHandler Apache2::SOAP
+        PerlSetVar dispatch_to "PerlHandler Nebulous::Server::SOAP"
+        PerlSetVar options "compress_threshold => 10000"
+    </Location>
+    END
+
+    apachectl configtest
+    Syntax OK
+
+=item * initialize Nebulous database connections from C<startup.pl>
+
+    my $dsn         = 'DBI:mysql:database=nebulous:host=localhost';
+    my $dbuser      = 'nebulous';
+    my $dbpasswd    = '@neb@';
+
+    Apache::DBI->connect_on_init( $dsn, $dbuser, $dbpasswd );
+    Nebulous::Server::SOAP->new_on_init(
+        dsn         => $dsn,
+        dbuser      => $dbuser,
+        dbpasswd    => $dbpasswd,
+        log_level   => 'all',
+    );
+
+# out of date from here down...
+
+#
+# CGI interface
+#
+
+ScriptAlias /nebulous /usr/local/apache/perl/imageserver.pl
+
+<Directory "/usr/local/apache/perl">
+        AllowOverride None
+        Options None
+        Order allow,deny
+        Allow from all
+</Directory>
+
+PerlModule Apache::PerlRun
+<Location /perl>
+        SetHandler perl-script
+        PerlHandler Apache::PerlRun
+        Options ExecCGI
+        allow from all
+        PerlSendHeader On
+</Location>
+
+#
+# Nebulous::Apache interface
+#
+
+PerlModule Apache::DBI
+PerlModule Nebulous::Apache
+
+<Location /nebulous>
+        SetHandler perl-script
+        PerlHandler Nebulous::Apache
+</Location>
+
+- setup the server
+
+As a CGI, will with either Apache 1.3.x or 2.0.x
+
+cp scripts/imagesever.pl /var/www/localhost/cgi-bin
+chmod 755 /var/www/localhost/cgi-bin/imageserver.pl
+touch /tmp/imageserver.log
+chmod 1777 /tmp/imageserver.log
+
+=head2 Testing the Nebulous Server
+
+You can test your configuration with the C<telnet> utility.
+
+    $ telnet localhost 80
+    Trying 127.0.0.1...
+    Connected to localhost.localdomain (127.0.0.1).
+    Escape character is '^]'.
+    GET /nebulous HTTP/1.0
+
+    HTTP/1.1 500 Internal Server Error
+    Date: Wed, 31 Aug 2005 01:10:47 GMT
+    Server: Apache/2.0.54 (Unix) mod_perl/2.0.1 Perl/v5.8.6
+    Content-Length: 645
+    Connection: close
+    Content-Type: text/html; charset=iso-8859-1
+    .
+    .
+
+    Connection closed by foreign host.
+
+If you get an HTTP 5xx code check your apache error_log
+
+
+=head2 MySQL Configuration/tuning
+
+in /etc/mysql/my.cnf
+under [mysqld]
+increase the number of alloweed connections, e.g.
+max_connections = 200
+
+Nebulous makes heavy use of MySQL's C<innodb> table type.  Try configuring
+MySQL with these parameters:
+
+    innodb_log_files_in_group = 2
+    innodb_buffer_pool_size = as big as possible (512M+)
+    innodb_log_buffer_size= 16M
+    innodb_log_file_size=10M
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/tmp.txt
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/tmp.txt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/docs/tmp.txt	(revision 21994)
@@ -0,0 +1,44 @@
+client
+--
+new
+
+new_file
+                new_file
+                open_file
+
+find_file
+    find_instance
+
+open_file
+    find_file
+
+delete_file
+                delete_file
+    nuke
+
+copy_file
+    open_file
+    new_file
+
+move_file
+    copy_file
+    delete_file
+
+replicate_file
+    open_file
+                replicate_file
+
+cull_file
+    find_instance
+    delete_instance
+
+delete_instance
+    nuke
+                delete_instance
+
+find_instance
+                find_instance
+
+# missing
+file_stat
+lock ?
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/examples/Makefile
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/examples/Makefile	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/examples/Makefile	(revision 21994)
@@ -0,0 +1,5 @@
+NEB_CFLAGS=`pkg-config nebclient --cflags`
+NEB_LIBS=`pkg-config nebclient --libs`
+
+nebexample: nebexample.c
+	$(CC) $(NEB_CFLAGS) $(CFLAGS) $(NEB_LIBS) $< -o $@
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/examples/nebexample.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/examples/nebexample.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/examples/nebexample.c	(revision 21994)
@@ -0,0 +1,45 @@
+// gcc `pkg-config nebclient --cflags --libs` example.c -o example
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <nebclient.h>
+
+#define NEB_SERVER  "http://podb1.ifa.hawaii.edu:80/nebulous"
+#define NEB_KEY     "foobarbaz"
+
+int main (int argc, char **argv) {
+    nebServer       *server = NULL;
+    char            *key = NEB_KEY;
+
+    server = nebServerAlloc(NEB_SERVER);
+    if (!server) {
+        printf("nebServerAlloc() failed\n");
+        exit(EXIT_FAILURE);
+    }
+
+    // make sure there isn't already a file named "foobarbaz" so this example
+    // doesn't cause an error
+    nebDelete(server, key);
+
+    int fh = nebCreate(server, key, 0, NULL, NULL, NULL);
+    if (fh < 0) {
+        printf( "nebCreate() failed: %s\n", nebErr(server));
+        exit(EXIT_FAILURE);
+    }
+
+    // fh is a file descriptor
+    close(fh);
+
+    if (!nebReplicate(server, key, NULL, NULL)) {
+        printf( "nebReplicate() failed: %s\n", nebErr(server));
+        exit(EXIT_FAILURE);
+    }
+
+    if (!nebDelete(server, key)) {
+        printf( "nebDelete() failed: %s\n", nebErr(server));
+        exit(EXIT_FAILURE);
+    }
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/examples/nebexample.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/examples/nebexample.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/examples/nebexample.pl	(revision 21994)
@@ -0,0 +1,28 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Nebulous::Client;
+
+my $neb = Nebulous::Client->new(
+    proxy   => 'http://podb1.ifa.hawaii.edu:80/nebulous'
+);
+
+my $key = shift || 'foobarbaz';
+
+# make sure there isn't already a file named "foobarbaz" so this example
+# doesn't cause an error
+$neb->delete($key);
+
+my $fh = $neb->create($key);
+die "can't create file $key " unless $fh;
+close($fh);
+
+if (!$neb->replicate($key)) {
+    die "can't replicate object $key";
+}
+
+if (!$neb->delete($key)) {
+    die "can't delete object $key";
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server.pm	(revision 21994)
@@ -0,0 +1,1304 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: Server.pm,v 1.49 2008-01-25 02:11:23 jhoblitt Exp $
+
+package Nebulous::Server;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = '0.06';
+
+use base qw( Class::Accessor::Fast );
+
+use DBI;
+use File::ExtAttr qw( setfattr );
+use Log::Log4perl;
+use Nebulous::Server::Config;
+use Nebulous::Server::Log;
+use Nebulous::Server::SQL;
+use Nebulous::Util qw( :standard );
+use Params::Validate qw( validate_pos SCALAR SCALARREF );
+use URI::file;
+
+__PACKAGE__->mk_accessors(qw( log sql config ));
+
+sub new {
+    my $class = shift;
+
+    # let Nebulous::Server::Config validate our params
+    my $config = Nebulous::Server::Config->init( @_ );
+
+    # log4perl is not avaliable until we call init()
+    Nebulous::Server::Log->init($config);
+    my $log = Log::Log4perl::get_logger( "Nebulous::Server" );
+
+    my $sql = Nebulous::Server::SQL->new;
+
+    $log->debug( "entered - @_" );
+
+    my $db;
+    eval {
+        $db = DBI->connect(
+            $config->dsn,
+            $config->dbuser,
+            $config->dbpasswd,
+            {
+                RaiseError => 1,
+                PrintError => 0,
+                AutoCommit => 0,
+            },
+        );
+
+        $db->do( $sql->set_transaction_model );
+
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ( $@ ) {
+        $db->rollback if $db;
+        $log->debug("rollback");
+        $log->logdie( "database error: $@" );
+    }
+
+    $log->debug( "connected to database: ", sub { $db->data_sources; } );
+
+    my $self = bless {}, ref $class || $class;
+    $self->log($log);
+    $self->sql($sql);
+    $self->db($db);
+    $self->config($config);
+
+    $log->debug( "leaving" );
+    
+    return $self;
+}
+
+sub db {
+    my $self = shift;
+
+    if (@_) {
+        $self->{db} = $_[0];
+        return $self;
+    }
+
+    my $log     = $self->log;
+    my $sql     = $self->sql;
+    my $config  = $self->config;
+
+    # if the dbh is still alive, return it
+    if (defined $self->{db} and $self->{db}->ping) {
+        $log->debug("db handle is still alive");
+        return $self->{db};
+    }
+    # otherwise create a new connection
+    $log->debug("db handle is dead");
+
+    # if we're running under mod_perl & Apache::DBI is loaded we want to
+    # reconnect to the database everytime the dbh is requested.  The rational is
+    # that if we're running under mod_perl this is probably a log running
+    # processes and the database might have gone away on us.  Apache::DBI will
+    # take care of getting a valid dbh back.
+    if ($INC{'Apache/DBI.pm'} && $ENV{MOD_PERL}) {
+        my $db;
+        eval {
+            $db = DBI->connect(
+                $config->dsn,
+                $config->dbuser,
+                $config->dbpasswd,
+                {
+                    RaiseError => 1,
+                    PrintError => 0,
+                    AutoCommit => 0,
+                },
+            );
+
+            $db->do( $sql->set_transaction_model );
+
+            $db->commit;
+            $log->debug("commit");
+        };
+        if ( $@ ) {
+            $db->rollback if $db;
+            $log->debug("rollback");
+            $log->logdie( "database error: $@" );
+        }
+
+        $self->{db} = $db;
+
+        return $db;
+    }
+
+    return $self->{db};
+}
+
+
+sub create_object
+{
+    my $self = shift;
+
+    my ($key, $vol_name) = validate_pos(@_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                # check that the volume requested is valid
+                'is valid volume name' => sub { $self->_is_valid_volume_name($_[0]) },
+            },
+            optional    => 1,
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug( "entered - @_" );
+
+    {
+        my $volume;
+        ($volume, $key) = parse_neb_key($key);
+        if (defined $volume) {
+            die "$volume is not a valid volume name"
+                unless $self->_is_valid_volume_name($volume);
+        }
+        $vol_name ||= $volume;
+
+    }
+
+    my ($uri, $vol_id);
+    eval {
+        {
+            # create storage_object
+            my $query = $db->prepare_cached( $sql->new_object ); 
+            $query->execute('NULL', $key);
+        }
+
+        my $object_id;
+        {
+            # get object ID
+            my $query = $db->prepare_cached( $sql->last_insert_id );
+            $query->execute;
+            ($object_id) = $query->fetchrow_array;
+            # XXX finish seems to be required when using LAST_INSERT_ID() or we
+            # get a warning about the stmt handling still be active the next
+            # time LAST_INSERT_ID() is invoked
+            $query->finish;
+        }
+
+        {
+            # create storage_object_attr
+            my $query = $db->prepare_cached( $sql->new_object_attr ); 
+            $query->execute($object_id);
+        }
+
+        {
+            # create instance with no URI
+            my $query = $db->prepare_cached( $sql->new_object_instance );
+            $query->execute;
+        }
+
+        my $ins_id;
+        {
+            # get instance ID
+            my $query = $db->prepare_cached( $sql->last_insert_id );
+            $query->execute;
+            ($ins_id) = $query->fetchrow_array;
+            # XXX finish seems to be required when using LAST_INSERT_ID() or we
+            # get a warning about the stmt handling still be active the next
+            # time LAST_INSERT_ID() is invoked
+            $query->finish;
+        }
+
+        # Unfortunately, since we want to use the instance row's ID as part of the
+        # actual on disk file name we can't try to create the file until after
+        # we've create both a new storage_storage object and instance.
+
+        # TODO add some stuff here to retry if unsucessful
+        ($uri, $vol_id) = $self->_create_empty_instance_file($key, $ins_id, $vol_name);
+        $log->debug("created $uri on volume ID: $vol_id");
+
+        {
+            # update the instance with URI & vol_id that the file is on
+            my $query = $db->prepare_cached( $sql->update_instance_uri );
+            # vol_id, uri, ins_id
+            $query->execute($vol_id, "$uri", $ins_id);
+        }
+
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("error: $@");
+    }
+
+    $log->debug("leaving");
+
+    return "$uri";
+}
+
+sub rename_object
+{
+    my $self = shift;
+
+    my ($key, $newkey) = validate_pos(@_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+        # make sure the "newkey" doesn't already exist
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is not valid object key' => sub { not $self->_is_valid_object_key($_[0]) },
+            },
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug("entered - @_");
+
+    # ignore volumes
+    $key    = parse_neb_key($key);
+    $newkey = parse_neb_key($newkey);
+
+    eval {
+        # rename storage_object
+        my $query = $db->prepare_cached($sql->rename_object); 
+        # this SQL statment takes the new key name as the first param
+        my $rows = $query->execute($newkey, $key);
+
+        # if we affected more then one row something very bad has happened.
+        unless ($rows == 1) {
+            $log->logdie("affected row count is $rows instead of 1");
+        }
+
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    $log->debug("leaving");
+
+    return $newkey;
+}
+
+
+sub replicate_object
+{
+    my $self = shift;
+
+    my ($key, $vol_name) = validate_pos(@_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                # check that the volume name requested is valid
+                'is valid volume name' => sub { $self->_is_valid_volume_name($_[0]) },
+            },
+            optional    => 1,
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug("entered - @_");
+
+    {
+        my $volume;
+        ($volume, $key) = parse_neb_key($key);
+        if (defined $volume) {
+            die "$volume is not a valid volume name"
+                unless $self->_is_valid_volume_name($volume);
+        }
+        $vol_name ||= $volume;
+    }
+
+    my ($uri, $vol_id);
+    eval {
+        my $so_id;
+        {
+            my $query = $db->prepare_cached( $sql->get_object_instances );
+            my $rows = $query->execute($key, 1);
+
+            unless ( $rows > 0 ) {
+                $query->finish;
+                $db->rollback;
+                $log->debug("rollback");
+                $log->logdie( "storage object does not exist" );
+            }
+
+            $so_id = $query->fetchrow_hashref->{ 'so_id' };
+            $query->finish;
+        }
+
+        {
+            my $query = $db->prepare_cached( $sql->new_instance );
+            $query->execute($so_id);
+        }
+
+        my $ins_id;
+        {
+            my $query = $db->prepare_cached( $sql->last_insert_id );
+            $query->execute();
+            ($ins_id) = $query->fetchrow_array;
+            # XXX finish seems to be required when using LAST_INSERT_ID() or we
+            # get a warning about the stmt handling still be active the next
+            # time LAST_INSERT_ID() is invoked
+            $query->finish;
+        }
+
+        # Unfortunately, since we want to use the instance row's ID as part of
+        # the actual on disk file name we can't try to create the file until
+        # after we've create both a new storage_storage object and instance.
+
+        # TODO add some stuff here to retry if unsucessful
+        ($uri, $vol_id) = $self->_create_empty_instance_file($key, $ins_id, $vol_name);
+
+        {
+            my $query = $db->prepare_cached( $sql->update_instance_uri );
+            # vol_id, uri, ins_id
+            $query->execute($vol_id, $uri, $ins_id);
+        }
+
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("error: $@");
+    }
+
+    $log->debug("leaving");
+
+    return "$uri";
+}
+
+sub lock_object
+{
+    my $self = shift;
+
+    my ( $key, $type ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is read or write' => sub { $_[0] =~ /^(?:read|write)$/ },
+            },
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug( "entered - @_" );
+
+    # ignore volume
+    $key = parse_neb_key($key);
+
+    my $so_id;
+    my $read_lock;
+    my $write_lock;
+    my $query;
+
+    eval {
+        {
+            # this will set update locks
+            $query = $db->prepare_cached( $sql->get_object_locks );
+            my $rows = $query->execute( $key );
+            unless ( $rows == 1 ) {
+                $log->logdie( "storage object does not exist" );
+            }
+
+            my $row = $query->fetchrow_hashref;
+            $query->finish;
+
+            $so_id      = $row->{ 'so_id' };
+            $read_lock  = $row->{ 'read_lock' };
+            $write_lock = $row->{ 'write_lock' };
+        }
+
+        if ($type eq 'write') {
+            # can't set a write lock twice and
+            # can't set a write lock if there are read locks
+            if ($write_lock) {
+                $log->logdie("can not write lock twice");
+            }
+            
+            if ($read_lock > 0) {
+                $log->logdie("can not write lock after read lock");
+            }
+
+            {
+                my $query = $db->prepare_cached( $sql->set_write_lock );
+                my $rows = $query->execute($key);
+            
+                # if we affected more then one row something very bad has happened.
+                unless ($rows == 1) {
+                    $log->logdie("affected row count is $rows instead of 1");
+                }
+
+            }
+        } elsif ($type eq 'read') {
+            # can't set a read lock if there's a write lock
+            if ($write_lock) {
+                $log->logdie("can not read lock after write lock");
+            }
+
+            {
+                my $query = $db->prepare_cached( $sql->increment_read_lock );
+                my $rows = $query->execute($key);
+            
+                # if we affected more then one row something very bad has happened.
+                unless ($rows == 1) {
+                    $log->logdie("affected row count is $rows instead of 1");
+                }
+            }
+        }
+
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("error: $@");
+    }
+
+    $log->debug("leaving");
+
+    return 1;
+}
+
+sub unlock_object
+{
+    my $self = shift;
+
+    my ( $key, $type ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is read or write' => sub { $_[0] =~ /^(?:read|write)$/ },
+            },
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug( "entered - @_" );
+
+    # ignore volume
+    $key = parse_neb_key($key);
+
+    my $so_id;
+    my $read_lock;
+    my $write_lock;
+    my $query;
+
+    eval {
+        {
+            # this will set update locks
+            $query = $db->prepare_cached( $sql->get_object_locks );
+            my $rows = $query->execute($key);
+            unless ($rows == 1) {
+                $log->logdie("storage object does not exist");
+            }
+
+            my $row = $query->fetchrow_hashref;
+            $query->finish;
+
+            $so_id      = $row->{ 'so_id' };
+            $read_lock  = $row->{ 'read_lock' };
+            $write_lock = $row->{ 'write_lock' };
+        }
+
+        if ($type eq 'write') {
+            # can't remove a write lock if it doesn't exist
+            if ($read_lock) {
+                $log->logdie("can not have a write lock under a read lock");
+            }
+
+            unless ($write_lock) {
+                $log->logdie("can not remove non-existant write lock");
+            }
+
+            {
+                my $query = $db->prepare_cached( $sql->delete_write_lock );
+                my $rows = $query->execute($key);
+            
+                # if we affected more then one row something very bad has happened.
+                unless ($rows == 1) {
+                    $log->logdie("affected row count is $rows instead of 1");
+                }
+            }
+        } elsif ($type eq 'read') {
+            # can't remove a read lock if there's a write lock and
+            # can't remove a read lock if there aren't any
+            if ($write_lock) {
+                $log->logdie("can not have a read lock under a write lock");
+            }
+               
+            if ($read_lock == 0) {
+                $log->logdie("can not remove non-existant read lock");
+            }
+
+            {
+                my $query = $db->prepare_cached( $sql->decrement_read_lock );
+                my $rows = $query->execute($key);
+            
+                # if we affected more then one row something very bad has happened.
+                unless ($rows == 1) {
+                    $log->logdie("affected row count is $rows instead of 1");
+                }
+
+            }
+        }
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("error: $@");
+    }
+
+    $log->debug( "leaving" );
+
+    return 1;
+}
+
+
+sub setxattr_object
+{
+    my $self = shift;
+
+    my ($key, $name, $value, $flags) = validate_pos(@_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is read or write' => sub { $_[0] =~ /^(?:create|replace)$/i },
+            },
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug("entered - @_");
+
+    # ignore volume
+    $key = parse_neb_key($key);
+
+    eval {
+        my $query;
+
+        if ($flags eq 'create') {
+            $query = $db->prepare_cached( $sql->new_object_xattr );
+        } else {
+            # replace
+            $query = $db->prepare_cached( $sql->replace_object_xattr );
+        }
+
+        # name, value, ext_id
+        my $rows = $query->execute($name, $value, $key);
+
+        # if we affected more then one row something very bad has happened.
+        if ($flags eq 'create') {
+            unless ($rows == 1) {
+                $log->logdie( "affected row count is $rows instead of 1" );
+            }
+        } else {
+            unless ($rows == 2) {
+                $log->logdie( "affected row count is $rows instead of 2" );
+            }
+        }
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    eval { 
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    $log->debug("leaving");
+
+    return 1;
+}
+
+
+sub getxattr_object
+{
+    my $self = shift;
+
+    my ($key, $name) = validate_pos(@_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+        {
+            type        => SCALAR,
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug("entered - @_");
+
+    # ignore volume
+    $key = parse_neb_key($key);
+
+    my $query;
+    eval {
+        $query = $db->prepare_cached( $sql->get_object_xattr );
+        # ext_id, name
+        my $rows = $query->execute($key, $name);
+
+        # if we affected more then one row something very bad has happened.
+        unless ($rows == 1) {
+            $log->logdie( "affected row count is $rows instead of 1" );
+        }
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    my $row = $query->fetchrow_hashref;
+    my $value = $row->{ 'value' };
+    $query->finish;
+
+    $log->debug("leaving");
+
+    return $value;
+}
+
+
+sub listxattr_object
+{
+    my $self = shift;
+
+    my ($key) = validate_pos(@_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug("entered - @_");
+
+    # ignore volume
+    $key = parse_neb_key($key);
+
+    my $query;
+    eval {
+        $query = $db->prepare_cached( $sql->list_object_xattr );
+        # ext_id
+        my $rows = $query->execute($key);
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    my @xattrs;
+    while (my $row = $query->fetchrow_hashref) {
+        push @xattrs, $row->{ 'name' };
+    }
+
+    $log->debug("leaving");
+
+    return @xattrs;
+}
+
+
+sub removexattr_object
+{
+    my $self = shift;
+
+    my ($key, $name) = validate_pos(@_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+        {
+            type        => SCALAR,
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug("entered - @_");
+
+    # ignore volume
+    $key = parse_neb_key($key);
+
+    my $query;
+    eval {
+        $query = $db->prepare_cached( $sql->remove_object_xattr );
+        # ext_id, name
+        my $rows = $query->execute($key, $name);
+
+        # if we affected more then one row something very bad has happened.
+        unless ($rows == 1) {
+            $log->logdie( "affected row count is $rows instead of 1" );
+        }
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    eval { 
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    $log->debug("leaving");
+
+    return 1;
+}
+
+
+sub find_objects
+{
+    my $self = shift;
+
+    my ( $pattern ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug( "entered - @_" );
+
+    my $query;
+
+    eval {
+        $query = $db->prepare_cached( $sql->find_objects );
+        $query->execute( $pattern );
+    };
+    $log->logdie( "database error: $@" ) if $@;
+
+    my @keys;
+
+    while ( my $row = $query->fetchrow_hashref ) {
+        my $key = $row->{ 'ext_id' };
+        push @keys, $key if $key;
+    }
+
+    $log->debug( "no keys found" ) unless ( scalar @keys );
+
+    $log->debug( "leaving" );
+
+    return \@keys;
+}
+
+
+sub find_instances
+{
+    my $self = shift;
+
+    my ($key, $vol_name) = validate_pos(@_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                # check that the volume name requested is valid
+                'is valid volume name' => sub { $self->_is_valid_volume_name($_[0]) },
+            },
+            optional    => 1,
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug("entered - @_");
+
+    {
+        my $volume;
+        ($volume, $key) = parse_neb_key($key);
+        if (defined $volume) {
+            die "$volume is not a valid volume name"
+                unless $self->_is_valid_volume_name($volume);
+        }
+        $vol_name ||= $volume;
+    }
+
+    my $query;
+    eval {
+        if ($vol_name) {
+            $query = $db->prepare_cached( $sql->get_object_instances_by_vol_name );
+            # ext_id, name, available
+            my $rows = $query->execute($key, $vol_name, 1);
+            unless ($rows > 0) {
+                $query->finish;
+                $log->logdie("no instances on storage volume: $vol_name or volume is not available");
+            }
+        } else {
+            $query = $db->prepare_cached( $sql->get_object_instances );
+            # ext_id, available
+            my $rows = $query->execute($key, 1);
+            unless ($rows > 0) {
+                $query->finish;
+                $log->logdie("no instances available");
+            }
+        }
+    };
+    $log->logdie("database error: $@") if $@;
+
+    my @locations;
+
+    while (my $row = $query->fetchrow_hashref) {
+        my $instance = $row->{ 'uri' };
+        push @locations, $instance if $instance;
+    }
+
+    # XXX remove this?
+    $log->logdie("no instances found") unless (scalar @locations);
+
+    $log->debug("found: @locations");
+
+    $log->debug("leaving");
+
+    return \@locations;
+}
+
+
+sub delete_instance
+{
+    my $self = shift;
+
+    my ( $uri ) = validate_pos( @_,
+        {
+            type => SCALAR|SCALARREF,
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug( "entered - @_" );
+
+    eval {
+        my $so_id;
+        my $instances;
+        # get so_id
+        {
+            my $query = $db->prepare_cached( $sql->get_object_from_uri );
+            my $rows = $query->execute( $uri );
+
+            unless ( $rows > 0 ) {
+                $query->finish;
+                $log->logdie( "no instance is associated with uri" );
+            }
+
+            $so_id = $query->fetchrow_hashref->{ 'so_id' };
+            $query->finish;
+
+        }
+
+        {
+            my $query = $db->prepare_cached( $sql->get_instance_count );
+            $query->execute( $so_id );
+
+            $instances = $query->fetchrow_hashref->{ 'count(ins_id)' };
+            $query->finish;
+        }
+
+        # remove instance
+        {
+            my $query = $db->prepare_cached( $sql->delete_instance );
+            my $rows = $query->execute( $uri );
+            $query->finish;
+            
+            # if we affected something other then one row something very bad
+            # has happened
+            unless ( $rows == 1 ) {
+                $log->logdie( "affected row count is $rows instead of 1" );
+            }
+        }
+
+        # if we just deleted the last instance associated with a storage object
+        # remove it too
+        if ( $instances == 1 ) {
+            # we just removed the last instance
+            my $query = $db->prepare_cached( $sql->delete_object );
+            my $rows = $query->execute( $so_id );
+            $query->finish;
+
+            # if we affected something other then two rows something very bad
+            # has happened
+            # this will have to be changed in order to support hardlinks
+            unless ( $rows == 2 ) {
+                $log->logdie( "affected row count is $rows instead of 2" );
+            }
+        }
+
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie( "database error: $@" );
+    }
+
+    $log->debug( "leaving" );
+
+    return 1;
+}
+
+
+sub stat_object
+{
+    my $self = shift;
+
+    my ( $key ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug("entered - @_");
+
+    # ignore volume
+    $key = parse_neb_key($key);
+
+    my $stat;
+    eval {
+        my $query = $db->prepare_cached( $sql->stat_object );
+        my $rows = $query->execute($key);
+
+        unless ($rows == 1) {
+            $log->logdie("no storage object found");
+        }
+
+        $stat = $query->fetchrow_arrayref;
+        $query->finish;
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    $log->debug("leaving");
+
+    return $stat;
+}
+
+
+sub _get_storage_volume
+{
+    my $self = shift;
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    no warnings qw( uninitialized );
+    $log->debug( "entered - @_" );
+    use warnings;
+
+    my $name = shift;
+
+    my ($vol_id, $vol_path, $xattr);
+    eval {
+        # TODO cache this?
+        my $query;
+        my $rows;
+        if ( $name ) {
+            $query = $db->prepare_cached( $sql->get_storage_volume_by_name );
+            # %free, name, avaiable, allocate
+            $rows = $query->execute(0.95, $name, 1, 1);
+            # XXX destinguish between non-existant and unaviable
+            unless ($rows > 0) {
+                $query->finish;
+                $log->logdie("storage volume: $name is not available");
+            }
+            # when matching by name we shouldn't ever match more than once
+            if ($rows > 1) {
+                $query->finish;
+                $log->logdie("affected row count is $rows instead of 1");
+            }
+        } else {
+            $query = $db->prepare_cached( $sql->get_storage_volume );
+            # %free, avaiable, allocate
+            $rows = $query->execute(0.95, 1, 1);
+            # there has to be atleast one storage volume
+            unless ($rows > 0) {
+                $query->finish;
+                $log->logdie("no storage volume is available");
+            }
+        }
+
+        my $free;
+        ($vol_id, $vol_path, $xattr, $free) = $query->fetchrow_array;
+        $query->finish;
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    $log->logdie("failed to find a suitable volume" )
+        unless defined $vol_id and defined $vol_path;
+
+    $log->debug( "leaving" );
+
+    return ($vol_id, $vol_path, $xattr);
+}
+
+
+sub _is_valid_object_key
+{
+    my ($self, $key) = @_;
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    my $ext_id;
+    eval {
+        my $query = $db->prepare_cached( $sql->get_object ); 
+        $query->execute($key);
+        ($ext_id) = $query->fetchrow_array;
+        $query->finish;
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie( "database error: $@" );
+    }
+
+    if (defined $ext_id) {
+        return 1;
+    } 
+
+    return;
+}
+
+
+sub _is_valid_volume_name
+{
+    my ($self, $vol_name) = @_;
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    my ($vol_id, $vol_path);
+    eval {
+        my $query = $db->prepare_cached( $sql->get_volume_by_name ); 
+        $query->execute( $vol_name );
+        my $free;
+        ($vol_id, $vol_path, $free) = $query->fetchrow_array;
+        $query->finish;
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie( "database error: $@" );
+    }
+
+    if (defined $vol_id and defined $vol_path) {
+        return 1;
+    } 
+
+    return;
+}
+
+sub _create_empty_instance_file
+{
+    my $self = shift;
+
+    my ($key, $ins_id, $volume) = @_;
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    # Find the storage volume to use. 
+    # ->_get_storage_volume() throws an exception on failure.
+    my ($vol_id, $vol_path, $xattr);
+    my ($storage_filename);
+    my ($uri);
+    eval {
+        ($vol_id, $vol_path, $xattr) = $self->_get_storage_volume($volume);
+        $storage_filename = $self->_generate_storage_filename($key, $ins_id);
+        # XXX put a hook for directory hashing here
+        $uri = URI::file->new("$vol_path/$storage_filename");
+        $log->debug("generated uri $uri");
+        $self->_create_empty_file($uri->file);
+    };
+    if ($@) {
+        $log->logdie($@);
+    }
+
+    if ($xattr) {
+        my $path = $uri->file;
+        die "can not set xattr on $path: $!"
+            unless (setfattr($path, 'user.nebulous_key', $key));
+    }
+
+    return ($uri, $vol_id);
+}
+
+
+sub _create_empty_file
+{
+    my $self = shift;
+
+    my ($path) = @_;
+
+    # perl's open() can't do an O_CREAT | O_EXCL
+    die "file $path already exists" if (-e $path);
+
+    my $fh;
+    die "can not open $path: $!"
+        unless (open($fh, '>', $path));
+
+    die "can not close $path: $!"
+        unless (close($fh));
+
+    die "can not chmod $path: $!"
+        unless (chmod 0664, $path);
+
+    return $path;
+}
+
+
+sub _generate_storage_filename
+{
+    my $self = shift;
+
+    my ($key, $ins_id) = @_;
+
+    my $filename = $key;
+    # mangle '/'s into ':'
+    $filename =~ s|/|:|g;
+
+    return "$ins_id.$filename"
+}
+
+
+sub DESTROY
+{
+    my $self = shift;
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug( "entered" );
+
+    $self->db->disconnect;        
+
+    $log->debug( "disconnected from database: ", sub { $db->data_sources; } );
+
+    $log->debug( "leaving" );
+}
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server.pod
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server.pod	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server.pod	(revision 21994)
@@ -0,0 +1,134 @@
+=pod
+
+=head1 NAME
+
+Nebulous::Server - Nebulous server component
+
+=head1 SYNOPSIS
+
+    use Nebulous::Server;
+
+    Nebulous::Server->new( $dsn, $username, $passwd );
+    Nebulous::Server->db( $db );
+    Nebulous::Server->log( $log );
+    Nebulous::Server->sql( $sql );
+    Nebulous::Server->config( $config );
+    Nebulous::Server->create_object( $key, $volume );
+    Nebulous::Server->rename_object( $key, $newkey );
+    Nebulous::Server->replicate_object( $key, $volume );
+    Nebulous::Server->lock_object( $key, $type );
+    Nebulous::Server->unlock_object( $key, $type );
+    Nebulous::Server->setxattr_object( $key, $name, $value, $flags );
+    Nebulous::Server->getxattr_object( $key, $name );
+    Nebulous::Server->listxattr_object( $key );
+    Nebulous::Server->removexattr_object( $key );
+    Nebulous::Server->find_objects( $pattern );
+    Nebulous::Server->find_instances( $key, $volume );
+    Nebulous::Server->delete_instance( $uri );
+    Nebulous::Server->stat_object( $key );
+
+=head1 DESCRIPTION
+
+This is the server side component of the Nebulous system.  It is primarily a
+middle-ware abstraction of an SQL database.
+
+=head1 USAGE
+
+Typically, this module would not be directly interacted with (although, it is
+possible to do so).  It is intended that one or more intermediate transport
+layers are used (SOAP, XML-RPC, etc.)
+
+=head2 Import Parameters
+
+This module accepts no arguments to it's C<import> method and exports no
+I<symbols>.
+
+=head2 Methods
+
+=head3 Class Methods
+
+=over 4
+
+=item * setup( $dsn, $username, $passwd );
+
+Accepts 3 parameters, all are mandatory.  Returns Boolean true.  Throws an
+exception on error.
+
+=item * create_object( $key, $volume );
+
+Accepts 4 parameters, only the first is mandatory.  Returns a URI.  Throws an
+exception on error.
+
+=item * replicate_object( $key, $volume );
+
+Accepts 2 parameters, only the first is mandatory.  Returns a URI.  Throws an
+exception on error.
+
+=item * lock_object( $key, $type );
+
+Accepts 2 parameters, all are mandatory.  Returns Boolean true.   Throws an
+exception on error.
+
+=item * unlock_object( $key, $type );
+
+Accepts 2 parameters, all are mandatory.  Returns Boolean true.   Throws an
+exception on error.
+
+=item * find_instance( $key, $volume );
+
+Accepts 2 parameters, only the first is mandatory.  Returns an arrayref.
+Throws an exception on error.
+
+=item * delete_instance( $uri );
+
+Accepts 1 parameters, it is mandatory.  Returns Boolean true.  Throws an
+exception on error.
+
+=item * stat_object( $key );
+
+Accepts 1 parameters, it is mandatory.  Returns a list of: so_id, ext_id,
+read_lock, write_lock, epoch.
+
+=back
+
+=head1 DEVELOPER NOTES
+
+=head2 REFERENCES
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2004-2005  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the LICENSE file included with
+this module, or in the L<perlgpl> Pod as supplied with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Client>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server/Apache.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server/Apache.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server/Apache.pm	(revision 21994)
@@ -0,0 +1,25 @@
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id
+
+package Nebulous::Server::Apache;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = 0.01;
+
+use Nebulous::Server::SOAP;
+use SOAP::Transport::HTTP;
+
+my $server = SOAP::Transport::HTTP::Apache
+    ->dispatch_to( 'Nebulous::Server::SOAP' )
+    ->options({ compress_threshold => 10 * 1024 });
+
+no warnings qw( redefine );
+sub handler { $server->handler(@_); }
+use warnings;
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server/Config.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server/Config.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server/Config.pm	(revision 21994)
@@ -0,0 +1,52 @@
+# Copyright (C) 2005  Joshua Hoblitt
+#
+# $Id: Config.pm,v 1.2 2006-12-12 00:06:27 jhoblitt Exp $
+
+package Nebulous::Server::Config;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = 0.02;
+
+use base qw( Class::Accessor::Fast );
+
+use Nebulous::Util qw( %LEVELS );
+use Params::Validate qw( validate SCALAR );
+
+my $new_validate = {
+    dsn         => { type => SCALAR },
+    dbuser      => { type => SCALAR },
+    dbpasswd    => { type => SCALAR },
+    log_level   => {
+        type        => SCALAR,
+        optional    => 1,
+        default     => 'all',
+        callbacks   => {
+            'is valid level' => sub {
+                defined $LEVELS{ lc $_[0] };
+            },
+        },
+    },
+};
+
+__PACKAGE__->mk_ro_accessors( keys %$new_validate );
+
+sub init {
+    my $class = shift;
+
+    my %p = validate( @_, $new_validate );
+
+    # normalize log levels to lower-case
+    $p{ log_level } = lc $p{ log_level };
+
+    my $self = \%p;
+
+    bless $self, $class || ref $class;
+
+    return $self;
+}
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server/Log.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server/Log.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server/Log.pm	(revision 21994)
@@ -0,0 +1,62 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: Log.pm,v 1.6 2006-12-12 00:02:53 jhoblitt Exp $
+
+package Nebulous::Server::Log;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = '0.02';
+
+use Log::Log4perl;
+use Nebulous::Server::Config;
+
+sub init {
+    my ($self, $config) = @_;
+
+    my $dsn         = $config->dsn;
+    my $dbuser      = $config->dbuser;
+    my $dbpasswd    = $config->dbpasswd;
+
+    my $conf = <<END;
+    log4perl.category.Nebulous.Server = DEBUG, SERVERLOGFILE
+
+    log4perl.appender.SERVERLOGFILE           = Log::Log4perl::Appender::File
+    log4perl.appender.SERVERLOGFILE.filename  = /tmp/nebulous_server.log
+    log4perl.appender.SERVERLOGFILE.mode      = append
+    log4perl.appender.SERVERLOGFILE.layout    = Log::Log4perl::Layout::PatternLayout
+    log4perl.appender.SERVERLOGFILE.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} | %H | %p | %M - %m%n
+#   date | hostname | priority | method/sub - message\n
+
+    log4perl.appender.SQLLOG            = Log::Log4perl::Appender::DBI
+    log4perl.appender.SQLLOG.datasource = $dsn
+    log4perl.appender.SQLLOG.username   = $dbuser
+    log4perl.appender.SQLLOG.password   = $dbpasswd
+    log4perl.appender.SQLLOG.sql        = \
+    INSERT INTO log (timestamp, hostname, level, sub, message) \
+    VALUES          (%d,        %H,       %p,    %M,  %m)
+#        VALUES          (?,         ?,        ?,     ?,   ?)
+#        log4perl.appender.SQLLOG.params.1   = %d
+#        log4perl.appender.SQLLOG.params.2   = %H
+#        log4perl.appender.SQLLOG.params.3   = %p
+#        log4perl.appender.SQLLOG.params.4   = %M
+#        log4perl.appender.SQLLOG.params.5   = %m
+#        log4perl.appender.SQLLOG.usePreparedStmt = 1
+    log4perl.appender.SQLLOG.bufferSize = 2
+    log4perl.appender.SQLLOG.layout     = Log::Log4perl::Layout::NoopLayout
+    log4perl.appender.SQLLOG.warp_message = 0
+END
+
+    if ($INC{'Apache/DBI.pm'} && $ENV{MOD_PERL}) {
+        Log::Log4perl::init_once( \$conf );
+    } else {
+        Log::Log4perl::init( \$conf );
+    }
+
+    return 1;
+}
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server/SOAP.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server/SOAP.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server/SOAP.pm	(revision 21994)
@@ -0,0 +1,78 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: SOAP.pm,v 1.4 2007-05-02 00:42:52 jhoblitt Exp $
+
+package Nebulous::Server::SOAP;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = '0.02';
+
+import SOAP::Data 'name'; 
+use Apache2::Const -compile => qw(OK);
+use Nebulous::Server;
+use SOAP::Lite;
+
+our $AUTOLOAD;
+
+our @args;
+our $neb;
+
+sub new_on_init {
+    my $self = shift;
+
+    require mod_perl2;
+    require Apache2::Module;
+    require Apache2::ServerUtil;
+
+    @args = @_;
+
+    my $s = Apache2::ServerUtil->server;
+    $s->push_handlers(PerlChildInitHandler => \&init);
+
+    return $self;
+}
+
+sub init {
+    my $self = shift;
+
+    $neb = Nebulous::Server->new(@args);        
+
+    return Apache2::Const::OK;
+}
+
+sub AUTOLOAD {
+    my $self = shift;
+
+    my ( $package, $method ) = $AUTOLOAD =~ m/(?:(.+)::)([^:]+)$/;
+    return undef if $method eq 'DESTROY';
+
+    init() unless defined $neb;
+
+    die "process $$ has not been initialized"
+        unless defined $neb;
+
+    die "method $method does not exist in Nebulous::Server"
+        unless defined ${Nebulous::Server::}{$method};
+
+    # create a sub and install it in the package so successive calls to the
+    # same method don't have to go through AUTOLOAD
+    my $method_sub;
+    eval q|
+    $method_sub = sub {
+        my $self = shift;
+        return name( result => $neb->| . $method . q|( @_ ) );
+    }
+    |;
+    die $@ if $@;
+
+    no strict 'refs';
+    *{"${package}::${method}"} = $method_sub;
+    use strict;
+
+    # invoke the method we just created
+    return $self->$method(@_);
+}
+
+1;
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server/SQL.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server/SQL.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/lib/Nebulous/Server/SQL.pm	(revision 21994)
@@ -0,0 +1,453 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: SQL.pm,v 1.43 2008-01-22 21:27:46 jhoblitt Exp $
+
+package Nebulous::Server::SQL;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = '0.02';
+
+use base qw( Class::Accessor::Fast );
+
+my %sql = (
+    set_transaction_model   => qq{
+        SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
+    },
+    update_instance_uri => qq{
+        UPDATE instance
+        SET vol_id = ?, uri = ?
+        WHERE ins_id = ?
+    },
+    last_insert_id      => qq{
+        SELECT LAST_INSERT_ID()
+    },
+    new_object          => qq{
+        INSERT INTO storage_object
+        (so_id, ext_id, type)
+        VALUES (?, ?, 'REG_FILE')
+    },
+    new_object_attr  => qq{
+        INSERT INTO storage_object_attr
+        (so_id, read_lock, write_lock)
+        VALUES (?, 0, NULL)
+    },
+    delete_object       => qq{
+        DELETE
+            storage_object,
+            storage_object_attr 
+        FROM storage_object
+        JOIN storage_object_attr
+            USING (so_id)
+        WHERE storage_object.so_id = ?
+    },
+    new_object_instance => qq{
+        INSERT INTO instance 
+        VALUES (NULL, LAST_INSERT_ID(), 0, 'error', NULL, NULL, NULL, NULL)
+    },
+    new_instance        => qq{
+        INSERT INTO instance
+        VALUES (NULL, ?, 0, 'error', NULL,NULL, NULL, NULL)
+    },
+    get_object          => qq{
+        SELECT
+            so_id,
+            ext_id,
+            read_lock,
+            write_lock,
+            epoch,
+            mtime
+        FROM storage_object
+        JOIN storage_object_attr
+        USING (so_id)
+        WHERE ext_id = ?
+    },
+    stat_object          => qq{
+        SELECT
+            storage_object.so_id,
+            storage_object.ext_id,
+            read_lock,
+            write_lock,
+            storage_object_attr.epoch,
+            storage_object_attr.mtime,
+            COUNT(instance.so_id) as instances
+        FROM storage_object
+        JOIN storage_object_attr
+            USING (so_id)
+        JOIN instance
+            USING (so_id)
+        WHERE ext_id = ?
+        GROUP BY storage_object.so_id
+    },
+    # Note: this sets an update lock
+    get_object_locks    => qq{
+        SELECT
+            storage_object.so_id,
+            read_lock,
+            write_lock 
+        FROM storage_object
+        JOIN storage_object_attr
+        USING (so_id)
+        WHERE ext_id = ?
+        FOR UPDATE
+    },
+    new_object_xattr  => qq{
+        INSERT INTO storage_object_xattr
+            SELECT
+                so_id,
+                ?,
+                ?        
+            FROM storage_object
+            WHERE ext_id = ?
+    },
+    replace_object_xattr  => qq{
+        REPLACE INTO storage_object_xattr
+            SELECT
+                so_id,
+                ?,
+                ?        
+            FROM storage_object
+            WHERE ext_id = ?
+    },
+    list_object_xattr    => qq{
+        SELECT storage_object_xattr.name
+        FROM storage_object
+        JOIN storage_object_xattr
+        USING (so_id)
+        WHERE ext_id = ?
+    },
+    get_object_xattr    => qq{
+        SELECT storage_object_xattr.value
+        FROM storage_object
+        JOIN storage_object_xattr
+        USING (so_id)
+        WHERE ext_id = ?
+            AND name = ?
+    },
+    remove_object_xattr    => qq{
+        DELETE FROM storage_object_xattr
+        WHERE so_id = (SELECT so_id from storage_object where ext_id = ?)
+            AND name = ?
+    },
+    set_write_lock      => qq{
+        UPDATE storage_object_attr
+        JOIN storage_object
+        USING(so_id)
+        SET write_lock = 'write'
+        WHERE storage_object.ext_id = ?
+    },
+    delete_write_lock   => qq{
+        UPDATE storage_object_attr
+        JOIN storage_object
+        USING(so_id)
+        SET write_lock = NULL
+        WHERE ext_id = ?
+    },
+    increment_read_lock => qq{
+        UPDATE storage_object_attr
+        JOIN storage_object
+        USING(so_id)
+        SET read_lock = read_lock + 1
+        WHERE ext_id = ?
+    },
+    decrement_read_lock => qq{
+        UPDATE storage_object_attr
+        JOIN storage_object
+        USING(so_id)
+        SET read_lock = read_lock - 1
+        WHERE ext_id = ?
+    },
+    delete_instance     => qq{
+        DELETE FROM instance
+        WHERE uri = ?
+    },
+    get_object_from_uri   => qq{
+        SELECT so_id
+        FROM instance
+        WHERE uri = ?
+    },
+    get_instance_count   => qq{
+        SELECT count(ins_id)
+        FROM instance
+        WHERE so_id = ?
+    },
+    get_object_instances    => qq{
+        SELECT
+            storage_object.so_id,
+            uri,
+            assigned_vol_id
+        FROM storage_object
+        JOIN instance
+            USING (so_id)
+        JOIN mountedvol
+            USING(vol_id)
+        WHERE ext_id = ?
+            AND available = ?
+    },
+    get_object_instances_by_vol_name => qq{
+        SELECT
+            storage_object.so_id,
+            uri,
+            assigned_vol_id
+        FROM storage_object
+        JOIN instance
+            USING (so_id)
+        JOIN mountedvol
+            USING(vol_id)
+        WHERE ext_id = ?
+            AND name = ?
+            AND available = ?
+    },
+    get_storage_volume_by_name   => qq{
+        SELECT
+            vol_id,
+            path,
+            xattr,
+            total - used as free
+        FROM mountedvol
+        WHERE
+            used / total < ?
+            AND name = ?
+            AND available = ?
+            AND allocate = ?
+        ORDER BY free DESC
+        LIMIT 1
+    },
+    get_storage_volume          => qq{
+        SELECT
+            vol_id,
+            path,
+            xattr,
+            total - used as free
+        FROM mountedvol
+        WHERE
+            used / total < ?
+            AND available = ?
+            AND allocate = ?
+        ORDER BY free DESC
+        LIMIT 1
+    },
+    new_volume          => qq{
+        INSERT INTO volume (name, path, allocate, available, xattr)
+        VALUES (?, ?, TRUE, TRUE, FALSE)
+    },
+    get_volume_by_name => qq{
+        SELECT vol_id, name, path
+        FROM volume
+        WHERE name = ?
+    },
+    find_objects => qq{
+        SELECT *
+        FROM storage_object
+        WHERE ext_id REGEXP ?
+    },
+    rename_object => qq{
+        UPDATE storage_object
+        SET ext_id = ?
+        WHERE ext_id = ?
+    },
+);
+
+{
+    my @schema;
+
+    local $/ = '###';
+
+    foreach my $statement (<DATA>) {
+        last unless ( $statement =~ /\S+/ );
+        $statement =~ s/###//g;
+        push @schema, $statement;
+    }
+
+    $sql{get_db_schema} = \@schema;
+}
+
+{
+    my @clear = split /;/, <<END;
+SET FOREIGN_KEY_CHECKS=0;
+DROP TABLE IF EXISTS storage_object;
+DROP TABLE IF EXISTS storage_object_attr;
+DROP TABLE IF EXISTS storage_object_xattr;
+DROP TABLE IF EXISTS instance;
+DROP TABLE IF EXISTS lock_record;
+DROP TABLE IF EXISTS volume;
+DROP TABLE IF EXISTS mount;
+DROP TABLE IF EXISTS log;
+DROP TABLE IF EXISTS mountedvol;
+DROP PROCEDURE IF EXISTS getmountedvol;
+SET FOREIGN_KEY_CHECKS=1
+END
+    $sql{get_db_clear} = \@clear;
+}
+
+__PACKAGE__->mk_ro_accessors( keys %sql );
+
+sub new {
+    my $class = shift;
+
+    my $self = \%sql;
+
+    bless $self, $class || ref $class;
+
+    return $self;
+}
+
+1;
+
+__DATA__
+CREATE TABLE storage_object (
+    so_id BIGINT NOT NULL AUTO_INCREMENT,
+    ext_id VARCHAR(255) NOT NULL UNIQUE,
+    type enum('REG_FILE'),
+    PRIMARY KEY(so_id),
+    KEY(ext_id(64)),
+    KEY(type)
+) ENGINE=innodb;
+
+###
+
+CREATE TABLE storage_object_attr (
+    so_id BIGINT NOT NULL AUTO_INCREMENT,
+    read_lock TINYINT DEFAULT 0 NOT NULL,
+    write_lock ENUM( 'write' ),
+    epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    mtime TIMESTAMP,
+    PRIMARY KEY(so_id)
+) ENGINE=innodb;
+
+###
+
+CREATE TABLE storage_object_xattr (
+    so_id BIGINT NOT NULL AUTO_INCREMENT,
+    name VARCHAR(255),
+    value BLOB,
+    PRIMARY KEY(so_id, name)
+) ENGINE=innodb;
+
+###
+
+CREATE TABLE instance (
+    ins_id BIGINT NOT NULL AUTO_INCREMENT,
+    so_id BIGINT NOT NULL,
+    vol_id INT NOT NULL,
+    uri VARCHAR(255) NOT NULL UNIQUE,
+    sha1sum CHAR(40) ASCII,
+    assigned_vol_id INT,
+    epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    mtime TIMESTAMP,
+    PRIMARY KEY(ins_id),
+    KEY(so_id),
+    KEY(vol_id),
+    KEY(uri(64))
+) ENGINE=innodb;
+
+###
+
+CREATE TABLE lock_record (
+    so_id BIGINT NOT NULL,
+    type ENUM( 'read', 'write' ) NOT NULL,
+    epoch TIMESTAMP,
+    KEY(so_ID)
+) ENGINE=innodb;
+
+###
+
+CREATE TABLE volume (
+    vol_id INT NOT NULL AUTO_INCREMENT,
+    name VARCHAR(255) UNIQUE NOT NULL,
+    path VARCHAR(255) NOT NULL,
+    allocate BOOLEAN DEFAULT FALSE,
+    available BOOLEAN DEFAULT FALSE,
+    xattr BOOLEAN DEFAULT FALSE,
+    PRIMARY KEY(vol_id),
+    KEY(name(16)),
+    KEY(allocate),
+    KEY(available)
+) ENGINE=innodb;
+
+###
+
+CREATE TABLE mount (
+    mountpoint VARCHAR(255) NOT NULL,
+    total BIGINT NOT NULL,
+    used BIGINT NOT NULL,
+    PRIMARY KEY(mountpoint)
+) ENGINE=innodb;
+
+###
+
+CREATE TABLE log (
+    timestamp TIMESTAMP,
+    hostname VARCHAR(255),
+    level VARCHAR(255),
+    sub VARCHAR(255),
+    message VARCHAR(2048) NOT NULL,
+    PRIMARY KEY(timestamp)
+) ENGINE=innodb;
+
+###
+
+CREATE TABLE mountedvol(
+    mountpoint VARCHAR(255) NOT NULL,
+    total BIGINT NOT NULL,
+    used BIGINT NOT NULL,
+    vol_id INT NOT NULL,
+    name VARCHAR(255) NOT NULL,
+    path VARCHAR(255) NOT NULL,
+    allocate BOOLEAN DEFAULT FALSE,
+    available BOOLEAN DEFAULT FALSE,
+    xattr BOOLEAN DEFAULT FALSE,
+    KEY(vol_id),
+    KEY(allocate),
+    KEY(available)
+) ENGINE=innodb;
+
+###
+
+CREATE PROCEDURE getmountedvol() DETERMINISTIC
+BEGIN
+    DECLARE done BOOLEAN DEFAULT FALSE;
+    DECLARE vol_idvar INT;
+    DECLARE namevar VARCHAR(255);
+    DECLARE pathvar VARCHAR(255);
+    DECLARE allocatevar BOOLEAN;
+    DECLARE availablevar BOOLEAN;
+    DECLARE xattrvar BOOLEAN;
+    DECLARE trans_level VARCHAR(255);
+    DECLARE cur1 CURSOR FOR SELECT vol_id, name, path, allocate, available, xattr FROM volume;
+    DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = TRUE;
+
+    -- store the current transaction level
+    SELECT @@session.tx_isolation INTO trans_level; 
+
+    -- set trans level to repeatable-read so the volume table does not change
+    -- out from under our cursor
+    SET @@session.tx_isolation = 'REPEATABLE-READ';
+
+    -- iterate over the volume table finding the coresponding entry in the
+    -- mount table and inserting union of the volume & mount row into the
+    -- mountedvol table
+    OPEN cur1;
+
+    DELETE FROM mountedvol;
+
+    myloop: LOOP
+        FETCH cur1 INTO vol_idvar, namevar, pathvar, allocatevar, availablevar, xattrvar;
+        IF `done` THEN LEAVE myloop; END IF;
+        INSERT INTO mountedvol
+            SELECT mountpoint, total, used, vol_idvar, namevar, pathvar, allocatevar, availablevar, xattrvar
+            FROM
+                (SELECT *, INSTR(pathvar, mountpoint) = 1 as substring
+                FROM mount
+                ORDER BY substring DESC, LENGTH(mountpoint) DESC
+                LIMIT 1) as bar;
+    END LOOP myloop;
+    
+    CLOSE cur1;
+
+    -- restore the original transaction level
+    SET @@session.tx_isolation = trans_level;
+
+    COMMIT;
+END 
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/scripts/bench_test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/scripts/bench_test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/scripts/bench_test.pl	(revision 21994)
@@ -0,0 +1,41 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings FATAL => qw( all );
+
+use lib "./lib";
+
+use Benchmark qw( timethese );
+use Nebulous::Client;
+
+my $neb = Nebulous::Client->new(
+    proxy   => 'http://localhost:80/nebulous'
+);
+
+my $key = shift || 'foobar';
+
+eval { $neb->delete( $key ); };
+
+my $fh = $neb->create( $key );
+close $fh;
+
+
+timethese( -3,
+    {
+        'stat' => sub {
+            $neb->stat( $key );
+        },
+    }
+);
+
+$neb->delete( $key );
+
+timethese( -3,
+    {
+        'create/delete' => sub {
+            my $fh = $neb->create( $key );
+            close $fh;
+            $neb->delete( $key );
+        },
+    }
+);
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/scripts/nebulous.cgi
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/scripts/nebulous.cgi	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/scripts/nebulous.cgi	(revision 21994)
@@ -0,0 +1,15 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id
+ 
+use strict;
+use warnings FATAL => qw( all );
+
+use SOAP::Transport::HTTP;
+use Nebulous::Server;
+   
+SOAP::Transport::HTTP::CGI
+    -> dispatch_to( 'Nebulous::Server' )
+    -> handle;
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/scripts/ptest.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/scripts/ptest.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/scripts/ptest.pl	(revision 21994)
@@ -0,0 +1,49 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings FATAL => qw( all );
+
+use lib "./lib";
+
+use Nebulous::Client;
+
+my $neb = Nebulous::Client->new(
+    proxy   => 'http://localhost:80/nebulous'
+);
+
+my $key = shift || 'foobar';
+my $kids = shift || 1;
+
+foreach my $id ( 1..$kids ) {
+    my $pid = fork;
+
+    unless ( $pid )  {
+        my $fname = "${key}_$id";
+        my $fh = $neb->open_create( $fname );
+        die "can't create file $fname" unless $fh;
+
+        print $fh "fooby\n";
+
+        close $fh;
+
+        $fh = $neb->open( $fname, 'read' ) or die "can't open file";
+        close $fh;
+
+        $neb->lock( $fname, 'read' );
+        $neb->unlock( $fname, 'read' );
+        $neb->replicate( $fname );
+        $neb->cull( $fname );
+        $neb->find( $fname );
+        $neb->copy( $fname, $fname . "_copy" );
+        $neb->move( $fname, $fname . "_move" );
+        $neb->delete( $fname . "_copy" );
+        $neb->delete( $fname . "_move" );
+
+        exit 0;
+    }
+}
+
+while ( $kids ) {
+    wait();
+    $kids --;
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/.cvsignore	(revision 21994)
@@ -0,0 +1,3 @@
+TEST
+htdocs
+logs
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/00_distribution.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/00_distribution.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/00_distribution.t	(revision 21994)
@@ -0,0 +1,25 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2005  Joshua Hoblitt
+#
+# $Id: 00_distribution.t,v 1.2 2007-05-02 01:07:56 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use lib qw( ./lib ./t );
+
+use Test::More;
+
+# example taken from Test::Distribution Pod
+
+BEGIN {
+    eval {
+        require Test::Distribution;
+    };
+    if($@) {
+        plan skip_all => 'Test::Distribution not installed';
+    } else {
+        import Test::Distribution not => [qw( versions use podcover )];
+    }
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/01_load.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/01_load.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/01_load.t	(revision 21994)
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 01_load.t,v 1.7 2005-06-30 02:35:06 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use lib qw( ./t ./lib );
+
+use Test::More tests => 8;
+
+BEGIN { use_ok( 'Nebulous::Client' ); }
+BEGIN { use_ok( 'Nebulous::Client::Log' ); }
+BEGIN { use_ok( 'Nebulous::Client::HTTP' ); }
+BEGIN { use_ok( 'Nebulous::Util' ); }
+BEGIN { use_ok( 'Nebulous::Server' ); }
+BEGIN { use_ok( 'Nebulous::Server::SQL' ); }
+BEGIN { use_ok( 'Nebulous::Server::Log' ); }
+BEGIN { use_ok( 'Nebulous::Server::SOAP' ); }
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/02_server_setup.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/02_server_setup.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/02_server_setup.t	(revision 21994)
@@ -0,0 +1,39 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 02_server_setup.t,v 1.5 2006-12-08 03:29:19 jhoblitt Exp $
+
+use strict;
+use warnings;
+
+use Test::More tests => 2;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Test::Nebulous;
+
+Test::Nebulous->setup;
+
+isa_ok(
+    Nebulous::Server->new(
+        dsn         => "DBI:mysql:database=test:host=localhost",
+        dbuser      => "test",
+        dbpasswd    => "",
+    ),
+    "Nebulous::Server"
+);
+
+Test::Nebulous->setup;
+
+eval {
+    Nebulous::Server->new(
+        dsn         => "DBI:mysql:database=foobar:host=localhost",
+        dbuser      => "baz",
+        dbpasswd    =>"boo",
+    );
+};
+like( $@, qr/DBI connect.*? failed/, "bad dsn/user/pass" );
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/03_server_create_object.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/03_server_create_object.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/03_server_create_object.t	(revision 21994)
@@ -0,0 +1,347 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 03_server_create_object.t,v 1.22 2008-01-25 02:06:08 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 65;
+
+use lib qw( ./t ./lib );
+
+use File::ExtAttr qw( getfattr );
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+use Test::URI;
+use URI::Split qw( uri_split );
+
+my $test_xattr = undef;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("foo");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("neb:/foo");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("neb://node01/foo");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("neb://node02/foo");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("/foo");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), '/foo', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+{
+    # key
+    my $uri = $neb->create_object("neb:///foo");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("/foo/");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), '/foo/', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("neb:/foo/");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), '/foo/', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("foo/");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo/', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("foo/bar");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo/bar"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo/bar', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("/foo/bar");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo/bar"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), '/foo/bar', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, volume
+    my $uri = $neb->create_object("foo", "node01");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+}
+
+Test::Nebulous->setup;
+
+{
+    # volume name override
+    my $uri = $neb->create_object("neb://node02/foo", "node01");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+}
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+    $neb->create_object("foo");
+};
+like($@, qr/Duplicate entry/, "object already exists");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("neb:/foo");
+    $neb->create_object("neb:/foo");
+};
+like($@, qr/Duplicate entry/, "object already exists");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo", 'node03');
+};
+like($@, qr/node03 is not available/, "request volume this is full");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("neb://node03/foo");
+};
+like($@, qr/node03 is not available/, "request volume this is full");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo", 'node04');
+};
+like($@, qr/node04 is not available/, "request volume with allocate = FALSE, available = FALSE");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("neb://node04/foo");
+};
+like($@, qr/node04 is not available/, "request volume with allocate = FALSE, available = FALSE");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo", 'node05');
+};
+like($@, qr/node05 is not available/, "request volume with allocate = FALSE , available = TRUE");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("neb://node05/foo");
+};
+like($@, qr/node05 is not available/, "request volume with allocate = FALSE , available = TRUE");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo", 'node06');
+};
+like($@, qr/node06 is not available/, "request volume with allocate = TRUE, available = FALSE");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("neb://node06/foo");
+};
+like($@, qr/node06 is not available/, "request volume with allocate = TRUE, available = FALSE");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo", 99);
+};
+like($@, qr/did not pass the \'is valid volume name\'/, "volume name doesn't exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("neb://99/foo");
+};
+like($@, qr/is not a valid volume name/, "volume name doesn't exist");
+
+Test::Nebulous->setup;
+
+eval {
+    # volume name override
+    $neb->create_object("neb://99/foo", "node01");
+};
+like($@, qr/is not a valid volume name/, "volume name doesn't exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object();
+};
+like($@, qr/1 - 2 were expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object(1, "node01", 3);
+};
+like($@, qr/1 - 2 were expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/04_server_replicate_object.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/04_server_replicate_object.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/04_server_replicate_object.t	(revision 21994)
@@ -0,0 +1,124 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 04_server_replicate_object.t,v 1.10 2007-05-08 02:27:42 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 16;
+
+use lib qw( ./t ./lib );
+
+use File::ExtAttr qw( getfattr );
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+use Test::URI;
+use URI::Split qw( uri_split );
+
+my $test_xattr = undef;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+{
+    # key
+    $neb->create_object("foo");
+    my $uri = $neb->replicate_object("foo");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, $volume
+    $neb->create_object("foo");
+    my $uri = $neb->replicate_object("foo", "node01");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, $volume
+    $neb->create_object("foo");
+    my $uri1 = $neb->replicate_object("foo", "node01");
+    my $uri2 = $neb->replicate_object("foo", "node02");
+
+    {
+        my ($scheme, $auth, $path, $query, $frag) = uri_split($uri1);
+        ok(-e $path, "file exists");
+        uri_scheme_ok($uri1, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+        is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+    }
+
+    {
+        my ($scheme, $auth, $path, $query, $frag) = uri_split($uri2);
+        ok(-e $path, "file exists");
+        uri_scheme_ok($uri2, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+        is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+    }
+}
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->replicate_object('foo');
+};
+like($@, qr/is valid object key/, 'storage object does not exist');
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+    $neb->replicate_object('foo', 'bar');
+};
+like($@, qr/is valid volume name/, 'storage volume does not exist');
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->replicate_object();
+};
+like($@, qr/1 - 2 were expected/, 'no params');
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+    $neb->replicate_object('foo', 'node01', 3);
+};
+like($@, qr/1 - 2 were expected/, 'too many params');
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/05_server_lock_object.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/05_server_lock_object.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/05_server_lock_object.t	(revision 21994)
@@ -0,0 +1,127 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 05_server_lock_object.t,v 1.8 2007-05-03 22:10:14 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 13;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+{
+    $neb->create_object("foo");
+
+    ok($neb->lock_object("foo", "read"), "read lock");
+}
+
+Test::Nebulous->setup;
+
+{
+    $neb->create_object("foo");
+
+    ok($neb->lock_object("foo", "read"), "read lock");
+    ok($neb->lock_object("foo", "read"), "read lock");
+}
+
+Test::Nebulous->setup;
+
+{
+    $neb->create_object("foo");
+
+    ok($neb->lock_object("foo", "write"), "write lock");
+}
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->lock_object("foo", "read");
+};
+like($@, qr/is valid object key/, "storage object does not exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->lock_object("foo", "write");
+};
+like($@, qr/is valid object key/, "storage object does not exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo", "write");
+    $neb->lock_object("foo", "write");
+};
+like($@, qr/can not write lock twice/, "can not write lock twice");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo", "read");
+    $neb->lock_object("foo", "write");
+};
+like($@, qr/can not write lock after read lock/, "can not write lock after read lock");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo", "write");
+    $neb->lock_object("foo", "read");
+};
+like($@, qr/can not read lock after write lock/, "can not read lock after write lock");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->lock_object();
+};
+like($@, qr/2 were expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo");
+};
+like($@, qr/2 were expected/, "not enough params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo", "both");
+};
+like($@, qr/is read or write/, "not read or write");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo", 'read', 3);
+};
+like($@, qr/2 were expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/06_server_unlock_object.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/06_server_unlock_object.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/06_server_unlock_object.t	(revision 21994)
@@ -0,0 +1,142 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 06_server_unlock_object.t,v 1.8 2007-05-03 22:10:14 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 14;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+{
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo", "read");
+
+    ok($neb->unlock_object("foo", "read"), "read unlock");
+}
+
+Test::Nebulous->setup;
+
+{
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo", "read");
+    $neb->lock_object("foo", "read");
+
+    ok($neb->unlock_object("foo", "read"), "read unlock");
+    ok($neb->unlock_object("foo", "read"), "read unlock");
+}
+
+Test::Nebulous->setup;
+
+{
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo", "write");
+
+    ok($neb->unlock_object("foo", "write"), "write unlock");
+}
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->unlock_object("foo", "read");
+};
+like($@, qr/is valid object key/, "storage object does not exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->unlock_object("foo", "write");
+};
+like($@, qr/is valid object key/, "storage object does not exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->unlock_object("foo", "read");
+};
+like($@, qr/can not remove non-existant read lock/, "no lock set");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->unlock_object("foo", "write");
+};
+like($@, qr/can not remove non-existant write lock/, "no lock set");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+    $neb->lock_object("foo", "write");
+
+    $neb->unlock_object("foo", "read");
+};
+like($@, qr/can not have a read lock under a write lock/, "read unlock under write lock");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+    $neb->lock_object("foo", "read");
+
+    $neb->unlock_object("foo", "write");
+};
+like($@, qr/can not have a write lock under a read lock/, "write unlock under read lock");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->unlock_object();
+};
+like($@, qr/2 were expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->unlock_object("foo");
+};
+like($@, qr/2 were expected/, "not enough params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->unlock_object("foo", "both");
+};
+like($@, qr/is read or write/, "not read or write");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->unlock_object("foo", 'read', 3);
+};
+like($@, qr/2 were expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/07_server_find_instances.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/07_server_find_instances.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/07_server_find_instances.t	(revision 21994)
@@ -0,0 +1,119 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 07_server_find_instances.t,v 1.8 2007-05-03 01:44:24 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 15;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::URI;
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("foo");
+
+    my $locations = $neb->find_instances("foo");
+
+    uri_scheme_ok($locations->[0], 'file');
+    is($uri, $locations->[0], "URIs match");
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri1 = $neb->create_object("foo");
+    my $uri2 = $neb->replicate_object("foo");
+
+    my $locations = $neb->find_instances("foo");
+
+    uri_scheme_ok($locations->[0], 'file');
+    uri_scheme_ok($locations->[1], 'file');
+    ok(eq_set([$uri1, $uri2], $locations), "URIs match");
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, volume
+    my $uri = $neb->create_object('foo', 'node01');
+
+    my $locations = $neb->find_instances('foo', 'node01');
+
+    uri_scheme_ok($locations->[0], 'file');
+    is($uri, $locations->[0], "URIs match");
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri1 = $neb->create_object("foo");
+    my $uri2 = $neb->replicate_object("foo");
+
+    my $locations = $neb->find_instances("foo", "node01");
+
+    uri_scheme_ok($locations->[0], 'file');
+    uri_scheme_ok($locations->[1], 'file');
+    ok(eq_set([$uri1, $uri2], $locations), "URIs match");
+}
+
+# object exists but instance is on a different volume
+Test::Nebulous->setup;
+
+eval {
+    # key, volume
+    my $uri = $neb->create_object('foo', 'node01');
+
+    my $locations = $neb->find_instances('foo', 'node02');
+};
+like($@, qr/no instances on storage volume/, 'instances on a different volume');
+
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->find_instances('foo');
+};
+like($@, qr/is valid object key/, "storage object does not exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+    $neb->find_instances('foo', 'bar');
+};
+like($@, qr/is valid volume name/, "storage volume does not exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->find_instances();
+};
+like($@, qr/1 - 2 were expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+    $neb->find_instances('foo', 'node01', 3);
+};
+like($@, qr/1 - 2 were expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/08_server_delete_instance.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/08_server_delete_instance.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/08_server_delete_instance.t	(revision 21994)
@@ -0,0 +1,73 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 08_server_delete_instance.t,v 1.8 2007-05-03 01:44:24 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 8;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+{
+    my $uri = $neb->create_object("foo");
+
+    ok($neb->delete_instance($uri), "delete instance");
+}
+
+Test::Nebulous->setup;
+
+{
+    my $uri1 = $neb->create_object("foo");
+    my $uri2 = $neb->replicate_object("foo");
+
+    ok($neb->delete_instance($uri1), "delete instance");
+
+    my $locations = $neb->find_instances("foo");
+
+    is($locations->[0], $uri2, "instance remains");
+
+    ok($neb->delete_instance( $uri2 ), "delete instance");
+
+    eval {
+        $neb->find_instances("foo");
+    };
+    like($@, qr/is valid object key/, "storage object was deleted");
+}
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->delete_instance("file:/foo");
+};
+like($@, qr/no instance is associated with uri/, "uri does not exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->delete_instance();
+};
+like($@, qr/1 was expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->delete_instance("foo", 2);
+};
+like($@, qr/1 was expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/09_server_stat_object.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/09_server_stat_object.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/09_server_stat_object.t	(revision 21994)
@@ -0,0 +1,72 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 09_server_stat_object.t,v 1.11 2007-05-03 03:21:28 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 12;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+{
+    $neb->create_object("foo");
+
+    my $info = $neb->stat_object("foo");
+
+    is(scalar @$info, 7, "number of columns");
+}
+
+Test::Nebulous->setup;
+
+{
+    $neb->create_object("foo", "node01");
+
+    my $info = $neb->stat_object("foo");
+
+    is(scalar @$info, 7,                       "number of columns");
+    is(@$info[0], 1,                           "so_id");
+    is(@$info[1], "foo",                       "ext_id");
+    is(@$info[2], 0,                           "read lock");
+    is(@$info[3], undef,                       "write lock");
+    like(@$info[4], qr/....-..-.. ..:..:../,   "epoch");
+    like(@$info[5], qr/....-..-.. ..:..:../,   "mtime");
+    is(@$info[6], 1,                           "instances");
+}
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->stat_object("foo");
+};
+like($@, qr/is valid object key/, "object does not exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->stat_object();
+};
+like($@, qr/1 was expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+    $neb->stat_object("foo", 2);
+};
+like($@, qr/1 was expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/10_server_is_valid_volume_name.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/10_server_is_valid_volume_name.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/10_server_is_valid_volume_name.t	(revision 21994)
@@ -0,0 +1,36 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 10_server_is_valid_volume_name.t,v 1.3 2007-03-28 22:02:11 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 3;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+ok($neb->_is_valid_volume_name('node01'), "valid volume name");
+
+Test::Nebulous->setup;
+
+ok($neb->_is_valid_volume_name('node02'), "valid volume name");
+
+Test::Nebulous->setup;
+
+is($neb->_is_valid_volume_name('node99'), undef, "invalid volume name");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/11_server_is_valid_object_key.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/11_server_is_valid_object_key.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/11_server_is_valid_object_key.t	(revision 21994)
@@ -0,0 +1,38 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 11_server_is_valid_object_key.t,v 1.1 2007-05-03 01:44:24 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 2;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+{
+    $neb->create_object('foo');
+
+    ok($neb->_is_valid_object_key('foo'), "valid object key");
+}
+
+Test::Nebulous->setup;
+
+{
+    ok(!$neb->_is_valid_object_key('foo'), "invalid object key");
+}
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/12_server_find_objects.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/12_server_find_objects.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/12_server_find_objects.t	(revision 21994)
@@ -0,0 +1,68 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 12_server_find_objects.t,v 1.1 2007-04-26 23:45:03 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 6;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+# search for a regex of '' should match nothing
+{
+    # key
+    my $uri = $neb->create_object("foo");
+
+    my $keys = $neb->find_objects();
+
+    is(scalar @$keys, 0, 'number of keys found');
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("foo");
+
+    my $keys = $neb->find_objects("foo");
+
+    is(scalar @$keys, 1, 'number of keys found');
+    is($keys->[0], "foo", "key name");
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri1 = $neb->create_object("foo");
+    my $uri2 = $neb->replicate_object("foo");
+
+    my $keys = $neb->find_objects("foo");
+
+    is(scalar @$keys, 1, 'number of keys found');
+    is($keys->[0], "foo", "key name");
+}
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->find_objects("foo", 3);
+};
+like($@, qr/1 was expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/13_server_rename_object.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/13_server_rename_object.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/13_server_rename_object.t	(revision 21994)
@@ -0,0 +1,73 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2007  Joshua Hoblitt
+#
+# $Id: 13_server_rename_object.t,v 1.2 2007-05-03 22:10:14 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 6;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+{
+    my $uri = $neb->create_object("foo");
+
+    $neb->rename_object("foo", "bar");
+
+    my $keys = $neb->find_objects('^foo$');
+    is(scalar @$keys, 0, 'number of keys found');
+    $keys = $neb->find_objects('^bar$');
+    is(scalar @$keys, 1, 'number of keys found');
+}
+
+Test::Nebulous->setup;
+
+# destination key exists
+eval {
+    $neb->create_object('foo');
+    $neb->create_object('bar');
+
+    $neb->rename_object('foo', 'bar');
+};
+like($@, qr/is not valid object key/, "too few params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->rename_object();
+};
+like($@, qr/2 were expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->rename_object("foo");
+};
+like($@, qr/2 were expected/, "too few params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->rename_object("foo", "bar", "baz");
+};
+like($@, qr/2 were expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/14_server_xattr.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/14_server_xattr.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/14_server_xattr.t	(revision 21994)
@@ -0,0 +1,187 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2007  Joshua Hoblitt
+#
+# $Id: 14_server_xattr.t,v 1.2 2007-05-03 22:10:14 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 32;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+# 1 key / xattr
+
+Test::Nebulous->setup;
+
+{
+    my $uri = $neb->create_object('foo');
+
+    ok($neb->setxattr_object('foo', 'bar', 'baz', 'create'), 'set object xattr');
+    {
+        my @xattrs = $neb->listxattr_object('foo');
+        is(scalar @xattrs, 1, 'number of xattrs');
+        is($xattrs[0], 'bar', 'xattr name');
+    }
+
+    my $value = $neb->getxattr_object('foo', 'bar');
+    is($value, 'baz', 'xattr value');
+
+    ok($neb->removexattr_object('foo', 'bar'), "remove object xattr");
+    {
+        my @xattrs = $neb->listxattr_object('foo');
+        is(scalar @xattrs, 0, 'number of xattrs');
+    }
+}
+
+# multiple xattrs
+
+Test::Nebulous->setup;
+
+{
+    my $uri = $neb->create_object('foo');
+
+    ok($neb->setxattr_object('foo', 'bar', 'baz', 'create'), 'set object xattr');
+    ok($neb->setxattr_object('foo', 'bonk', 'quix', 'create'), 'set object xattr');
+    
+    {
+        my @xattrs = $neb->listxattr_object('foo');
+        is(scalar @xattrs, 2, 'number of xattrs');
+        is($xattrs[0], 'bar', 'xattr name');
+        is($xattrs[1], 'bonk', 'xattr name');
+    }
+
+    my $value = $neb->getxattr_object('foo', 'bar');
+    is($value, 'baz', 'xattr value');
+    $value = $neb->getxattr_object('foo', 'bonk');
+    is($value, 'quix', 'xattr value');
+
+    ok($neb->removexattr_object('foo', 'bar'), "remove object xattr");
+    ok($neb->removexattr_object('foo', 'bonk'), "remove object xattr");
+    {
+        my @xattrs = $neb->listxattr_object('foo');
+        is(scalar @xattrs, 0, 'number of xattrs');
+    }
+}
+
+# replace xattrs
+
+Test::Nebulous->setup;
+
+{
+    my $uri = $neb->create_object('foo');
+
+    ok($neb->setxattr_object('foo', 'bar', 'baz', 'create'), 'set object xattr');
+    ok($neb->setxattr_object('foo', 'bar', 'quix', 'replace'), 're-set object xattr');
+    
+    {
+        my @xattrs = $neb->listxattr_object('foo');
+        is(scalar @xattrs, 1, 'number of xattrs');
+        is($xattrs[0], 'bar', 'xattr name');
+    }
+
+    my $value = $neb->getxattr_object('foo', 'bar');
+    is($value, 'quix', 'xattr value');
+
+    ok($neb->removexattr_object('foo', 'bar'), "remove object xattr");
+    {
+        my @xattrs = $neb->listxattr_object('foo');
+        is(scalar @xattrs, 0, 'number of xattrs');
+    }
+}
+
+# setxattr_object
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->setxattr_object();
+};
+like($@, qr/4 were expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+
+    $neb->setxattr_object('foo', 'bar');
+};
+like($@, qr/4 were expected/, "too few params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+
+    $neb->setxattr_object('foo', 'bar', 'baz');
+};
+like($@, qr/4 were expected/, "too few params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+
+    $neb->setxattr_object('foo', 'bar', 'baz', 'create', 'quix');
+};
+like($@, qr/4 were expected/, "too many params");
+
+# listxattr_object
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+
+    $neb->listxattr_object();
+};
+like($@, qr/1 was expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+
+    $neb->listxattr_object('foo', 'bar');
+};
+like($@, qr/1 was expected/, "too many params");
+
+# getxattr_object
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->getxattr_object();
+};
+like($@, qr/2 were expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+
+    $neb->getxattr_object('foo');
+};
+like($@, qr/2 were expected/, "too few params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+
+    $neb->getxattr_object('foo', 'bar', 'baz');
+};
+like($@, qr/2 were expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/75_parse_neb_key.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/75_parse_neb_key.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous-Server/t/75_parse_neb_key.t	(revision 21994)
@@ -0,0 +1,170 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 75_parse_neb_key.t,v 1.2 2008-01-23 22:46:44 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More;
+
+plan tests => 36;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+# neb://<volume name>/...
+# neb:path...
+# neb:/path... (same as neb:path, leading '/' is stripped)
+# neb:///path... (same as neb:path)
+
+# key
+{
+    my ($volume, $path) = parse_neb_key('foo/bar/baz/quix');
+
+    is($path, 'foo/bar/baz/quix', 'path');
+    is($volume, undef, 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('/foo/bar/baz/quix');
+
+    is($path, 'foo/bar/baz/quix', 'path');
+    is($volume, undef, 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('//foo/bar/baz/quix');
+
+    is($path, 'foo/bar/baz/quix', 'path');
+    is($volume, undef, 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('///foo/bar/baz/quix');
+
+    is($path, 'foo/bar/baz/quix', 'path');
+    is($volume, undef, 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('foo////bar/baz/quix');
+
+    is($path, 'foo/bar/baz/quix', 'path');
+    is($volume, undef, 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('foo/bar/baz/quix/');
+
+    is($path, 'foo/bar/baz/quix', 'path');
+    is($volume, undef, 'volume name');
+}
+
+
+# URI w/ volume name
+{
+    my ($volume, $path) = parse_neb_key('neb://foo/bar/baz/quix');
+
+    is($path, 'bar/baz/quix', 'path');
+    is($volume, 'foo', 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('neb://foo//bar/baz/quix');
+
+    is($path, 'bar/baz/quix', 'path');
+    is($volume, 'foo', 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('neb://foo///bar/baz/quix');
+
+    is($path, 'bar/baz/quix', 'path');
+    is($volume, 'foo', 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('neb://foo/bar///baz/quix');
+
+    is($path, 'bar/baz/quix', 'path');
+    is($volume, 'foo', 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('neb://foo/bar/baz/quix/');
+
+    is($path, 'bar/baz/quix', 'path');
+    is($volume, 'foo', 'volume name');
+}
+
+
+# URI w/o volume name
+
+{
+    my ($volume, $path) = parse_neb_key('neb:/foo/bar/baz/quix');
+
+    is($path, 'foo/bar/baz/quix', 'path');
+    is($volume, undef, 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('neb:///foo/bar/baz/quix');
+
+    is($volume, undef, 'volume name');
+    is($path, 'foo/bar/baz/quix', 'path');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('neb://///foo/bar/baz/quix');
+
+    is($path, 'foo/bar/baz/quix', 'path');
+    is($volume, undef, 'volume name');
+}
+
+# key w/ whitespace
+eval {
+    parse_neb_key('/ foo/bar/baz/quix');
+};
+like( $@, qr/may not contain whitespace/, "whitespace" );
+
+eval {
+    parse_neb_key(' /foo/bar/baz/quix');
+};
+like( $@, qr/may not contain whitespace/, "whitespace" );
+
+eval {
+    parse_neb_key('/foo/bar/baz/quix ');
+};
+like( $@, qr/may not contain whitespace/, "whitespace" );
+
+# URI w/ whitespace
+
+eval {
+    parse_neb_key('neb ://foo/bar/baz/quix');
+};
+like( $@, qr/may not contain whitespace/, "whitespace" );
+
+eval {
+    parse_neb_key('neb:// foo/bar/baz/quix');
+};
+like( $@, qr/may not contain whitespace/, "whitespace" );
+
+eval {
+    parse_neb_key(' neb://foo/bar/baz/quix');
+};
+like( $@, qr/may not contain whitespace/, "whitespace" );
+
+eval {
+    parse_neb_key('neb://foo/bar/baz/quix ');
+};
+like( $@, qr/may not contain whitespace/, "whitespace" );
+
+# URI w/o volume requires leading slash
+eval {
+    my ($volume, $path) = parse_neb_key('neb:foo/bar/baz/quix');
+};
+like( $@, qr/requires a leading slash/, "leading slash" );
Index: /tags/ipp-1-X/rel-0_06/Nebulous/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/.cvsignore	(revision 21994)
@@ -0,0 +1,6 @@
+Build
+META.yml
+Makefile
+Makefile.PL
+_build
+blib
Index: /tags/ipp-1-X/rel-0_06/Nebulous/Build.PL
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/Build.PL	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/Build.PL	(revision 21994)
@@ -0,0 +1,120 @@
+use Module::Build;
+# See perldoc Module::Build for details of how this works
+
+my $build_pkg   = eval { require Apache::TestMB }
+                ? 'Apache::TestMB'
+                : 'Module::Build';
+
+my $class = $build_pkg->subclass(code => <<'EOF');
+use Cwd;
+
+my $pkg_dir = "./nebclient";
+
+sub ACTION_code {
+    my $self = shift;
+
+    $self->SUPER::ACTION_code(@_);
+
+    my $old_pwd = getcwd();
+    chdir $pkg_dir;
+
+    unless (-e "configure") {
+        system("./autogen.sh") == 0 or die "install failed: $?";
+    }
+
+    chdir $old_pwd;
+}
+
+sub ACTION_build {
+    my $self = shift;
+
+    $self->SUPER::ACTION_build(@_);
+
+    my $old_pwd = getcwd();
+    chdir $pkg_dir;
+
+    unless (-e "Makefile") {
+        system("sh ./configure") == 0 or die "build failed: $?";
+    }
+
+    system("make") == 0 or die "build failed: $?";
+
+    chdir $old_pwd;
+}
+
+# Do not attempt to install nebclient.  It is bundled in this package for
+# testing only.
+#
+# sub ACTION_install {
+#     my $self = shift;
+# 
+#     $self->SUPER::ACTION_install(@_);
+# 
+#     my $old_pwd = getcwd();
+#     chdir $pkg_dir;
+# 
+#     system("make install") == 0 or die "install failed: $?";
+# 
+#     chdir $old_pwd;
+# }
+
+sub ACTION_clean {
+    my $self = shift;
+
+    $self->SUPER::ACTION_clean(@_);
+
+    my $old_pwd = getcwd();
+    chdir $pkg_dir;
+
+    system("make clean") == 0 or die "install failed: $?";
+
+    chdir $old_pwd;
+}
+EOF
+
+$class->new(
+    module_name         => 'Nebulous',
+    dist_version_from   => 'lib/Nebulous/Server.pm',
+    author              => 'Joshua Hoblitt <jhoblitt@cpan.org>',
+    license             => 'gpl',
+    create_makefile_pl  => 'passthrough',
+    requires            => {
+        'Class::Accessor::Fast' => 0,
+        'Config::YAML'          => '1.42',
+        'DBD::mysql'            => '3.0007',
+        'DBI'                   => '1.53',
+        'File::ExtAttr'         => '1.03',
+        'File::Spec::Functions' => 0,
+        'Log::Log4perl'         => '0.48',
+        'Net::Server::Daemonize'=> '0.05',
+        'Params::Validate'      => '0.73',
+        'SOAP::Lite'            => '0.69',
+        'Sys::Statistics::Linux::DiskUsage' => '0.02',
+        'URI'                   => '1.30',
+    },
+    build_requires      => {
+        'Apache2::SOAP'         => 0,
+        'Apache::DBI'           => '1.05',
+        'Apache::Test'          => '1.27',  # bundles Apache::TestMB
+        'Apache::TestMB'        => 0,
+        'File::Temp'            => 0,
+        'Test::More'            => '0.49',
+        'Test::URI'             => '1.06',
+    },
+    recommends          => {
+        'Test::Distribution'    => '1.22',
+    },
+    script_files        => [qw(
+        bin/neb-addvol
+        bin/neb-cat
+        bin/neb-cp
+        bin/neb-df
+        bin/neb-locate
+        bin/neb-initdb
+        bin/neb-ls
+        bin/neb-mv
+        bin/neb-rm
+        bin/neb-touch
+        bin/nebdiskd
+    )],
+)->create_build_script;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/Changes
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/Changes	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/Changes	(revision 21994)
@@ -0,0 +1,95 @@
+Revision history for Nebulous
+
+0.06 Fri Jan 25 10:55:59 HST 2008
+    - define Nebulous::Client::find_objects() as returning [] when NO keys are
+      found
+    - change neb-touch to use Nebulous::Client::find_objects() instead of
+      ::find()
+    - add Nebulous::Sever:: neb key/uri support
+    - add Nebulous::Util::parse_neb_key()
+    - change bin/* scripts to conistently use --volume instead of --node,
+      etc.
+    - pod cleanups
+    - add neb-replicate & neb-cull
+
+0.05 2007-05-04 16:59:31(???)
+    - make filesystem xattr support optional & disabled by default
+    - generate instance filenames that leave the "key" at the end so as to not
+      break a pplications that expect a certain "extension" on the filename
+    - set an xattr on all created files of "user.nebulous_key"
+    - add neb-locate
+    - change all Nebulous::Client public methods to behave in list context
+    - rework the getmountedvol() stored procedure to attempt to work around
+      what appears to be some nasty transacational isolation leak throught that
+      was causing getmountedvol() to randomly hang when nebdiskd changed the
+      mount table.
+    - fix a nasty logic bug in Nebulous::Client->replicate()
+    - break 1:1 relationship between key names and on disk file names
+    - overhaul Nebulous::Client->cull()
+    - add the number of instances to ->stat_object()
+    - SQL cleanup
+    - better paramter checking
+    - overhaul instance table
+    - add ->_is_valid_object_key() method
+    - change ->find_instances() to check it's params and only return instances
+      on mounted & available volumes
+    - add volume.available field and logic to use it
+    - add volume.allocate field and logic to use it
+    - add instance.vol_id field
+    - remove $class_id & $comment params from Nebulous::Server->create() and
+      Nebulous::Client->create*() and all supporting functions and tests
+    - add Nebulous::Server->{setxattr_object, listxattr_object,
+      getxattr_object, removexattr_object}()
+    - add neb-cat
+    - add neb-mv
+    - change Nebulous::Client->move() to use ->rename_object()
+    - add Nebulous::Server->rename_object()
+    - add neb-rm
+    - add neb-cp
+    - add neb-ls
+    - add Nebulous::Client->find_objects()
+    - add Nebulous::Server->find_objects()
+    - add neb-touch
+    - add neb-df
+    - change neb-addvol to properly mangle URIs into paths
+
+0.04 Mon Apr 23 13:33:16 HST 2007
+    - include autogen.sh in the tarball
+    - add nebdiskd
+    - [nebclient] VERSION to '0.0.3'
+    - change API to generally return true URIs instead of file paths
+    - add support for some what intelligent volume allocations
+    - minor code & build fixes, ws changes
+
+0.03 Mon Dec 11 14:19:45 HST 2006
+    - change Nebulous::Server instantiate objects (init -> new) instead of
+      working with class data
+    - add a DESTROY method to Nebulous::Server to tear down the database
+      connection
+    - add a Nebulous::Server->config() accessor
+    - make Nebulous::Server->db() Apache::DBI aware
+    - make SQL syntax MySQL 5 compatible
+    - update SOAP, DBI & DBD, and Apache::* deps
+    - change Nebulous::Server::SOAP to be mod_perl aware
+    - change Nebulous::Server::SOAP install stub methods to bypass AUTOLOAD on
+      successive calls to the same method
+    - make Nebulous::Server::Log mod_perl aware
+    - change Nebulous::Server::Log to accept a Nebulous::Server::Config object
+      as a parameter instead of fetching it as a singleton
+    - make Nebulous::Server::Config no longer a singleton
+
+0.02 Fri Dec  2 17:36:59 HST 2005
+    - recommend Test::Distribution 1.22
+    - add t/00_distribution.t
+    - rename test files
+    - [nebclient] VERSION to '0.0.2'
+    - Nebulous::Client, Nebulous::Server, & Nebulous::Server::SQL
+        VERSION to '0.02'
+    - add Nebulous::Client->open_create()
+    - change Nebulous::Client->create() to return just a filename
+    - [nebclient] add nebOpenCreate()
+    - [nebclient] change nebCreate() to return just a filename
+
+0.01 Fri Sep  3 10:23:31 2004
+    - first working version
+	- original version; created by ExtUtils::ModuleMaker 0.32
Index: /tags/ipp-1-X/rel-0_06/Nebulous/LICENSE
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/LICENSE	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/LICENSE	(revision 21994)
@@ -0,0 +1,260 @@
+The General Public License (GPL)
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave,
+Cambridge, MA 02139, USA. Everyone is permitted to copy and distribute
+verbatim copies of this license document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it. By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to most of
+the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom
+to distribute copies of free software (and charge for this service if you wish), that
+you receive source code or can get it if you want it, that you can change the
+software or use pieces of it in new free programs; and that you know you can do
+these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights. These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a
+fee, you must give the recipients all the rights that you have. You must make
+sure that they, too, receive or can get the source code. And you must show
+them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer
+you this license which gives you legal permission to copy, distribute and/or
+modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced by
+others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish
+to avoid the danger that redistributors of a free program will individually obtain
+patent licenses, in effect making the program proprietary. To prevent this, we
+have made it clear that any patent must be licensed for everyone's free use or
+not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+GNU GENERAL PUBLIC LICENSE
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND
+MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or translated
+into another language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope. The act of running the Program is not
+restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program). Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as
+you receive it, in any medium, provided that you conspicuously and appropriately
+publish on each copy an appropriate copyright notice and disclaimer of warranty;
+keep intact all the notices that refer to this License and to the absence of any
+warranty; and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at
+your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus
+forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you also
+meet all of these conditions:
+
+a) You must cause the modified files to carry prominent notices stating that you
+changed the files and the date of any change.
+
+b) You must cause any work that you distribute or publish, that in whole or in
+part contains or is derived from the Program or any part thereof, to be licensed
+as a whole at no charge to all third parties under the terms of this License.
+
+c) If the modified program normally reads commands interactively when run, you
+must cause it, when started running for such interactive use in the most ordinary
+way, to print or display an announcement including an appropriate copyright
+notice and a notice that there is no warranty (or else, saying that you provide a
+warranty) and that users may redistribute the program under these conditions,
+and telling the user how to view a copy of this License. (Exception: if the
+Program itself is interactive but does not normally print such an announcement,
+your work based on the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Program, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to
+work written entirely by you; rather, the intent is to exercise the right to control
+the distribution of derivative or collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and 2
+above provided that you also do one of the following:
+
+a) Accompany it with the complete corresponding machine-readable source
+code, which must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange; or,
+
+b) Accompany it with a written offer, valid for at least three years, to give any
+third party, for a charge no more than your cost of physically performing source
+distribution, a complete machine-readable copy of the corresponding source
+code, to be distributed under the terms of Sections 1 and 2 above on a medium
+customarily used for software interchange; or,
+
+c) Accompany it with the information you received as to the offer to distribute
+corresponding source code. (This alternative is allowed only for noncommercial
+distribution and only if you received the program in object code or executable
+form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all the
+source code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+executable. However, as a special exception, the source code distributed need
+not include anything that is normally distributed (in either source or binary form)
+with the major components (compiler, kernel, and so on) of the operating system
+on which the executable runs, unless that component itself accompanies the
+executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source
+code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so long
+as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Program
+or its derivative works. These actions are prohibited by law if you do not accept
+this License. Therefore, by modifying or distributing the Program (or any work
+based on the Program), you indicate your acceptance of this License to do so,
+and all its terms and conditions for copying, distributing or modifying the
+Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor to copy,
+distribute or modify the Program subject to these terms and conditions. You
+may not impose any further restrictions on the recipients' exercise of the rights
+granted herein. You are not responsible for enforcing compliance by third parties
+to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent infringement
+or for any other reason (not limited to patent issues), conditions are imposed on
+you (whether by court order, agreement or otherwise) that contradict the
+conditions of this License, they do not excuse you from the conditions of this
+License. If you cannot distribute so as to satisfy simultaneously your obligations
+under this License and any other pertinent obligations, then as a consequence
+you may not distribute the Program at all. For example, if a patent license would
+not permit royalty-free redistribution of the Program by all those who receive
+copies directly or indirectly through you, then the only way you could satisfy
+both it and this License would be to refrain entirely from distribution of the
+Program.
+
+If any portion of this section is held invalid or unenforceable under any particular
+circumstance, the balance of the section is intended to apply and the section as
+a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other
+property right claims or to contest validity of any such claims; this section has
+the sole purpose of protecting the integrity of the free software distribution
+system, which is implemented by public license practices. Many people have
+made generous contributions to the wide range of software distributed through
+that system in reliance on consistent application of that system; it is up to the
+author/donor to decide if he or she is willing to distribute software through any
+other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain countries
+either by patents or by copyrighted interfaces, the original copyright holder who
+places the Program under this License may add an explicit geographical
+distribution limitation excluding those countries, so that distribution is permitted
+only in or among countries not thus excluded. In such case, this License
+incorporates the limitation as if written in the body of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the
+General Public License from time to time. Such new versions will be similar in
+spirit to the present version, but may differ in detail to address new problems or
+concerns.
+
+Each version is given a distinguishing version number. If the Program specifies a
+version number of this License which applies to it and "any later version", you
+have the option of following the terms and conditions either of that version or of
+any later version published by the Free Software Foundation. If the Program does
+not specify a version number of this License, you may choose any version ever
+published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of all
+derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS
+NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
+COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
+"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR
+IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED
+TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY
+WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS
+PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
+(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
+OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
Index: /tags/ipp-1-X/rel-0_06/Nebulous/MANIFEST
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/MANIFEST	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/MANIFEST	(revision 21994)
@@ -0,0 +1,131 @@
+Build.PL
+Changes
+LICENSE
+MANIFEST
+META.yml
+Makefile.PL
+README
+Todo
+autogen.sh
+bin/neb-addvol
+bin/neb-cat
+bin/neb-cp
+bin/neb-cull
+bin/neb-df
+bin/neb-initdb
+bin/neb-locate
+bin/neb-ls
+bin/neb-mv
+bin/neb-replicate
+bin/neb-rm
+bin/neb-touch
+bin/nebdiskd
+docs/c_api.h
+docs/database_setup.txt
+docs/design.txt
+docs/requirements.txt
+docs/setup.txt
+docs/tmp.txt
+examples/Makefile
+examples/nebexample.c
+examples/nebexample.pl
+lib/Nebulous/Client.pm
+lib/Nebulous/Client.pod
+lib/Nebulous/Client/HTTP.pm
+lib/Nebulous/Client/Log.pm
+lib/Nebulous/Client/QuickStart.pod
+lib/Nebulous/Server.pm
+lib/Nebulous/Server.pod
+lib/Nebulous/Server/Apache.pm
+lib/Nebulous/Server/Config.pm
+lib/Nebulous/Server/Log.pm
+lib/Nebulous/Server/SOAP.pm
+lib/Nebulous/Server/SQL.pm
+lib/Nebulous/Util.pm
+nebclient/Doxyfile.in
+nebclient/Makefile.am
+nebclient/Makefile.in
+nebclient/aclocal.m4
+nebclient/autogen.sh
+nebclient/compile
+nebclient/config.guess
+nebclient/config.h.in
+nebclient/config.sub
+nebclient/configure
+nebclient/configure.ac
+nebclient/depcomp
+nebclient/install-sh
+nebclient/ltmain.sh
+nebclient/missing
+nebclient/nebclient.pc.in
+nebclient/nebulous.wsdl
+nebclient/src/Makefile.am
+nebclient/src/Makefile.in
+nebclient/src/SOAP.nsmap
+nebclient/src/nebclient.c
+nebclient/src/nebclient.h
+nebclient/src/soapC.c
+nebclient/src/soapClient.c
+nebclient/src/soapH.h
+nebclient/src/soapStub.h
+nebclient/src/stdsoap2.c
+nebclient/src/stdsoap2.h
+nebclient/src/xmalloc.c
+nebclient/src/xmalloc.h
+nebclient/test/tap/INSTALL
+nebclient/test/tap/Makefile.am
+nebclient/test/tap/Makefile.in
+nebclient/test/tap/README
+nebclient/test/tap/aclocal.m4
+nebclient/test/tap/compile
+nebclient/test/tap/configure
+nebclient/test/tap/configure.in
+nebclient/test/tap/src/
+nebclient/test/tap/src/Makefile.am
+nebclient/test/tap/src/Makefile.in
+nebclient/test/tap/src/config.h.in
+nebclient/test/tap/src/tap.c
+nebclient/test/tap/src/tap.h
+nebclient/tests/Makefile.am
+nebclient/tests/Makefile.in
+nebclient/tests/tests.c
+scripts/bench_test.pl
+scripts/nebulous.cgi
+scripts/ptest.pl
+t/00_distribution.t 
+t/01_load.t
+t/02_server_setup.t
+t/03_server_create_object.t
+t/04_server_replicate_object.t
+t/05_server_lock_object.t
+t/06_server_unlock_object.t
+t/07_server_find_instances.t
+t/08_server_delete_instance.t
+t/09_server_stat_object.t
+t/10_server_is_valid_volume_name.t
+t/11_server_is_valid_object_key.t
+t/12_server_find_objects.t
+t/13_server_rename_object.t
+t/14_server_xattr.t
+t/50_client_new.t
+t/51_client_create.t
+t/51_client_open_create.t
+t/52_client_replicate.t
+t/53_client_cull.t
+t/54_client_lock.t
+t/55_client_unlock.t
+t/56_client_find_instances.t
+t/57_client_find.t
+t/58_client_open.t
+t/59_client_delete.t
+t/60_client_copy.t
+t/61_client_move.t
+t/62_client_delete_instance.t
+t/63_client_stat.t
+t/64_client_find_objects.t
+t/75_parse_neb_key.t
+t/90_nebclient.t
+t/TEST.PL
+t/Test/Nebulous.pm
+t/conf/extra.conf.in
+t/conf/startup.pl.in
Index: /tags/ipp-1-X/rel-0_06/Nebulous/README
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/README	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/README	(revision 21994)
@@ -0,0 +1,16 @@
+pod2text Poi::PixelData.pm > README
+
+If this is still here it means the programmer was too lazy to create the readme file.
+
+You can create it now by using the command shown above from this directory.
+
+At the very least you should be able to use this set of instructions
+to install the module...
+
+perl Build.PL
+./Build
+./Build test
+./Build install
+
+
+If you are on a windows box you should use 'nmake' rather than 'make'.
Index: /tags/ipp-1-X/rel-0_06/Nebulous/Todo
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/Todo	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/Todo	(revision 21994)
@@ -0,0 +1,42 @@
+TODO list for Perl module Nebulous
+
+- make nebclient lib thread safe
+- handle/check for storage volumes being offline
+- move storage 'classes' into the database, cache at startup?
+- use specific storage volume requests instead of ignoring them
+- admin interface to control volumes (enable/disable, add/remove)
+- add zeroconf support
+- add support for SQL and/or Apache logging
+- make copy replicate source attributes, implement as replicate/reparent?
+- implement proper storage object rename support (same volume move w/o copy)
+- redo database schema with foreign keys
+- validation of URIs
+- test that client->delete_instance removes the storage object too
+- review caching of database statement handles
+- code tiding/consistency
+- file creation retrying
+- server config file
+- make Apache::DBI behave
+- split SOAP out of Client.pm
+- Perl client error string support with DBI like 'AutoRaise' exceptions
+- CLI utilities
+- write neb-fsck utility
+- write Linux::statfs module so that statfs.f_bavail can be obtained (not available via df)
+- change neb-ls to have a limit number of keys shown (-n) param and default to
+  something reasonable (say 20)
+- add multiple regex and/or glob support to neb-ls, eg. neb-ls -r 'foo.*' -r 'bar$'
+- store the key name as an xattr on the actual on disk file
+- add an neb-locate --reverse option to map uri/paths into keys
+
+distant future
+--
+- cache some database tables (updated at some interval) 
+- volume size/% in-use discovery
+- server side per client lock tracking
+- per client authentication
+- client side lookup table of filehandles/locks
+- Perl only?, scoped lock release/filehandle destruction
+- restructure database so that storage objects are more like inodes
+- add support for directories
+- FUSE interface
+- hot-spot analysis
Index: /tags/ipp-1-X/rel-0_06/Nebulous/autogen.sh
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/autogen.sh	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/autogen.sh	(revision 21994)
@@ -0,0 +1,1 @@
+perl Build.PL -apxs /usr/sbin/apxs2 
Index: /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-addvol
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-addvol	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-addvol	(revision 21994)
@@ -0,0 +1,176 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2005-2008  Joshua Hoblitt
+#
+# $Id: neb-addvol,v 1.7 2008-01-22 21:40:39 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use DBI;
+use Nebulous::Server::SQL;
+use URI;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ($db, $dbuser, $dbpass, $volume, $uri);
+
+$db     = $ENV{'NEB_DB'} unless $db;
+$dbuser = $ENV{'NEB_USER'} unless $dbuser;
+$dbpass = $ENV{'NEB_PASS'} unless $dbpass;
+
+GetOptions(
+    'db=s'      => \$db,
+    'user=s'    => \$dbuser,
+    'pass=s'    => \$dbpass,
+    'volume=s'  => \$volume,
+    'uri|u=s'   => \$uri,
+) || pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required options: --db --user --pass", -exitval => 2 )
+    unless $db && $dbuser && $dbpass && $volume && $uri;
+
+my $dbh = DBI->connect(
+    "DBI:mysql:database=$db:host=localhost",
+    $dbuser,
+    $dbpass,
+    {
+        RaiseError => 1,
+        PrintError => 0,
+        AutoCommit => 1,
+    },
+);
+
+my $sql = Nebulous::Server::SQL->new();
+
+print "Checking URI...";
+
+my $path = URI->new($uri)->file;
+unless (-d $path) {
+    die "path: $path dirived from URI: $uri does not exist";
+}
+
+print " OK\n";
+
+print "Adding volume...";
+
+my $query = $dbh->prepare( $sql->new_volume );
+$query->execute( $volume, $path );
+
+print " OK\n";
+
+__END__
+
+=pod
+
+=head1 NAME
+
+neb-addvol - add a storage volume to a Nebulous server
+
+=head1 SYNOPSIS
+
+    neb-addvol --volume <volume name> --uri <volume uri>
+        [--db <database>] [--user <username>] [--pass <password>]
+
+=head1 DESCRIPTION
+
+This program initialize a database for use by L<Nebulous::Server> by creating
+the appropriate set of tables.  Any pre-existing tables with conflicting names
+are first removed.
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --volume <volume name>
+
+Symbolic name of volume being added.
+
+=item * --uri|-u <volume uri>
+
+URI to the volume being added.
+
+=item * --db|-d <database>
+
+Name of database (C<namespace>) to create tables in.
+
+Optional if the appropriate environment variable is set.
+
+=item * --user|-u <username>
+
+Username to authenticate with.
+
+Optional if the appropriate environment variable is set.
+
+=item * --pass|-p <password>
+
+Password to authenticate with.
+
+Optional if the appropriate environment variable is set.
+
+=back
+
+=head1 ENVIRONMENT
+
+These environment variables may be used in place of the specified command line
+options.  All command line option will override the corresponding environment
+value.
+
+=over 4
+
+=item * C<NEB_DB>
+
+Equivalent to --db|-d
+
+=item * C<NEB_USER>
+
+Equivalent to --user|-u
+
+=item * C<NEB_PASS>
+
+Equivalent to --pass|-p 
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2005-2008  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Server>, L<neb-initdb>, L<neb-df>, L<nebdiskd>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-cat
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-cat	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-cat	(revision 21994)
@@ -0,0 +1,156 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2007  Joshua Hoblitt
+#
+# $Id: neb-cat,v 1.1 2007-04-28 02:52:13 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use Nebulous::Client;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+use constant CHUNK_SIZE => 1024;
+
+my ($server);
+
+$server = $ENV{'NEB_SERVER'} unless $server;
+
+GetOptions(
+    'server|s=s'    => \$server,
+) || pod2usage( 2 );
+
+pod2usage( -msg => "Required options: --server <key...>", -exitval => 2 )
+        unless defined $server;
+
+my $neb = Nebulous::Client->new(
+    proxy => "$server",
+);
+
+die "can't connected to Nebulous Server: $server"
+    unless defined $neb;
+
+unless (scalar @ARGV) {
+    no strict;
+    print_fh(STDIN);
+    use strict;
+}
+
+foreach my $key (@ARGV) {
+    my $fh;
+    # copy cat's behavior of treating '-' as stdin
+    if ($key eq '-') {
+        open($fh, '-') or warn "failed to open stdin" and next;
+    } else {
+        $fh = $neb->open( $key, 'read' )
+            or warn "failed to open key: $key" and next;
+    }
+
+    print_fh($fh);
+
+    close ($fh) or die "failed to close filehandle: $!";
+}
+
+sub print_fh
+{
+    my $fh = shift;
+
+    my $status;
+    while ($status = read($fh, my $buf, CHUNK_SIZE)) {
+            print $buf;
+    }
+
+    # read() returns undef on error
+    unless (defined $status) {
+        die "failed to read from filehandle: $!";
+    }
+}
+
+__END__
+
+=pod
+
+=head1 NAME
+
+neb-cat - concatenate one instance per Nebulous key and print on the standard output
+
+=head1 SYNOPSIS
+
+    neb-cat [--server <URL>] <key...>
+
+=head1 DESCRIPTION
+
+This program selects one instance per Nebulous keys given in C<<key...>> and
+conatenates them together then prints them on the standard output.  Note that
+just as with the C<cat> utility, C<-> can be used to read from the standard
+input.
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --server|-s <URL>
+
+URL of the Nebulous server to connect to.
+
+Optional if the appropriate environment variable is set.
+
+=back
+
+=head1 ENVIRONMENT
+
+These environment variables may be used in place of the specified command line
+options.  All command line option will override the corresponding environment
+value.
+
+=over 4
+
+=item * C<NEB_SERVER>
+
+Equivalent to --server|-s
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2007  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Server>, L<neb-initdb>, L<neb-addvol>, L<nebdiskd>, L<neb-df>,
+L<neb-touch>, C<regex(7)>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-cp
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-cp	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-cp	(revision 21994)
@@ -0,0 +1,136 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2007-2008  Joshua Hoblitt
+#
+# $Id: neb-cp,v 1.5 2008-01-22 21:40:39 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use Nebulous::Client;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ($volume, $server);
+
+$server = $ENV{'NEB_SERVER'} unless $server;
+
+GetOptions(
+    'volume=s'      => \$volume,
+    'server|s=s'    => \$server,
+) || pod2usage( 2 );
+
+my $src = shift;
+my $dst = shift;
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required options: --server <src key> <dst key>",
+        -exitval => 2 )
+        unless defined $server and defined $src and defined $dst;
+
+my $neb = Nebulous::Client->new(
+    proxy => "$server",
+);
+
+die "can't connected to Nebulous Server: $server"
+    unless defined $neb;
+
+my $status;
+if ($volume) {
+    $status = $neb->copy( $src, $dst, $volume);
+} else {
+    $status = $neb->copy( $src, $dst);
+}
+
+warn "copy failied" unless $status;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+neb-cp - list Nebulous keys
+
+=head1 SYNOPSIS
+
+    neb-cp [--server <URL>] [--volume <dst volume name>] <src key> <dst key>
+
+=head1 DESCRIPTION
+
+Copy a Nebulous storage key
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --server|-s <URL>
+
+URL of the Nebulous server to connect to.
+
+Optional if the appropriate environment variable is set.
+
+=item * -volume <volume name>
+
+The volume to place the new key's first storage instance on.
+
+Optional.
+
+=back
+
+=head1 ENVIRONMENT
+
+These environment variables may be used in place of the specified command line
+options.  All command line option will override the corresponding environment
+value.
+
+=over 4
+
+=item * C<NEB_SERVER>
+
+Equivalent to --server|-s
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2007-2008  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Server>, L<neb-initdb>, L<neb-addvol>, L<nebdiskd>, L<neb-df>,
+L<neb-touch>, C<regex(7)>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-cull
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-cull	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-cull	(revision 21994)
@@ -0,0 +1,134 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2007-2008  Joshua Hoblitt
+#
+# $Id: neb-cull,v 1.1 2008-01-22 22:10:27 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use Nebulous::Client;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ($server, $volume);
+
+$server = $ENV{'NEB_SERVER'} unless $server;
+
+GetOptions(
+    'server|s=s'    => \$server,
+    'volume|v=s'    => \$volume,
+) || pod2usage( 2 );
+
+my $key = shift;
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required options: --server", -exitval => 2 )
+    unless $server;
+pod2usage( -msg => "missing key operand", exitval => 2 )
+    unless defined $key;
+
+my $neb = Nebulous::Client->new(
+    proxy => "$server",
+);
+
+die "can't connected to Nebulous Server: $server"
+    unless defined $neb;
+
+if (defined $volume) {
+    $neb->cull($key, $volume)
+        or die "failed to replicate Nebulous key: $key";
+} else {
+    $neb->cull($key)
+        or die "failed to replicate Nebulous key: $key";
+}
+
+__END__
+
+=pod
+
+=head1 NAME
+
+neb-cull - remove an instance of an object
+
+=head1 SYNOPSIS
+
+    neb-cull [--server <URL>] [--volume <volume name>] <key>
+
+=head1 DESCRIPTION
+
+This program removes an instance of the Nebulous object specified by C<<key>>.  It will I<NOT> remove the last instance of an object (nor the object itself).
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --server|-s <URL>
+
+URL of the Nebulous server to connect to.
+
+Optional if the appropriate environment variable is set.
+
+=item * --volume <volume name>
+
+Symbolic name of the volume to create the new instance on.
+
+Optional.
+
+=back
+
+=head1 ENVIRONMENT
+
+These environment variables may be used in place of the specified command line
+options.  All command line option will override the corresponding environment
+value.
+
+=over 4
+
+=item * C<NEB_SERVER>
+
+Equivalent to --server|-s
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2007-2008  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Server>, L<neb-initdb>, L<neb-addvol>, L<nebdiskd>, L<neb-df>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-df
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-df	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-df	(revision 21994)
@@ -0,0 +1,198 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2007  Joshua Hoblitt
+#
+# $Id: neb-df,v 1.3 2007-04-28 01:19:59 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use DBI;
+use Nebulous::Server::SQL;
+use URI;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ($db, $dbuser, $dbpass, $name, $uri);
+
+$db     = $ENV{'NEB_DB'} unless $db;
+$dbuser = $ENV{'NEB_USER'} unless $dbuser;
+$dbpass = $ENV{'NEB_PASS'} unless $dbpass;
+
+GetOptions(
+    'db=s'      => \$db,
+    'user=s'    => \$dbuser,
+    'pass=s'    => \$dbpass,
+) || pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required options: --db --user --pass", -exitval => 2 )
+    unless $db && $dbuser && $dbpass;
+
+my $dbh = DBI->connect(
+    "DBI:mysql:database=$db:host=localhost",
+    $dbuser,
+    $dbpass,
+    {
+        RaiseError => 1,
+        PrintError => 0,
+        AutoCommit => 1,
+    },
+);
+
+my $sql = Nebulous::Server::SQL->new();
+
+# ask the db to generate the table of mounted Nebulous volume 
+$dbh->do("call getmountedvol()");
+
+# suck that table into an AoH
+my $query = $dbh->prepare("SELECT * FROM mountedvol");
+$query->execute();
+
+my @stats;
+while (my $mountedvol = $query->fetchrow_hashref) {
+    push @stats, $mountedvol;
+}
+
+# output a summary of the information in a vaguely POSIX df like format
+print "Filesystem           1K-blocks      Used Available Use% Mounted on\n";
+
+foreach my $vol (@stats) {
+    my $path        = $vol->{path};
+    my $total       = $vol->{total};
+    my $used        = $vol->{used};
+    my $available   = $total - $used;
+    my $usedper     = ($used / $total) * 100; 
+    my $mountpoint  = $vol->{mountpoint};
+
+    # indicated the part of the nebulous volume name that matches up with a
+    # local volume (mountpoint) 
+    #$path =~ s/$mountpoint/[$mountpoint]/;
+
+    # printf formats taken from df.c in coreutils-6.7
+    # Copyright (C) 91, 1995-2006 Free Software Foundation, Inc.
+
+    if (length $path > 20) {
+        printf ("%s\n%20s", $path, "");
+    } else {
+        printf ("%-20s", $path);
+    }
+
+    printf(" %*s %*s %*s %*.0f%% %s\n",
+            9,
+            $total,
+            9,
+            $used,
+            9,
+            $available,
+            3,
+            $usedper,
+            $mountpoint,
+        );
+}
+
+__END__
+
+=pod
+
+=head1 NAME
+
+neb-df - provide a `df` like summary of nebulous volumes
+
+=head1 SYNOPSIS
+
+    neb-df [--db <database>] [--user <username>] [--pass <password>]
+
+=head1 DESCRIPTION
+
+This program outputs a list of Nebulous volumes and various metadata about
+them.  It attempts to conform to the format of data output by the GNU version
+of C<df> when passed the C<-k> flag. E.g. C<df -k>
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --db|-d <database>
+
+Name of database (C<namespace>) to retreive metadata from.
+
+Optional if the appropriate environment variable is set.
+
+=item * --user|-u <username>
+
+Username to authenticate with.
+
+Optional if the appropriate environment variable is set.
+
+=item * --pass|-p <password>
+
+Password to authenticate with.
+
+Optional if the appropriate environment variable is set.
+
+=back
+
+=head1 ENVIRONMENT
+
+These environment variables may be used in place of the specified command line
+options.  All command line option will override the corresponding environment
+value.
+
+=over 4
+
+=item * C<NEB_DB>
+
+Equivalent to --db|-d
+
+=item * C<NEB_USER>
+
+Equivalent to --user|-u
+
+=item * C<NEB_PASS>
+
+Equivalent to --pass|-p 
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2007  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Server>, L<neb-initdb>, L<neb-addvol>, L<nebdiskd>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-initdb
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-initdb	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-initdb	(revision 21994)
@@ -0,0 +1,162 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2005-2007  Joshua Hoblitt
+#
+# $Id: neb-initdb,v 1.7 2007-04-28 01:19:59 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.02';
+
+use DBI;
+use Nebulous::Server::SQL;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ($db, $dbuser, $dbpass);
+
+$db     = $ENV{'NEB_DB'} unless $db;
+$dbuser = $ENV{'NEB_USER'} unless $dbuser;
+$dbpass = $ENV{'NEB_PASS'} unless $dbpass;
+
+GetOptions(
+    'db=s'      => \$db,
+    'user=s'    => \$dbuser,
+    'pass=s'    => \$dbpass,
+) || pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required options: --db --user --pass", -exitval => 2 )
+    unless $db && $dbuser && $dbpass;
+
+my $dbh = DBI->connect(
+    "DBI:mysql:database=$db:host=localhost",
+    $dbuser,
+    $dbpass,
+    {
+        RaiseError => 1,
+        PrintError => 0,
+        AutoCommit => 1,
+    },
+);
+
+my $sql = Nebulous::Server::SQL->new();
+
+print "Dropping any existing tables...";
+
+foreach my $statement (@{ $sql->get_db_clear }) {
+    $dbh->do( $statement );
+}
+
+print " OK\nCreating new tables...";
+
+foreach my $statement (@{ $sql->get_db_schema }) {
+    $dbh->do( $statement );
+}
+
+print " OK\n";
+
+__END__
+
+=pod
+
+=head1 NAME
+
+neb-initdb - initialize a Nebulous server database
+
+=head1 SYNOPSIS
+
+    neb-initdb [--db <database>] [--user <username>] [--pass <password>]
+
+=head1 DESCRIPTION
+
+This program initialize a database for use by L<Nebulous::Server> by creating
+the appropriate set of tables.  Any pre-existing tables with conflicting names
+are first removed.
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --db|-d <database>
+
+Name of database (C<namespace>) to create tables in.
+
+Optional if the appropriate environment variable is set.
+
+=item * --user|-u <username>
+
+Username to authenticate with.
+
+Optional if the appropriate environment variable is set.
+
+=item * --pass|-p <password>
+
+Password to authenticate with.
+
+Optional if the appropriate environment variable is set.
+
+=back
+
+=head1 ENVIRONMENT
+
+These environment variables may be used in place of the specified command line
+options.  All command line option will override the corresponding environment
+value.
+
+=over 4
+
+=item * C<NEB_DB>
+
+Equivalent to --db|-d
+
+=item * C<NEB_USER>
+
+Equivalent to --user|-u
+
+=item * C<NEB_PASS>
+
+Equivalent to --pass|-p 
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2005-2007  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Server>, L<neb-addvol>, L<neb-df>, L<nebdiskd>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-locate
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-locate	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-locate	(revision 21994)
@@ -0,0 +1,172 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2007-2008  Joshua Hoblitt
+#
+# $Id: neb-locate,v 1.3 2008-01-22 21:14:55 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use Nebulous::Client;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ($all, $path, $server, $volume);
+
+$server = $ENV{'NEB_SERVER'} unless $server;
+
+GetOptions(
+    'all|a'         => \$all,
+    'path|p'        => \$path,
+    'server|s=s'    => \$server,
+    'volume=s'      => \$volume,
+) || pod2usage( 2 );
+
+my $key = shift;
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required options: --server <URL> <key>",
+        -exitval => 2 )
+        unless defined $server and defined $key;
+
+my $neb = Nebulous::Client->new(
+    proxy => "$server",
+);
+
+die "can't connected to Nebulous Server: $server"
+    unless defined $neb;
+
+my $uris;
+if (defined $volume) {
+    $uris = $neb->find_instances($key, $volume);
+} else {
+    $uris = $neb->find_instances($key);
+}
+
+unless (defined $uris) {
+    warn "no instances found\n";
+    exit 1;
+}
+
+my @files;
+if (defined $all) { 
+    # print all instances
+    if (defined $path) {
+        @files = map {URI->new($_)->file if $_} @$uris;
+    } else {
+        @files = @$uris;
+    }
+} else {
+    # print just one
+    if (defined $path) {
+        @files = (URI->new(@$uris[0])->file);
+    } else {
+        @files = @$uris[0];
+    }
+}
+
+print join(" ", @files), "\n";
+
+__END__
+
+=pod
+
+=head1 NAME
+
+neb-locate - list URIs|paths to Nebulous key instances
+
+=head1 SYNOPSIS
+
+    neb-locate [--server <URL>] [--volume <volume name>] [--all] [--path] <key>
+
+=head1 DESCRIPTION
+
+This program will lookup the URIs|paths associated with C<<key>> and list them. By default only one instance is listed.
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --all|-a
+
+This flag causes all found instances to be listed.  By default only one (if any
+are found) is reported.
+
+Optional.
+
+=item * --path|-p
+
+This flag causes instances to be listed as C<paths> instead of C<URI>s.
+
+Optional.
+
+=item * --server|-s <URL>
+
+URL of the Nebulous server to connect to.
+
+Optional if the appropriate environment variable is set.
+
+=item * --volume <volume name>
+
+Restrict search for instances to this Nebulous volume.
+
+Optional.
+
+=back
+
+=head1 ENVIRONMENT
+
+These environment variables may be used in place of the specified command line
+options.  All command line option will override the corresponding environment
+value.
+
+=over 4
+
+=item * C<NEB_SERVER>
+
+Equivalent to --server|-s
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2007-2008  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Server>, L<neb-initdb>, L<neb-addvol>, L<nebdiskd>, L<neb-df>,
+L<neb-touch>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-ls
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-ls	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-ls	(revision 21994)
@@ -0,0 +1,129 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2007  Joshua Hoblitt
+#
+# $Id: neb-ls,v 1.4 2007-04-28 01:19:59 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use Nebulous::Client;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ($server);
+
+$server = $ENV{'NEB_SERVER'} unless $server;
+
+GetOptions(
+    'server|s=s'     => \$server,
+) || pod2usage( 2 );
+
+my $pattern = shift;
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required options: --server", -exitval => 2 )
+    unless $server;
+
+my $neb = Nebulous::Client->new(
+    proxy => "$server",
+);
+
+die "can't connected to Nebulous Server: $server"
+    unless defined $neb;
+
+# default to listing everything (bad idea?)
+$pattern ||= ".*";
+
+my $keys = $neb->find_objects($pattern);
+
+if ($keys) {
+    print join(" ", @{ $keys }), "\n";
+}
+
+__END__
+
+=pod
+
+=head1 NAME
+
+neb-ls - list Nebulous keys
+
+=head1 SYNOPSIS
+
+    neb-ls [--server <URL>] <pattern>
+
+=head1 DESCRIPTION
+
+This program list Nebulous keys matched by C<<pattern>>.  Call it with no
+arguments is equivalanet to searching with the pattern C<.*>.  Where
+C<<pattern>> is a POSIX 1003.2 compatable regular repression.
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --server|-s <URL>
+
+URL of the Nebulous server to connect to.
+
+Optional if the appropriate environment variable is set.
+
+=back
+
+=head1 ENVIRONMENT
+
+These environment variables may be used in place of the specified command line
+options.  All command line option will override the corresponding environment
+value.
+
+=over 4
+
+=item * C<NEB_SERVER>
+
+Equivalent to --server|-s
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2007  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Server>, L<neb-initdb>, L<neb-addvol>, L<nebdiskd>, L<neb-df>,
+L<neb-touch>, C<regex(7)>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-mv
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-mv	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-mv	(revision 21994)
@@ -0,0 +1,122 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2007  Joshua Hoblitt
+#
+# $Id: neb-mv,v 1.1 2007-04-28 01:17:45 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use Nebulous::Client;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ($server);
+
+$server = $ENV{'NEB_SERVER'} unless $server;
+
+GetOptions(
+    'server|s=s'    => \$server,
+) || pod2usage( 2 );
+
+my $src = shift;
+my $dst = shift;
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required options: --server <src key> <dst key>",
+        -exitval => 2 )
+        unless defined $server and defined $src and defined $dst;
+
+my $neb = Nebulous::Client->new(
+    proxy => "$server",
+);
+
+die "can't connected to Nebulous Server: $server"
+    unless defined $neb;
+
+$neb->move( $src, $dst ) or warn "move failed";
+
+__END__
+
+=pod
+
+=head1 NAME
+
+neb-mv - move (rename) Nebulous keys
+
+=head1 SYNOPSIS
+
+    neb-mv [--server <URL>] <src key> <dst key>
+
+=head1 DESCRIPTION
+
+This program renames a Nebulous keys.
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --server|-s <URL>
+
+URL of the Nebulous server to connect to.
+
+Optional if the appropriate environment variable is set.
+
+=back
+
+=head1 ENVIRONMENT
+
+These environment variables may be used in place of the specified command line
+options.  All command line option will override the corresponding environment
+value.
+
+=over 4
+
+=item * C<NEB_SERVER>
+
+Equivalent to --server|-s
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2007  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Server>, L<neb-initdb>, L<neb-addvol>, L<nebdiskd>, L<neb-df>,
+L<neb-touch>, C<regex(7)>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-replicate
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-replicate	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-replicate	(revision 21994)
@@ -0,0 +1,136 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2007-2008  Joshua Hoblitt
+#
+# $Id: neb-replicate,v 1.1 2008-01-22 22:10:27 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use Nebulous::Client;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ($server, $volume);
+
+$server = $ENV{'NEB_SERVER'} unless $server;
+
+GetOptions(
+    'server|s=s'    => \$server,
+    'volume|v=s'    => \$volume,
+) || pod2usage( 2 );
+
+my $key = shift;
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required options: --server", -exitval => 2 )
+    unless $server;
+pod2usage( -msg => "missing key", exitval => 2 )
+    unless defined $key;
+
+my $neb = Nebulous::Client->new(
+    proxy => "$server",
+);
+
+die "can't connected to Nebulous Server: $server"
+    unless defined $neb;
+
+if (defined $volume) {
+    $neb->replicate($key, $volume)
+        or die "failed to replicate Nebulous key: $key";
+} else {
+    $neb->replicate($key)
+        or die "failed to replicate Nebulous key: $key";
+}
+
+
+__END__
+
+=pod
+
+=head1 NAME
+
+neb-replicate - create another instance of an object
+
+=head1 SYNOPSIS
+
+    neb-replicate [--server <URL>] [--volume <volume name>] <key>
+
+=head1 DESCRIPTION
+
+This program adds an additonal instance to the Nebulous object with a key of
+C<<key>>.
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --server|-s <URL>
+
+URL of the Nebulous server to connect to.
+
+Optional if the appropriate environment variable is set.
+
+=item * --volume <volume name>
+
+Symbolic name of the volume to create the new instance on.
+
+Optional.
+
+=back
+
+=head1 ENVIRONMENT
+
+These environment variables may be used in place of the specified command line
+options.  All command line option will override the corresponding environment
+value.
+
+=over 4
+
+=item * C<NEB_SERVER>
+
+Equivalent to --server|-s
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2007-2008  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Server>, L<neb-initdb>, L<neb-addvol>, L<nebdiskd>, L<neb-df>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-rm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-rm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-rm	(revision 21994)
@@ -0,0 +1,120 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2007  Joshua Hoblitt
+#
+# $Id: neb-rm,v 1.2 2007-04-28 01:19:59 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use Nebulous::Client;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ($server);
+
+$server = $ENV{'NEB_SERVER'} unless $server;
+
+GetOptions(
+    'server|s=s'    => \$server,
+) || pod2usage( 2 );
+
+pod2usage( -msg => "Required options: --server <key...>", -exitval => 2 )
+        unless defined $server;
+
+my $neb = Nebulous::Client->new(
+    proxy => "$server",
+);
+
+die "can't connected to Nebulous Server: $server"
+    unless defined $neb;
+
+foreach my $key (@ARGV) {
+    $neb->delete($key) or warn "failed to delete key: $key";
+}
+
+__END__
+
+=pod
+
+=head1 NAME
+
+neb-rm - remove Nebulous keys
+
+=head1 SYNOPSIS
+
+    neb-rm [--server <URL>] <key...>
+
+=head1 DESCRIPTION
+
+This program removes Nebulous keys in the whitespace seperated list
+C<<key...>>.
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --server|-s <URL>
+
+URL of the Nebulous server to connect to.
+
+Optional if the appropriate environment variable is set.
+
+=back
+
+=head1 ENVIRONMENT
+
+These environment variables may be used in place of the specified command line
+options.  All command line option will override the corresponding environment
+value.
+
+=over 4
+
+=item * C<NEB_SERVER>
+
+Equivalent to --server|-s
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2007  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Server>, L<neb-initdb>, L<neb-addvol>, L<nebdiskd>, L<neb-df>,
+L<neb-touch>, C<regex(7)>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-touch
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-touch	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/bin/neb-touch	(revision 21994)
@@ -0,0 +1,138 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2007-2008  Joshua Hoblitt
+#
+# $Id: neb-touch,v 1.7 2008-01-25 20:54:04 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use Nebulous::Client;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ($server, $volume);
+
+$server = $ENV{'NEB_SERVER'} unless $server;
+
+GetOptions(
+    'server|s=s'    => \$server,
+    'volume=s'      => \$volume,
+) || pod2usage( 2 );
+
+my $file = shift;
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required options: --server", -exitval => 2 )
+    unless $server;
+pod2usage( -msg => "missing file operand", exitval => 2 )
+    unless defined $file;
+
+my $neb = Nebulous::Client->new(
+    proxy => "$server",
+);
+
+die "can't connected to Nebulous Server: $server"
+    unless defined $neb;
+
+unless (scalar @{$neb->find_objects($file)}) {
+    if (defined $volume) {
+        $neb->create($file, $volume)
+            or die "failed to create Nebulous key $file";
+    } else {
+        $neb->create($file)
+            or die "failed to create Nebulous key $file";
+    }
+}
+
+__END__
+
+=pod
+
+=head1 NAME
+
+neb-touch - create an empty file
+
+=head1 SYNOPSIS
+
+    neb-touch [--server <URL>] [--volume <volume name>] <key>
+
+=head1 DESCRIPTION
+
+This program creates an empty file with the Nebulous key of C<<key>>.  At some
+point in the future it will be able to adjust the timestamp of storage
+instances assosiated with a Nebulous key similar to C<touch(1)>.
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --server|-s <URL>
+
+URL of the Nebulous server to connect to.
+
+Optional if the appropriate environment variable is set.
+
+=item * --volume <volume name>
+
+Symbolic name of the volume to create the first instance on.
+
+Optional.
+
+=back
+
+=head1 ENVIRONMENT
+
+These environment variables may be used in place of the specified command line
+options.  All command line option will override the corresponding environment
+value.
+
+=over 4
+
+=item * C<NEB_SERVER>
+
+Equivalent to --server|-s
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2007-2008  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Server>, L<neb-initdb>, L<neb-addvol>, L<nebdiskd>, L<neb-df>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/bin/nebdiskd
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/bin/nebdiskd	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/bin/nebdiskd	(revision 21994)
@@ -0,0 +1,412 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2007  Joshua Hoblitt
+# 
+# $Id: nebdiskd,v 1.4 2007-05-04 23:36:46 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.02';
+
+use Config::YAML;
+use DBI;
+use File::Spec;
+use Nebulous::Server::SQL;
+use Net::Server::Daemonize qw( daemonize unlink_pid_file );
+use Sys::Statistics::Linux::DiskUsage;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ($debug, $db, $dbuser, $dbpass, $pidfile, $stop, $restart, $verbose);
+GetOptions(
+    'debug'     => \$debug,
+    'db|d=s'    => \$db,
+    'user|u=s'  => \$dbuser,
+    'pass|p=s'  => \$dbpass,
+    'pidfile=s' => \$pidfile,
+    'stop|s'    => \$stop,
+    'restart|r' => \$restart,
+    'verbose|v' => \$verbose,
+) || pod2usage( 2 );
+
+my $rcfile = "$ENV{HOME}/.nebdiskrc";
+$rcfile = File::Spec->canonpath($rcfile);
+
+my $c = read_rcfile($rcfile);
+
+$db     ||= $c->get_db      || $ENV{'NEB_DB'};
+$dbuser ||= $c->get_dbuser  || $ENV{'NEB_USER'};
+$dbpass ||= $c->get_dbpass  || $ENV{'NEB_PASS'};
+$pidfile ||= $c->get_pidfile || "/var/tmp/nebdiskd";
+my $mounts = $c->get_mounts;
+my $poll_interval = $c->get_poll_interval || 5;
+
+if ($restart || $stop) {
+    my $status = kill_pid_file($pidfile);
+    exit($status) if $stop;
+}
+
+$c->set_db($db);
+$c->set_dbuser($dbuser);
+$c->set_dbpass($dbpass);
+$c->set_pidfile($pidfile);
+$c->set_poll_interval($poll_interval);
+$c->write;
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required options: --db --user --pass", -exitval => 2 )
+    unless $db && $dbuser && $dbpass;
+
+daemonize(
+    $<,     # User
+    $),     # Group
+    $pidfile,  # PID file
+) unless $debug;
+
+$SIG{TERM} = sub { unlink_pid_file($pidfile); exit(); };
+$SIG{INT}  = $SIG{TERM};
+$SIG{HUP}  = sub { $c = read_rcfile($rcfile) }; 
+
+my $dbh = setup_db(
+        db      => $db,
+        dbuser  => $dbuser,
+        dbpass  => $dbpass,
+    );
+
+poll_mounts(
+        dbh             => $dbh,
+        poll_interval   => $poll_interval,
+        debug           => $debug,
+    ) or die "poll_mounts() should not have returned";
+
+sub poll_mounts
+{
+    my %p = @_;
+
+    my $dbh             = $p{dbh} or return;
+    my $poll_interval   = $p{poll_interval} || 60;
+    my $debug           = $p{debug} || 0;
+
+    my $lxs = Sys::Statistics::Linux::DiskUsage->new;
+
+    while (1) {
+        # list of mount points to stat so that the automounter will mount these
+        # volumes if they have been unmounted.
+        stat_dirs($mounts);
+
+        eval {
+            my $query = $dbh->prepare_cached("INSERT INTO mount VALUES(?, ?, ?)");
+            $dbh->do("DELETE FROM mount");
+
+            print "flushed mount table\n" if $debug;
+
+            my $stats = $lxs->get;
+            foreach my $dev (keys %$stats) {
+                my $mnt = $stats->{$dev};
+                my %mount;
+                $query->execute(@$mnt{qw( mountpoint total usage )});
+                print "adding $mnt->{mountpoint} to db\n" if $debug;
+            }
+
+            $dbh->do("call getmountedvol()");
+
+            $dbh->commit;
+        };
+        if ($@) {
+            $db->rollback;
+            warn $@;
+        }
+
+        sleep $poll_interval;
+    }
+}
+
+sub read_rcfile
+{
+    my $rcfile = shift;
+
+    return unless defined $rcfile;
+
+    if (!-f $rcfile) {
+        open(my $fh, '>', $rcfile) or die "can't open file: $!";
+        close($fh) or die "can't close file:$!";
+    }
+
+    return Config::YAML->new(
+            config => $rcfile,
+            output => $rcfile,
+    );
+}
+
+
+sub setup_db
+{
+    my %p = @_;
+
+    return unless defined $p{db}
+              and defined $p{dbuser}
+              and defined $p{dbpass};
+
+    my $sql = Nebulous::Server::SQL->new;
+
+    my $dbh = DBI->connect(
+        "DBI:mysql:database=$p{db}:host=localhost",
+        $p{dbuser},
+        $p{dbpass},
+        {
+            RaiseError => 1,
+            PrintError => 1,
+            AutoCommit => 0,
+        },
+    );
+
+    eval {
+        $dbh->do( $sql->set_transaction_model );
+        $dbh->commit;
+    };
+    if ($@) { 
+        $db->rollback;
+        die $@;
+    }
+
+    return $dbh;
+}
+
+
+sub stat_dirs
+{
+    my $mounts = shift;
+
+    return unless defined $mounts;
+
+    foreach my $path (@$mounts) {
+        stat File::Spec->canonpath($path) or warn "can not stat path: $path";
+        print "stated $path\n" if $debug;
+    }
+}
+
+#
+# This function, originally named check_pid_file() was copied from
+# Net::Server::Daemonize '0.05' licensed under the Perl license.  It has been
+# renamed and modified to kill off process who's PID value is stored in pidfile.
+#
+
+sub kill_pid_file {
+  my $pid_file = shift;
+
+  ### no pid_file = return success
+  return 1 unless -e $pid_file;
+
+  ### get the currently listed pid
+  if( ! open(_PID,$pid_file) ){
+    die "Couldn't open existant pid_file \"$pid_file\" [$!]\n";
+  }
+  my $_current_pid = <_PID>;
+  close _PID;
+  my $current_pid = $_current_pid =~ /^(\d{1,10})/ ? $1 : die "Couldn't find pid in existing pid_file";
+
+  my $exists = undef;
+
+  ### try a proc file system
+  if( -d '/proc' ) {
+    $exists = -e "/proc/$current_pid";
+
+  ### try ps
+  #}elsif( -x '/bin/ps' ){ # not as portable
+  # the ps command itself really isn't portable
+  # this follows BSD syntax ps (BSD's and linux)
+  # this will fail on Unix98 syntax ps (Solaris, etc)
+  }elsif( `ps h o pid p $$` =~ /^\s*$$\s*$/ ){ # can I play ps on myself ?
+    $exists = `ps h o pid p $current_pid`;
+
+  }
+
+  ### running process exists, ouch
+    if( $exists ){
+
+        if( $current_pid == $$ ){
+            warn "Pid_file created by this same process. Doing nothing.\n";
+            return 1;
+        }else{
+            kill 'TERM', $current_pid
+                or die "Failed to signal process ($current_pid)";
+            unlink $pid_file || die "Couldn't remove pid_file \"$pid_file\" [$!]\n";
+            return 1;
+
+        }
+    }
+}
+
+__END__
+
+=pod
+
+=head1 NAME
+
+nebdiskd - Nebulous mounted volume capacity monitoring daemon
+
+=head1 SYNOPSIS
+
+    nebdiskd [--db <db name>] [--user <db username>] [--pass <db password>] [--debug] [--pidfile <filename>] [--stop] [--restart] [--verbose]
+
+=head1 DESCRIPTION
+
+This program looks for mounted volumes, at a configurable interval, and records
+statistics about them into a database.
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --db|-d <db name>
+
+Name of database (C<namespace>) to write too.
+
+Optional if defined in the F<.nebdiskdrc> file or the appropriate environment
+variable is set.
+
+=item * --user|-u <db username>
+
+Username to authenticate with.
+
+Optional if defined in the F<.nebdiskdrc> file or the appropriate environment
+variable is set.
+
+=item * --pass|-p <db password>
+
+Password to authenticate with.
+
+Optional if defined in the F<.nebdiskdrc> file or the appropriate environment
+variable is set.
+
+=item * --debug
+
+This flag prevents the program from "daemonizing" so output can be sent to
+C<stdout>/C<stderr> and a debugger used on the running process.
+
+=item * --pidfile <filename>
+
+Filename to log the running daemon's PID too.
+
+Optional, if this option is omitted and no value is defined in the
+F<.nebdiskrc> then no pidfile is created.
+
+=item * --stop|-s
+
+Uses the pidfile to kill an already running daemon.
+
+=item * --restart|-r
+
+Uses the pidfile to kill an already running daemon and then starts a new
+instance.
+
+=item * --verbose|-r
+
+Turns on informational/debugging messages to be sent to the
+C<stderr>/C<stdout>.  This option is probably not very usefully unless combined
+with C<--debug>.
+
+=back
+
+=head1 ENVIRONMENT
+
+These environment variables may be used in place of the specified command line
+options.  All command line option will override the corresponding environment
+value.
+
+=over 4
+
+=item * C<NEB_DB>
+
+Equivalent to --db|-d
+
+=item * C<NEB_USER>
+
+Equivalent to --user|-u
+
+=item * C<NEB_PASS>
+
+Equivalent to --pass|-p 
+
+=back
+
+=head1 RCFILE
+
+This program will attempt to read an C<rcfile> from F<$HOME/.nebdiskrc> and if
+found will use it's values to override program defaults.  Please not that the
+precedence for values is: command line, rcfile, environment variables.
+
+The format of the C<rcfile> is in L<YAML> format and uses the following values:
+
+    ---
+    db: nebulous
+    dbpass: '@neb@'
+    dbuser: nebulous
+    mounts:
+      - /mnt
+      - /tmp
+      - /usr
+    pidfile: /var/tmp/nebdiskd
+    poll_interval: 5
+
+The values C<db>, C<dbpass>, C<dbuser>, and C<pidfile> have the same semantics
+as their command line and/or environment variable equivalents.
+
+=over 4
+
+=item * C<mounts>
+
+A list of "paths" to C<stat(2)> before mounted volumes are polled.  The propose
+of this option is to attempt to keep "automounted" volumes mounted while this
+program is running.
+
+This value may be omitted or left blank.
+
+=item * C<poll_interval>
+
+The number of seconds to wait between checks for mounted volumes.
+
+This value may be omitted or left blank.  The default value is C<60>s.
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2007  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Server>, L<YAML>, L<neb-addvol>, L<neb-df>, L<neb-initdb>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/docs/c_api.h
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/docs/c_api.h	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/docs/c_api.h	(revision 21994)
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2004 Joshua Hoblitt
+ *
+ * $Id: c_api.h,v 1.1.1.1 2004-12-22 02:16:23 jhoblitt Exp $
+ */
+
+// should there be an argument for "suggested" storage location?
+int add( const char *ext_id, const char *data, int size )
+
+int delete( const char *ext_id )
+
+// should there be an argument for "suggested" storage location?
+int update( const char *ext_id, const char *data, int size )
+
+// should there be an argument for "suggested" storage location?
+int move( const char *old_ext_id, const char *new_ext_id )
+
+// open returns a fd 
+int open( const char *ext_id )
+
+int close( const char *ext_id )
+
+// maybe open and close are a bad idea, perhaps...
+int read( const char *ext_id, char *data )
Index: /tags/ipp-1-X/rel-0_06/Nebulous/docs/database_setup.txt
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/docs/database_setup.txt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/docs/database_setup.txt	(revision 21994)
@@ -0,0 +1,59 @@
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id: database_setup.txt,v 1.7 2005-11-09 00:49:44 jhoblitt Exp $
+
+### Database Setup
+
+### MySQL 4.1
+
+DROP DATABASE IF EXISTS nebulous;
+CREATE DATABASE nebulous;
+GRANT ALL PRIVILEGES ON *.* TO 'nebulous'@'localhost'
+    IDENTIFIED BY 'pixel' WITH GRANT OPTION;
+FLUSH PRIVILEGES;
+USE nebulous;
+
+### Initialization
+
+# localhost
+
+$ mkdir /tmp/po01 /tmp/po02
+INSERT INTO volume VALUES (1,'po01','file:/tmp/po01');
+INSERT INTO volume VALUES (1,'po02','file:/tmp/po02');
+
+# NFS
+
+INSERT INTO volume VALUES (1,'po01','file:/netdisks/po01');
+INSERT INTO volume VALUES (2,'po02','file:/netdisks/po02');
+INSERT INTO volume VALUES (3,'po03','file:/netdisks/po03');
+INSERT INTO volume VALUES (4,'po04','file:/netdisks/po04');
+INSERT INTO volume VALUES (5,'po05','file:/netdisks/po05');
+INSERT INTO volume VALUES (6,'po06','file:/netdisks/po06');
+INSERT INTO volume VALUES (7,'po07','file:/netdisks/po07');
+INSERT INTO volume VALUES (8,'po08','file:/netdisks/po08');
+
+INSERT INTO class VALUES (1,3,0,'raw image data');
+
+### Example queries
+
+LOAD DATA INFILE '/home/moa/jhoblitt/tmp/storage_objects.txt' INTO TABLE storage_object; 
+LOAD DATA INFILE '/home/moa/jhoblitt/tmp/instances.txt' INTO TABLE instance; 
+
+SELECT * FROM storage_object LEFT JOIN instance ON storage_object.so_id=instance.so_id WHERE storage_object.ext_id = "foobarbaz1.fits";
+SELECT * FROM storage_object LEFT JOIN instance USING (so_id) WHERE storage_object.ext_id = "foobarbaz1.fits";
+
+SET AUTOCOMMIT = 0;
+BEGIN;
+UPDATE instance SET read_lock=read_lock+1 WHERE ins_id=1;
+INSERT INTO lock_record values (1, 'read', NULL);
+COMMIT;
+
+SET AUTOCOMMIT = 0;
+BEGIN;
+INSERT INTO storage_object values (NULL, 'myfooedbar.fits', 'mr. wizard made this', NULL);
+INSERT INTO instance values (NULL, LAST_INSERT_ID(), 'file://tmp/bat/man/12345a', 'da39a3ee5e6b4b0d3255bfef95601890afd80709',0, NULL, NULL);
+COMMIT;
+
+IF select write_lock from instance WHERE id=1 THEN
+ELSE
+ENDIF
Index: /tags/ipp-1-X/rel-0_06/Nebulous/docs/design.txt
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/docs/design.txt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/docs/design.txt	(revision 21994)
@@ -0,0 +1,283 @@
+# Copyright (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: design.txt,v 1.6 2005-11-05 01:13:35 jhoblitt Exp $
+
+Abstract
+--
+
+Nebulous is a user-space distributed object (file) storage system.  It is much
+more of a database of objects locations then a file system in the traditional
+sense.  Nebulous is considered distributed because of it's data storage model,
+where objects are stored across a number of storage volumes and may have one
+or more redundant copies.  While IPC is done in the traditional client/server
+model with a single[1] centralized server containing all storage object
+meta-data.  This system was designed, unlike most distributed storage system,
+specifically so that clients have the option of hosting one or more storage
+volumes and that data may be stored and accessed locally on a node.  This
+allows network I/O to be dramatically reduced if the end user does simple data
+locality optimizations.  Although, if you so choose, clients and storage
+volumes can reside on independent hardware.  Above all else, Nebulous is
+designed to make efficient use of both disk and network bandwidth.
+
+Data model
+--
+
+In Nebulous terminology a file is refereed to as a a resource.  Each resource
+is represented inside the Nebulous Server as a "Storage Object".  There is one
+Storage Object per resource (a file) that is being managed by the Nebulous
+Server.  A Storage Object maps an External Identifier (eg. filename) to a
+Storage ID.  In addition, creation time and comments may be stored in a
+Storage Object.  Storage Objects /do not/ contain the storage location of a
+resource as we need to allow for N copies of a resource to be stored.  The
+actual storage location of a resource is held in a Storage Object Instance,
+which maps to a Storage ID in a many-to-one relationship.
+
+A Storage Object Instance, or just Instance, represents a single copy of a
+resource being managed by the Nebulous Server. An Instance contains an
+Instance ID, the parent Storage ID, the location of the resource as a URI, and
+other assorted meta-data.
+
+Storage IDs are a signed 64-bit integer.  Negative values are considered
+reserved for future use.  Allocation should be incremental and, as we are
+unlikely to exceed 2^63 Storage Objects in the life time of the project, never
+reused. Instance IDs follow the same scheme as Storage IDs but exists in a
+unique namespace.
+
+Database record relationships
+--
+* All Storage Objects must have at least once associated Instance.
+
+* All Instances must be associated with a Storage Object.
+
+* All Instances must be associated with a valid URI (file exists).
+
+* All Storage Objects with locks set must have the correct number of
+corresponding Lock Records.
+
+* All Lock Records must be associated with a Storage Object.
+
+Data transport
+--
+XXX
+
+Data Storage
+--
+XXX
+
+
+Components
+--
+
+There are 4 principle components required for a working Nebulous system;
+server, client, data transport, and data storage.  The Nebulous software
+distribution provides only the server and the client software.  Data
+transport[2] and Data storage are left to 3rd party software packages.  As
+those functionalities are typically included with most operating systems.
+Nebulous build upon and benefits from advances made in those technologies.
+
+Server
+--
+
+The server is responsible for keeping track of storage objects, all instances
+of that object, and enforcing locking semantics.  Extensive logging and
+tracing support is provided for debug and to allow for statics generation and
+possible X<hotspot> optimization.
+
+Nebulous uses a centralized server model.  This model was choosen because it
+allows efficient X<pattern matching> of storage object names.  The current
+'best' technique for a distributed metadata store is with distributed hash
+tables.  Unfortunately, no widely available DHT implementation allows efficient
+I<pattern matching> of key names.
+
+
+[1] Multiple Nebulous servers should be possible via database replication.
+[2] A future version of Nebulous may include it's own data transport layer
+based on the WEB DAV protocol.
+
+Client <-> Server IPC
+--
+
+The Nebulous Server and clients communicate via the SOAP protocol.  Since SOAP
+is platform independent this allows native Nebulous clients to be written in a
+variety of languages.  With in the Nebulous Server itself the IPC mechanism is
+abstracted to allow ether multi-protocol support or complete replacement of
+SOAP by another protocol.
+
+XXX SOAP namespace
+
+
+Storage volume state tracking.
+
+Nebulous itself does not attempt to determine the state of storage volumes.
+Instead, it relies on some 3rd party to determine both the state
+(available/not) and capacity (total size + % utilized).  This information is
+then feed into Nebulous via either the administrative API or CLI management
+tools.
+
+XXX Storage Location determination
+
+
+Locking semantics
+--
+Nebulous uses 'advisory locking' where clients are excepted to check for the
+existence of locks but this policy is not enforced.  Locks are set on a
+Storage Object and apply to all Instances of that object.
+
+Two types of locks can be set; 'read' locks and 'write' locks.  Read locks are
+implemented as a semaphore while write locks use an exclusive mutex.
+
+    - Read lock
+In order to obtain a Read Lock on a Storage Object the Write Lock mutex must
+be in the state of 'free'.  When a Read Lock is acquire the Read semaphore is
+incremented by one.  When a Read Lock is released the Read semaphore is
+decremented by one.  This must happen atomically with the
+creation/destruction of a Lock Record.
+
+    - Write lock
+In order to obtain a Write lock on a Storage Object the Write Lock mutex must
+be in the state of 'free' and the Read lock semaphore must have a value of
+zero.  When a Write Lock is acquired the Write mutex is set to 'write'.  When a
+Write Lock is released the Write mutex is set to to 'free'.  This must happen
+atomically with the creation/destruction of a Lock Record.  As an extension, a
+sate of 'wait' may be implemented such that clients waiting on Read Locks to
+be released may prevent any additional Read Locks from being acquired.
+
+XXX Lock Records are currently unimplemented
+    - Lock Records A Lock Record is used to double check the indicated lock
+      state of a Storage Object and can be used to identify logical system
+errors.  A Lock Record contains the Storage ID of the object and the type of
+lock set.  eg, enum( 'read', 'write').
+
+    - Client best practices
+When attempting to acquire a lock a client should either "spin lock" with a
+reasonable pause between lock attempts or fail completely.  Aggressive "spin
+locking" is considered antisocial and may eventually require the Nebulous
+Server to identify and ignore such clients.
+
+
+House keeping
+--
+    - Lock sweeping
+In the event that a Storage Object operation fails to complete successfully
+stale locks will have to be identified and removed from the IPP Pixel Data
+Server Database.  This should be done periodically by comparing the entries
+in the Lock table to the list of active nodes maintained by the IPP
+Controller.  It should also happen as soon as possible after a node goes
+offline (triggered by the IPP Controller marking a node as offline?).  A sweep
+must be /completed/ before an offline node can be marked on-line.
+
+Once a node is determined to be offline all entries in the Lock table set by
+that node should be identified.   The locks on the Storage Object
+Instances pointed to by those entries should then be rolled back and Lock
+Record entries themselves must be removed from the lock table.
+
+    - Consistency sweeping
+Periodically the IPP Pixel Data Server meta-data and Storage Object will need
+to be checked for sanity.  This would be similar to running fsck on a modern
+filesystem.  Consistency sweeping should include Lock sweeping and should be
+considered a super-set.
+
+
+Server Operations
+--
+    - setup
+    - create_object
+    - rename_object
+        XXX unimplemented
+    - link_object
+        XXX unimplemented
+    - replicate object
+    - lock_object
+    - unlock_object
+    - find_objects
+        XXX unimplemented
+    - find_instances
+    - delete_instance
+    - fission_object
+        XXX unimplemented
+    - fuse_objects
+        XXX unimplemented
+    - stat_object
+    - stat_instance
+        XXX unimplemented
+
+Client Operations
+--
+    - create
+Creates and opens new Storage Object
+
+    - replicate
+Adds an Instance to a Storage Object
+
+    - cull
+Removes an Instance from a Storage Object
+
+This operation can not remove the last Instance of a Storage Object.
+
+    - lock
+Trys to acquire a lock on a storage object
+
+This operation times out after a default interval of 10s.
+
+    - unlock
+Trys to release a lock on a storage object
+    
+    - find_instances
+Find all instances of a storage object
+
+Only Instances on active storage volumes are found.
+
+    - find
+Find any instance of a storage object
+
+Only Instances on active storage volumes are found.
+
+    - open
+Open a storage object for read or write
+
+Opening a storage object as 'write' will remove all but one Instance to
+prevent Instances from becoming inconsistent.
+
+    - delete
+Delete a storage object and all of it's instances
+
+Removes a storage object and all of it's instances by sequentially deleting each
+Instance.  When a Storage Object has no more associated instances it is
+automatically removed by the Nebulous server.
+
+    - copy
+Copy a storage object
+
+The new storage object will be created with only one Instance.  Most properties
+of the source Storage Object will be preserved.
+
+    - move
+Rename a storage object
+
+Currently this operation will remove all but one instance of the storage
+object and may change it's storage location.
+
+    - delete_instance
+    
+Remove a storage object instance
+
+Removing the last Instance of a Storage Object will destroy the Storage
+Object.
+
+    - stat
+View the properties of a storage object
+
+
+    - import
+        XXX unimplemented
+Import a file into Nebulous
+
+Creates a new Storage Object with the specified External Identifier.  The
+source file will then be "copied" into the Nebulous system leaving the original
+file unmodified.
+
+    - fission
+        XXX unimplemented
+Create a new Storage Object from an existing one by either splitting off an
+Instance and re-parenting it or by cloning an existing Instance and associating
+it with the new Storage Object.
Index: /tags/ipp-1-X/rel-0_06/Nebulous/docs/requirements.txt
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/docs/requirements.txt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/docs/requirements.txt	(revision 21994)
@@ -0,0 +1,28 @@
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id: requirements.txt,v 1.2 2005-09-14 00:46:01 jhoblitt Exp $
+
+- store all image data aquired during the first two years of PS1's
+  operations.  Approximately 10^8 files (OTA level).
+
+- injest new data from the summit at the same rate it is produced when
+  operating at a cadence of 40s between integrations.  Approximately 400Mb/s
+  and 64 files/integration.
+
+- support phase 1 & 2 processing. x files per t_min
+
+- support phase 3 & 4 processing. x files per t_min
+
+- support accessing small blocks of a file (ie., seek)
+
+- tolerate partal system failures without data loss
+
+- execeedly efficent use of both disk and network I/O
+
+what are the science drivers for these 3?
+--
+- data corruption is guarenteed to be detectable.
+
+- relibably store xx.x% of files 
+
+- xx.x% of stored images must be retreivable in xs.
Index: /tags/ipp-1-X/rel-0_06/Nebulous/docs/setup.txt
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/docs/setup.txt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/docs/setup.txt	(revision 21994)
@@ -0,0 +1,369 @@
+=pod
+
+=head1 Installing a Nebulous Server
+
+=head2 Create a UNIX group for Nebulous
+
+All Nebulous user's need to be in the same UNIX group as the Nebulous server.
+
+    groupadd -g 877 nebulous
+
+This is a silly hack to generate a gid.
+
+    perl -le 'map { $gid += ord } split //, shift; print $gid' nebulous
+
+=head2 Add the users that you want to be able to access Nebulous to that group
+
+    usermod -G nebulous foouser
+
+=head2 Setup directory permissions for the nebulous group
+
+As root:
+
+    mkdir /data/ipp000.0/nebulous
+    mkdir /data/ipp000.1/nebulous
+    mkdir /data/ipp002.0/nebulous
+    mkdir /data/ipp003.0/nebulous
+
+    # note that this is just an example, this won't work over NFS with
+    # root_squash enablded
+    chown nobody:nebulous /data/ipp00?.?/nebulous
+
+    chmod 0770 /data/ipp00?.?/nebulous
+    ls -lad /data/ipp00?.?/nebulous
+
+=head2 Build and install the Nebulous Perl modules (see: README)
+
+=head2 Create and initialize the database
+
+    mysql -u root mysql -p
+    (enter your MySQL root password)
+
+    DROP DATABASE IF EXISTS nebulous;
+    CREATE DATABASE nebulous;
+    GRANT ALL PRIVILEGES ON nebulous.* TO 'nebulous'@'localhost'
+        IDENTIFIED BY '@neb@';
+    FLUSH PRIVILEGES;
+    exit
+
+    export NEB_DB=nebulous
+    export NEB_USER=nebulous
+    export NEB_PASS=@neb@
+
+    neb-initdb
+    neb-addvol --name ipp000.0 --uri file:///data/ipp000.0/nebulous
+    neb-addvol --name ipp000.1 --uri file:///data/ipp000.1/nebulous
+    neb-addvol --name ipp002.0 --uri file:///data/ipp002.0/nebulous
+    neb-addvol --name ipp003.0 --uri file:///data/ipp003.0/nebulous
+
+#    perl -e 'for (1..24) { $i = sprintf "po%02d", $_ ; system "neb-addvol --name $i --uri file:/$i/nebulous" }'
+    .
+    .
+
+If you get an error similar to this while initializing the database it means
+that the creation of the Nebulous's stored procedures failed:
+
+    ERROR 1146 (42S02): Table 'mysql.proc' doesn't exist
+
+It probably means that your instance of MySQL has been upgraded for an older
+version that did not support stored precedures.  You can fix this by running
+the C<mysql_fix_privilege_tables> script that you should have received with
+MySQL.
+
+In order for the test suite to pass the "test" account needs have the
+appropriate permissions to create and modify stored procedures.
+
+    update user set Create_routine_priv = 'Y', Alter_routine_priv = 'Y', Execute_priv = 'Y' where user = 'test';
+    update db set Create_routine_priv = 'Y', Alter_routine_priv = 'Y', Execute_priv = 'Y' where db = 'test';
+
+    flush privileges;
+
+Please see this webpage for further details:
+
+http://dev.mysql.com/doc/refman/5.0/en/stored-procedure-privileges.html
+
+
+=head2 Setup nebdiskd daemon
+
+Create the .netdiskrc file in the home directory of the user that nebdiskd
+will run as.  This does not need to be/should not be the root user.  Merely a
+user with permissions to see all of the approparite volumes.
+
+Example F<.netdiskrc>:
+
+    db: nebulous
+    dbpass: '@neb@'
+    dbuser: nebulous
+    mounts:
+      - /data/ipp000.0
+      - /data/ipp000.1
+      - /data/ipp002.0
+      - /data/ipp003.0
+    pidfile: /var/tmp/nebdiskd
+    poll_interval: 5
+
+Start the daemon by running the command C<nebdiskd>.  Use this command to
+verify that the daemon is working correclty.
+
+    neb-volstat
+
+nebdiskd should always been running when nebulous is use.  This command is an
+example of how to startup the daemon running as another user.  This could be
+use to start the daemon from the root account while the system init scripts
+are running.
+
+    sudo -H -u jhoblitt nebdiskd
+
+See the nebdiskd POD/man page for further details
+
+=head2 Install Apache2 with mod_perl
+
+=head3 Minimum software requirements:
+
+Nebulous will work with both Apache 1.3 & 2.x.  However, this guide will only
+cover configuraton with Apache 2.x and mod_perl 2.x.
+
+=over 4
+
+=item * Apache2 >= 2.0.54
+
+=item * mod_perl >= 2.0.0
+
+=item * Apache::DBI >= '0.97' [*]
+
+=back
+
+[*] required for connect_on_init() to work under mod_perl >= 2.0.1
+
+=head3 Apache 1.x 
+
+=item * building mod_perl-1.29 from source:
+
+    perl Makefile.PL USE_APXS=1 INSTALLDIRS=vendor WITH_APXS=/usr/sbin/apxs EVERYTHING=1 PERL_DEBUG=1
+
+    #MP_TRACE = 1 MP_DEBUG = 1 MP_USE_DSO = 1 MP_INST_APACHE2 = 1 MP_APXS = /usr/sbin/apxs2
+
+=head3 Apache 2.x 
+
+=head4 removing Apache on RHEl3
+
+On RHEL3 I had to remove these packages in order to fully remove MySQL.
+
+As C<root>:
+
+    rpm -e \
+    httpd-2.0.46-46.2.ent \
+    httpd-devel-2.0.46-46.2.ent \
+    redhat-config-httpd-1.1.0-4.30.2 \
+    mod_perl-1.99_09-10.ent \
+    mod_authz_ldap-0.22-5 \
+    mod_auth_pgsql-2.0.1-4.ent \
+    mod_python-3.0.3-5.ent \
+    mod_auth_mysql-20030510-2.ent \
+    mod_ssl-2.0.46-46.2.ent \
+    webalizer-2.01_10-15.ent \
+    mod_perl-1.99_09-10.ent \
+    mod_auth_pgsql-2.0.1-4.ent \
+    mod_python-3.0.3-5.ent \
+    mod_auth_mysql-20030510-2.ent \
+    mod_ssl-2.0.46-46.2.ent \
+    squirrelmail-1.4.3a-11.EL3 \
+    php-4.3.2-25.ent \
+    php-imap-4.3.2-25.ent \
+    php-ldap-4.3.2-25.ent \
+    php-mysql-4.3.2-25.ent \
+    php-odbc-4.3.2-25.ent \
+    php-pgsql-4.3.2-25.ent 
+
+    rm -rf /etc/httpd
+
+=head4 installing Apache2 from source
+
+    tar -jxvf httpd-2.0.54.tar.bz2
+    cd httpd-2.0.54
+    ./configure \
+    --disable-suexec \
+    --with-perl=/usr/bin/perl \
+    --with-port=80 \
+    --with-program-name=apache2 \
+    --with-devrandom=/dev/urandom \
+    --prefix           /usr \
+    --exec_prefix      /usr \
+    --bindir           /usr/bin \
+    --sbindir          /usr/sbin \
+    --libdir           /usr/lib \
+    --libexecdir       /usr/lib/apache2/modules \
+    --mandir           /usr/share/man \
+    --infodir          /usr/share/info \
+    --includedir       /usr/include/apache2 \
+    --datadir          /var/www/localhost \
+    --sysconfdir       /etc/apache2/conf \
+    --localstatedir    /var
+    make
+    su
+    make install
+    exit
+    cd ..
+
+=head4 installing mod_perl 2.x
+
+    tar -zxvf mod_perl-2.0.1.tar.gz
+    cd mod_perl-2.0.1
+    perl Makefile.PL
+    (apxs = /usr/sbin/apxs)
+    make
+    su
+    make install
+    echo "LoadModule perl_module /usr/lib/apache2/modules/mod_perl.so" >> /etc/apache2/conf/apache2.conf
+    exit
+
+    apachectl configtest
+    Syntax OK
+
+=head4 installing and configuring Nebulous
+
+    tar -zvxf Nebulous-0.01.tar.gz
+    cd Nebulous-0.01
+    perl Build.PL -axps /usr/sbin/apxs
+    ./Build
+    ./Build test
+    su
+    ./Build install
+
+
+    vi /etc/apache2/conf/startup.pl
+    (change Group to "Group nebulous")
+
+    cp fooconf /etc/apache2/conf/startup.pl
+    echo "PerlPostConfigRequire /etc/apache2/conf/startup.pl" >> /etc/apache2/conf/apache2.conf
+
+
+=head3 configurating Apache to act as a Nebulous/SOAP server
+
+=item * add the "nebulous" group to /etc/group
+=item * configure Apache to run as the nebulous group. 
+
+    Group nebulous
+
+Note that in theory the C<perchild> MPM can run vhosts as differenet
+users/groups but this module is currently non-funcitonal.
+
+L<http://httpd.apache.org/docs/trunk/mod/perchild.html>
+
+=item * configure a path for Neublous
+
+Make sure mod_perl is being loaded into Apache.  In order to do this on
+gentoo, you must edit /etc/config.d/apache2 and add C<-DPERL> to
+C<APACHE2_OTPS>.
+
+    cat <<END >> /etc/apache2/conf/apache2.conf
+    <Location /nebulous>
+        SetHandler perl-script
+        PerlResponseHandler Apache2::SOAP
+        PerlSetVar dispatch_to "PerlHandler Nebulous::Server::SOAP"
+        PerlSetVar options "compress_threshold => 10000"
+    </Location>
+    END
+
+    apachectl configtest
+    Syntax OK
+
+=item * initialize Nebulous database connections from C<startup.pl>
+
+    my $dsn         = 'DBI:mysql:database=nebulous:host=localhost';
+    my $dbuser      = 'nebulous';
+    my $dbpasswd    = '@neb@';
+
+    Apache::DBI->connect_on_init( $dsn, $dbuser, $dbpasswd );
+    Nebulous::Server::SOAP->new_on_init(
+        dsn         => $dsn,
+        dbuser      => $dbuser,
+        dbpasswd    => $dbpasswd,
+        log_level   => 'all',
+    );
+
+# out of date from here down...
+
+#
+# CGI interface
+#
+
+ScriptAlias /nebulous /usr/local/apache/perl/imageserver.pl
+
+<Directory "/usr/local/apache/perl">
+        AllowOverride None
+        Options None
+        Order allow,deny
+        Allow from all
+</Directory>
+
+PerlModule Apache::PerlRun
+<Location /perl>
+        SetHandler perl-script
+        PerlHandler Apache::PerlRun
+        Options ExecCGI
+        allow from all
+        PerlSendHeader On
+</Location>
+
+#
+# Nebulous::Apache interface
+#
+
+PerlModule Apache::DBI
+PerlModule Nebulous::Apache
+
+<Location /nebulous>
+        SetHandler perl-script
+        PerlHandler Nebulous::Apache
+</Location>
+
+- setup the server
+
+As a CGI, will with either Apache 1.3.x or 2.0.x
+
+cp scripts/imagesever.pl /var/www/localhost/cgi-bin
+chmod 755 /var/www/localhost/cgi-bin/imageserver.pl
+touch /tmp/imageserver.log
+chmod 1777 /tmp/imageserver.log
+
+=head2 Testing the Nebulous Server
+
+You can test your configuration with the C<telnet> utility.
+
+    $ telnet localhost 80
+    Trying 127.0.0.1...
+    Connected to localhost.localdomain (127.0.0.1).
+    Escape character is '^]'.
+    GET /nebulous HTTP/1.0
+
+    HTTP/1.1 500 Internal Server Error
+    Date: Wed, 31 Aug 2005 01:10:47 GMT
+    Server: Apache/2.0.54 (Unix) mod_perl/2.0.1 Perl/v5.8.6
+    Content-Length: 645
+    Connection: close
+    Content-Type: text/html; charset=iso-8859-1
+    .
+    .
+
+    Connection closed by foreign host.
+
+If you get an HTTP 5xx code check your apache error_log
+
+
+=head2 MySQL Configuration/tuning
+
+in /etc/mysql/my.cnf
+under [mysqld]
+increase the number of alloweed connections, e.g.
+max_connections = 200
+
+Nebulous makes heavy use of MySQL's C<innodb> table type.  Try configuring
+MySQL with these parameters:
+
+    innodb_log_files_in_group = 2
+    innodb_buffer_pool_size = as big as possible (512M+)
+    innodb_log_buffer_size= 16M
+    innodb_log_file_size=10M
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/docs/tmp.txt
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/docs/tmp.txt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/docs/tmp.txt	(revision 21994)
@@ -0,0 +1,44 @@
+client
+--
+new
+
+new_file
+                new_file
+                open_file
+
+find_file
+    find_instance
+
+open_file
+    find_file
+
+delete_file
+                delete_file
+    nuke
+
+copy_file
+    open_file
+    new_file
+
+move_file
+    copy_file
+    delete_file
+
+replicate_file
+    open_file
+                replicate_file
+
+cull_file
+    find_instance
+    delete_instance
+
+delete_instance
+    nuke
+                delete_instance
+
+find_instance
+                find_instance
+
+# missing
+file_stat
+lock ?
Index: /tags/ipp-1-X/rel-0_06/Nebulous/examples/Makefile
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/examples/Makefile	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/examples/Makefile	(revision 21994)
@@ -0,0 +1,5 @@
+NEB_CFLAGS=`pkg-config nebclient --cflags`
+NEB_LIBS=`pkg-config nebclient --libs`
+
+nebexample: nebexample.c
+	$(CC) $(NEB_CFLAGS) $(CFLAGS) $(NEB_LIBS) $< -o $@
Index: /tags/ipp-1-X/rel-0_06/Nebulous/examples/nebexample.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/examples/nebexample.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/examples/nebexample.c	(revision 21994)
@@ -0,0 +1,45 @@
+// gcc `pkg-config nebclient --cflags --libs` example.c -o example
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <nebclient.h>
+
+#define NEB_SERVER  "http://podb1.ifa.hawaii.edu:80/nebulous"
+#define NEB_KEY     "foobarbaz"
+
+int main (int argc, char **argv) {
+    nebServer       *server = NULL;
+    char            *key = NEB_KEY;
+
+    server = nebServerAlloc(NEB_SERVER);
+    if (!server) {
+        printf("nebServerAlloc() failed\n");
+        exit(EXIT_FAILURE);
+    }
+
+    // make sure there isn't already a file named "foobarbaz" so this example
+    // doesn't cause an error
+    nebDelete(server, key);
+
+    int fh = nebCreate(server, key, 0, NULL, NULL, NULL);
+    if (fh < 0) {
+        printf( "nebCreate() failed: %s\n", nebErr(server));
+        exit(EXIT_FAILURE);
+    }
+
+    // fh is a file descriptor
+    close(fh);
+
+    if (!nebReplicate(server, key, NULL, NULL)) {
+        printf( "nebReplicate() failed: %s\n", nebErr(server));
+        exit(EXIT_FAILURE);
+    }
+
+    if (!nebDelete(server, key)) {
+        printf( "nebDelete() failed: %s\n", nebErr(server));
+        exit(EXIT_FAILURE);
+    }
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/examples/nebexample.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/examples/nebexample.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/examples/nebexample.pl	(revision 21994)
@@ -0,0 +1,28 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Nebulous::Client;
+
+my $neb = Nebulous::Client->new(
+    proxy   => 'http://podb1.ifa.hawaii.edu:80/nebulous'
+);
+
+my $key = shift || 'foobarbaz';
+
+# make sure there isn't already a file named "foobarbaz" so this example
+# doesn't cause an error
+$neb->delete($key);
+
+my $fh = $neb->create($key);
+die "can't create file $key " unless $fh;
+close($fh);
+
+if (!$neb->replicate($key)) {
+    die "can't replicate object $key";
+}
+
+if (!$neb->delete($key)) {
+    die "can't delete object $key";
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Client.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Client.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Client.pm	(revision 21994)
@@ -0,0 +1,747 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: Client.pm,v 1.38 2008-01-25 20:54:04 jhoblitt Exp $
+
+package Nebulous::Client;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = '0.02';
+
+use File::Copy qw();
+use Log::Log4perl qw(get_logger :levels);
+use Nebulous::Client::Log;
+use Nebulous::Util qw( :standard );
+use Params::Validate qw( validate validate_pos SCALAR );
+#use SOAP::Lite +trace => [qw( debug )];
+use SOAP::Lite;
+use Time::HiRes qw( sleep );
+use URI;
+
+use constant LOCK_INTERVAL  => 1;
+use constant LOCK_DEFAULT   => 10;    # default to a 10s lock timeout
+
+$SOAP::Constants::PATCH_HTTP_KEEPALIVE = 1;
+my $log;
+
+# TODO remove most of the logdies
+
+sub import {
+    my $class = shift;
+
+	my %args = validate( @_,
+        {
+            trace => {
+                type        => SCALAR,
+                optional    => 1,
+                default     => 'warn',
+                callbacks   => {
+                    'is valid level' => sub {
+                        defined $LEVELS{ lc $_[0] };
+                    },
+                },
+            },
+        },
+    );
+
+    Nebulous::Client::Log->init;
+    $log = get_logger( "Nebulous::Client" );
+    $log->level( $LEVELS{ lc $args{ 'trace' } } );
+
+    # this has to be after the log level is set
+    $log->debug( "args: @_" );
+
+    return 1;
+}
+
+sub new {
+    my $class = shift;
+
+    my %args = validate( @_,
+        {
+            proxy   => {
+                type        => SCALAR,
+            },
+            uri     => {
+                type        => SCALAR,
+                optional    => 1,
+            },
+        },
+    );
+
+    $log->debug( "entered - @_" );
+
+    my $lite = SOAP::Lite->new(
+            proxy => $args{ 'proxy' },
+            uri   => $args{ 'uri' } || "urn:Nebulous/Server/SOAP",
+    );
+
+    $log->logdie( "can not create SOAP::Lite object" ) unless $lite;
+
+    my $self = bless( { server => $lite }, ref $class || $class );
+
+    $log->debug( "leaving" );
+
+    return $self;
+}
+
+sub create {
+    my $self = shift;
+
+    my ( $key, @params ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    $log->debug( "entered - @_" );
+
+    # how should already existing files be handled?
+
+    my $response = $self->{ 'server' }->create_object( $key, @params );
+    if ( $response->fault ) {
+        $log->error( $response->faultcode, " - ", $response->faultstring );
+        $log->debug( "leaving" );
+
+        return;
+    }
+
+    my $res = $response->result;
+    $log->debug( "server response: $res" );
+
+    my $uri = URI->new($res);
+    $log->debug( "URI is: $uri" );
+
+    $log->debug( "leaving" );
+
+    return $uri;
+}
+
+sub open_create {
+    my $self = shift;
+
+    my ( $key, @params ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    $log->debug( "entered - @_" );
+
+    # how should already existing files be handled?
+
+    my $response = $self->{ 'server' }->create_object( $key, @params );
+    if ( $response->fault ) {
+        $log->error( $response->faultcode, " - ", $response->faultstring );
+        $log->debug( "leaving" );
+
+        return;
+    }
+
+    my $res = $response->result;
+    $log->debug( "server response: $res" );
+
+    my $uri = URI->new($res);
+    $log->debug( "URI is: $uri" );
+
+    my $fh;
+    eval {
+        $fh = _open_uri( $uri, '+<' );
+    };
+    $log->logdie( $@ ) if $@;
+
+    $log->debug( "leaving" );
+
+    return $fh;
+}
+
+sub replicate {
+    my $self = shift;
+
+    my ( $key, @params ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            # volume
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    $log->debug( "entered - @_" );
+
+    # We have to open the instance that we're going to copy from first.  If
+    # we don't do this, it's possible that open will find & open the new
+    # instance that we're in the process of creating
+    my $fh  = $self->open( $key, 'read' );
+    unless ( $fh ) {
+        $log->debug( "can't open $key" );
+        $log->debug( "leaving" );
+
+        return;
+    }
+
+    # ask the server for a new instance attached to our key
+    my $response = $self->{ 'server' }->replicate_object( $key, @params );
+    if ( $response->fault ) {
+        $log->error( $response->faultcode, " - ", $response->faultstring );
+        $log->debug( "leaving" );
+
+        return;
+    }
+
+    my $res = $response->result;
+    $log->debug( "server response: $res" );
+
+    my $uri = URI->new($res);
+    $log->debug( "URI is: $uri" );
+
+    my $new_fh;
+    eval {
+        $new_fh = _open_uri( $uri, '>' );
+    };
+    $log->logdie( $@ ) if $@;
+
+    File::Copy::copy( $fh, $new_fh ) or $log->logdie( "can not copy instance $uri" );
+
+    $log->debug( "copied instance" );
+
+    close( $fh ) or $log->logdie( "can not close $key" );
+    close( $new_fh ) or $log->logdie( "can not close $key" );
+
+    $log->debug( "leaving" );
+
+    return $uri;
+}
+
+sub cull {
+    my $self = shift;
+
+    my ($key, $vol_name) = validate_pos(@_,
+        {
+            type => SCALAR,
+        },
+        {
+            # volume
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    $log->debug( "entered - @_" );
+
+    my $locations;
+    # if vol_name is specified we need to stat the file to find out how many
+    # instances there are on all volumes.  Otherwise we wouldn't know if it's
+    # safe to remove the last instance on the specified volume.
+    # XXX We need some way to determine which is the best instance to remove
+    if (defined $vol_name) {
+        my @stats = $self->stat($key);
+        my $instances = $stats[6];
+        if (defined $instances and $instances < 2) {
+            $log->debug("can not cull - not enough instances");
+            $log->debug("leaving");
+
+            return;
+        }
+
+        $locations = $self->find_instances($key, $vol_name);
+        unless (defined $locations) {
+            $log->debug( "no instances" );
+            $log->debug( "leaving" );
+
+            return;
+        }
+    } else {
+        $locations = $self->find_instances($key);
+        unless ($locations) {
+            $log->debug("no instances");
+            $log->debug("leaving");
+
+            return;
+        }
+
+        if (scalar @{ $locations } < 2) {
+            $log->debug("can not cull - not enough instances");
+            $log->debug("leaving");
+
+            return;
+        }
+    }
+
+    my $uri = $self->delete_instance( @$locations[0] );
+
+    $log->debug("leaving");
+
+    return $uri;
+}
+
+sub lock {
+    my $self = shift;
+
+    my ( $key, $type, $timeout ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is read or write' => sub { $_[0] =~ /^(?:read|write)$/ },
+            },
+        },
+        {
+            type        => SCALAR,
+            default     => LOCK_DEFAULT,
+            optional    => 1,
+            callbacks   => {
+                'is + integer' => sub { $_[0] =~ /^\d+$/ },
+            },
+        },
+    );
+
+    my $endtime = time() + $timeout;
+
+    $log->debug( "entered - @_" );
+
+    my $locked;
+
+    while ( time() < $endtime ) {
+        $log->debug( "trying to get a $type lock..." );
+
+        my $response = $self->{ 'server' }->lock_object( $key, $type );
+        if ( $response->fault ) {
+            $log->error( $response->faultcode, " - ", $response->faultstring );
+            $log->debug( "leaving" );
+            
+            # don't bother to spin lock if the object doesn't exist
+            if ( $response->faultstring =~ /storage object does not exist/ ) {
+                return;
+            }
+
+            next;
+        }
+
+        $locked = $response->result;
+        if ( $locked ) {
+            $log->debug( "got a $type lock" );
+            last;
+        }
+    } continue {
+        $log->debug( "sleeping..." );
+        sleep LOCK_INTERVAL;
+    }
+
+    $log->debug( "can not get a lock" ) unless $locked;
+
+    $log->debug( "leaving" );
+    
+    $locked ? return 1 : return;
+}
+
+sub unlock {
+    my $self = shift;
+
+    my ( $key, $type ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is read or write' => sub { $_[0] =~ /^(?:read|write)$/ },
+            },
+        },
+    );
+
+    $log->debug( "entered - @_" );
+
+    my $unlocked;
+
+    $log->debug( "trying to release a $type lock..." );
+
+    my $response = $self->{ 'server' }->unlock_object( $key, $type );
+    if ( $response->fault ) {
+        $log->error( $response->faultcode, " - ", $response->faultstring );
+        $log->debug( "leaving" );
+
+        return;
+    }
+
+    $unlocked = $response->result;
+    if ( $unlocked ) {
+        $log->debug( "released a $type lock" );
+    } else {
+        $log->debug( "can not release $type lock" );
+    }
+
+    $log->debug( "leaving" );
+    
+    $unlocked ? return 1 : return;
+}
+
+sub find_objects {
+    my $self = shift;
+
+    my ( $pattern ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    $log->debug( "entered - @_" );
+
+    my $response = $self->{ 'server' }->find_objects( $pattern );
+    if ( $response->fault ) {
+        $log->error( $response->faultcode, " - ", $response->faultstring );
+        $log->debug( "leaving" );
+
+        return;
+    }
+
+    my $keys = $response->result;
+
+    $log->debug( "server found: @$keys" );
+
+#    foreach my $path ( @{ $uris } ) {
+#        $path = _get_file_path( $path );
+#    }
+
+    $log->debug( "leaving" );
+
+# note that no keys found is returned as []
+
+    return $keys;
+}
+
+sub find_instances {
+    my $self = shift;
+
+    my ( $key, @params ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            #volume
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    $log->debug( "entered - @_" );
+
+    my $response = $self->{ 'server' }->find_instances( $key, @params );
+    if ( $response->fault ) {
+        $log->error( $response->faultcode, " - ", $response->faultstring );
+        $log->debug( "leaving" );
+
+        return;
+    }
+
+    my $uris = $response->result;
+
+    $log->debug( "server found: @$uris" );
+
+#    foreach my $path ( @{ $uris } ) {
+#        $path = _get_file_path( $path );
+#    }
+
+    $log->debug( "leaving" );
+
+    return $uris;
+}
+
+sub find {
+    my $self = shift;
+
+    my ( $key ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+    );
+
+    $log->debug( "entered - @_" );
+
+    my $locations = $self->find_instances( $key );
+
+    my $path;
+    eval {
+        $path = _get_file_path( $locations->[0] );
+    };
+    $log->logdie( $@ ) if $@;
+
+    $log->debug( "leaving" );
+
+    return $path;
+}
+
+sub open {
+    my $self = shift;
+
+    my ( $key, $type ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is read or write' => sub { $_[0] =~ /^(?:read|write)$/ },
+            },
+        },
+    );
+
+    $log->debug( "entered - @_" );
+
+    my $fh;
+
+    # need to figure out which is the most optimal copy to open
+    my $locations = $self->find_instances( $key );
+
+    my $path;
+    eval {
+        $path = _get_file_path( $locations->[0] );
+    };
+    $log->logdie( $@ ) if $@;
+
+    unless ( $path ) {
+        $log->debug( "no instances" );
+
+        if ( $type eq 'write' ) {
+            $log->debug( "creating a new storage object" );
+
+            my $ret = $self->open_create( $key );
+
+            $log->debug( "leaving" );
+
+            return $ret;
+        } else {
+            $log->debug( "leaving" );
+            return;
+        }
+    }
+
+    if ( $type eq 'write' ) {
+        my $num_instances = scalar @$locations;
+
+        if ( $num_instances > 1 ) {
+            $log->warn( "write not allowed with multiple instances" );
+            $log->debug( "leaving" );
+            return;
+        }
+
+        eval {
+            $fh = _get_filehandle( $path, '+<' );
+        };
+        $log->logdie( $@ ) if $@;
+    } elsif ( $type eq 'read' ) {
+        eval {
+            $fh = _get_filehandle( $path, '<' );
+        };
+        $log->logdie( $@ ) if $@;
+    }
+
+    $log->debug( "leaving" );
+
+    return $fh;
+}
+
+sub delete {
+    my $self = shift;
+
+    my ( $key ) = validate_pos( @_,
+        {
+            type => SCALAR,
+        },
+    );
+
+    $log->debug( "entered - @_" );
+
+    my $locations = $self->find_instances( $key );
+
+    return undef unless $locations;
+        
+    # a lock is implicitly removed when the last storage object is deleted
+    foreach my $uri ( @$locations ) {
+        $self->delete_instance( $uri ) or return undef;
+    }
+
+    $log->debug( "leaving" );
+
+    return 1;
+}
+
+sub copy {
+    my $self = shift;
+
+    my ( $key, $new_key, $volume ) = validate_pos( @_,
+        {
+            type => SCALAR,
+        },
+        {
+            type => SCALAR,
+        },
+        {
+            #volume
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+#    $log->debug( "entered - @_" );
+
+    my $fh      = $self->open( $key, 'read' );
+    unless ( $fh ) {
+        $log->debug( "can not open object" );
+        $log->debug( "leaving" );
+
+        return;
+    }
+
+    my $new_fh;
+    if (defined $volume) {
+        $new_fh  = $self->open_create( $new_key, $volume );
+    } else {
+        $new_fh  = $self->open_create( $new_key );
+    }
+    unless ( $new_fh ) {
+        $log->debug( "can not open object" );
+        $log->debug( "leaving" );
+
+        return;
+    }
+
+    File::Copy::copy( $fh, $new_fh ) or $log->logdie( "can not copy object $key" );
+
+    close( $fh ) or $log->logdie->( "can not close $key" );
+    close( $new_fh ) or $log->logdie->( "can not close $new_key" );
+
+    $log->debug( "leaving" );
+
+    return 1;
+}
+
+sub move {
+    my $self = shift;
+
+    my ( $key, $new_key ) = validate_pos( @_,
+        {
+            type => SCALAR,
+        },
+        {
+            type => SCALAR,
+        },
+    );
+
+    $log->debug( "entered - @_" );
+
+    my $response = $self->{ 'server' }->rename_object( $key, $new_key );
+    if ( $response->fault ) {
+        $log->error( $response->faultcode, " - ", $response->faultstring );
+        $log->debug( "leaving" );
+
+        return;
+    }
+
+    $log->debug( "leaving" );
+
+    return 1;
+}
+
+sub delete_instance {
+    my $self = shift;
+
+    my ($uri) = validate_pos(@_,
+        {
+            type => SCALAR,
+        },
+    );
+
+    $log->debug( "entered - @_" );
+
+    # it is being assumed here that it is better to have files on disk and not in
+    # the database then the inverse.
+
+    my $path;
+    eval {
+        $path = _get_file_path( $uri );
+    };
+    $log->logdie( $@ ) if $@;
+
+    my $response = $self->{ 'server' }->delete_instance( $uri );
+    if ( $response->fault ) {
+        $log->error( $response->faultcode, " - ", $response->faultstring );
+        $log->debug( "leaving" );
+
+        return;
+    }
+
+    $log->debug( "server deleted instance" );
+
+    eval {
+        _nuke_file( $path );
+    };
+    $log->logdie( $@ ) if $@;
+
+    $log->debug( "leaving" );
+
+    return $uri;
+}
+
+sub stat {
+    my $self = shift;
+
+    my ( $key ) = validate_pos( @_,
+        {
+            type => SCALAR,
+        },
+    );
+
+    $log->debug( "entered - @_" );
+
+    my $response = $self->{ 'server' }->stat_object( $key );
+    if ( $response->fault ) {
+        $self->set_err( $response->faultcode, " - ", $response->faultstring );
+        $log->error( $self->err );
+        $log->debug( "leaving" );
+
+        return;
+    }
+
+    $log->debug( "server returned a stat" );
+
+    my $stats = $response->result;
+
+    $log->debug( "leaving" );
+
+    return $stats;
+}
+
+sub err {
+    my $self = shift;
+
+    die "accepts no params" if @_;
+
+    return $self->{ 'err' };
+}
+
+sub set_err {
+    my $self = shift;
+
+    $self->{ 'err' } = shift;
+
+    return $self;
+}
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Client.pod
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Client.pod	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Client.pod	(revision 21994)
@@ -0,0 +1,434 @@
+=pod
+
+=head1 NAME
+
+Nebulous::Client - Nebulous client component
+
+=head1 SYNOPSIS
+
+    use Nebulous::Client;
+
+    my $neb = Nebulous::Client->new(
+        proxy   => 'http://localhost:80/nebulous'
+    );
+
+    my $uri = $neb->create( "key", "node01" );
+    my $fh = $neb->open_create( "key", "node01" );
+    $neb->replicate( "key", "node01" );
+    $neb->cull( "key", "node01" );
+    $neb->lock( "key", 'write' );
+    $neb->unlock( "key", 'write' );
+    my $uris = $neb->find_objects( $pattern );
+    my $uris = $neb->find_instances( "key", "node01" );
+    my $path = $neb->find( "key" );
+    my $fh = $neb->open( "key", 'read' );
+    $data->delete( "key" );
+    $data->copy( "key", "new_key", "node01" );
+    $data->move( "key", "new_key" );
+    $data->delete_instance( $uri );
+    my $stats = $neb->stat( "key" );
+
+=head1 DESCRIPTION
+
+This component provides client access to the Nebulous storage system.  It
+provides an interface for files to be added, managed, and removed from the
+system.
+
+=head1 USAGE
+
+=head2 Import Parameters
+
+This module accepts an optional hash as argument to it's C<import> method and
+exports no I<symbols>.
+
+    use Nebulous::Client trace => qw( debug );
+
+The hash is allowed to have a single key, C<trace>.  This controls the level of
+tracing sent to the standard out.  The value maybe one of: C<off>, C<fatal>,
+C<error>, C<warn>, C<info>, C<debug>, C<all>. 
+
+The default level of tracing is C<warn>.
+
+=head2 Methods
+
+=head3 Constructors
+
+=over 4
+
+=item * new( ... )
+
+Accepts a mandatory hash.
+
+    my $neb = Nebulous::Client->new(
+        proxy   => 'http://localhost:80/nebulous'
+        uri     => 'urn:Nebulous/Server',
+    );
+
+=over 4
+
+=item * proxy
+
+The URL of the Nebulous server to connect to.
+
+=item * uri
+
+The namespace of the SOAP service.  Unless you know what your doing, don't set
+this key.
+
+This key is optional.
+
+=back
+
+=back
+
+=head3 Object Methods
+
+=over 4
+
+
+=item * create($key, $volume).
+
+Creates a new storage object.
+
+=over 4
+
+=item * key
+
+The storage object key (name).
+
+=item * volume
+
+The preferred storage location of initial instance.
+
+This parameter is optional.
+
+=back
+
+Returns a URI or C<undef> on failure.
+
+
+=item * open_create($key, $volume).
+
+Creates and opens new storage object.
+
+=over 4
+
+=item * key
+
+The storage object key (name).
+
+=item * volume
+
+The preferred storage location of initial instance.
+
+This parameter is optional.
+
+=back
+
+Returns a filehandle or C<undef> on failure.
+
+
+=item * replicate($key, $volume)
+
+Adds an instance to a storage object.
+
+=over 4
+
+=item * key
+
+The storage object key (name).
+
+=item * volume
+
+The preferred storage location of initial instance.
+
+This parameter is optional.
+
+=back
+
+Returns true on success.
+
+
+=item * cull($key, $volume)
+
+Removes an instance from a storage object.
+
+=over 4
+
+=item * key
+
+The storage object key (name).
+
+=item * volume
+
+The volume to attempt to remove an instance from.  If there is no instance on
+the specified volume this method will fail.  If there is more then one instance
+on the specified volume I<only one> of them will be removed.
+
+This parameter is optional.
+
+=back
+
+Returns true on success.
+
+
+=item * lock($key, $type, $timeout)
+
+Trys to acquire a lock on a storage object
+
+=over 4
+
+=item * key
+
+The storage object key (name).
+
+=item * type
+
+The type of lock to acquire.  Either C<read> or C<write>.
+
+=item * timeout
+
+The number of seconds to I<try> for a lock.
+
+This parameter is optional.
+
+=back
+
+Returns true on success.
+
+
+=item * unlock($key, $type)
+
+Trys to release a lock on a storage object.
+
+=over 4
+
+=item * key
+
+The storage object key (name).
+
+=item * type
+
+The type of lock to release.  Either C<read> or C<write>.
+
+=back
+
+Returns true on success.
+
+
+=item * find_objects($pattern)
+
+Lists all storage objects that match C<$pattern>.  Where C<$pattern> is a POSIX
+1003.2 compatable regular repression.  Note that this is I<NOT> a Perl or PCRE
+regular expression.
+
+=over 4
+
+=item * pattern
+
+The storage object key (name).
+
+This parameter is optional.
+
+=back
+
+Returns an arrayref of scalars.
+
+
+=item * find_instances($key, $volume)
+
+Lists all instances of a storage object
+
+=over 4
+
+=item * key
+
+The storage object key (name).
+
+=item * volume
+
+Restrict search to this storage location.
+
+This parameter is optional.
+
+=back
+
+Returns an arrayref of scalars.
+
+
+=item * find($key)
+
+Find any instance of a storage object.
+
+=over 4
+
+=item * key
+
+The storage object key (name).
+
+=back
+
+Returns the path to the instance.
+
+
+=item * open($key, $type)
+
+Open a storage object for read or write.
+
+=over 4
+
+=item * key
+
+The storage object key (name).
+
+=item * type
+
+The type of lock to acquire.  Either C<read> or C<write>.
+
+=back
+
+Returns a filehandle or C<undef> on failure.
+
+
+=item * delete($key)
+
+Delete a storage object and all of it's instances.
+
+=over 4
+
+=item * key
+
+The storage object key (name).
+
+=back
+
+Returns true on success.
+
+
+=item * copy($key, $new_key, $volume)
+
+Copy a storage object.
+
+=over 4
+
+=item * key
+
+The source object.
+
+=item * new_key
+
+The destination object.
+
+=item * volume
+
+The preferred storage location of the new instance.
+
+This parameter is optional.
+
+=back
+
+Returns true on success or C<undef> on failure.
+
+
+=item * move($key, $new_key)
+
+Rename a storage object.
+
+=over 4
+
+=item * key
+
+The source object.
+
+=item * new_key
+
+The destination object.
+
+=back
+
+Returns true on success or C<undef> on failure.
+
+
+=item * delete_instance($uri)
+
+Remove a storage object instance.
+
+=over 4
+
+=item * uri
+
+URI of the instance to remove.
+
+=back
+
+Returns true on success or C<undef> on failure.
+
+=item * stat($key)
+
+View the properties of a storage object.
+
+=over 4
+
+=item * key
+
+The storage object key (name).
+
+=back
+
+Returns an arrayref of scalars.
+
+
+=back
+
+=head1 DEVELOPER NOTES
+
+=head1 REFERENCES
+
+=over 4
+
+=item MogileFS
+
+The Nebulous system is similar in function to MogileFS but very different in
+implementation and operation.
+
+L<http://www.danga.com/mogilefs/>
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2004-2005  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the LICENSE file included with
+this module, or in the L<perlgpl> Pod as supplied with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Client::QuickStart>, L<Nebulous::Server>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Client/HTTP.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Client/HTTP.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Client/HTTP.pm	(revision 21994)
@@ -0,0 +1,26 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: HTTP.pm,v 1.2 2005-06-30 02:35:06 jhoblitt Exp $
+
+package Nebulous::Client::HTTP;
+
+use strict;
+
+our $VERSION = '0.01';
+
+use base qw( SOAP::Lite );
+
+sub call {
+    my $result = $_[0]->SUPER::call( @_ );
+
+    if (( UNIVERSAL::isa( $result, 'SOAP::SOM' )) && $result->fault ) {
+
+        return $result->faultstring;
+    }
+
+    return $result;
+}
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Client/Log.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Client/Log.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Client/Log.pm	(revision 21994)
@@ -0,0 +1,45 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: Log.pm,v 1.6 2007-05-05 01:06:27 eugene Exp $
+
+package Nebulous::Client::Log;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = '0.01';
+
+use Log::Log4perl;
+use File::Spec;
+
+sub init {
+    my $log_path;
+    if (defined $ENV{HOME}) {
+    	$log_path = $ENV{HOME};
+    } else {
+    	$log_path = File::Spec->tmpdir();
+    }
+    # my $log_path = $ENV{HOME} or File::Spec->tmpdir();
+
+    my $conf = <<END;
+    log4perl.category.Nebulous.Client = DEBUG, Screen
+#log4perl.category.Nebulous.Client = DEBUG, CLIENTLOGFILE, Screen
+
+    log4perl.appender.Screen        = Log::Log4perl::Appender::Screen
+    log4perl.appender.Screen.stderr = 0
+    log4perl.appender.Screen.layout = Log::Log4perl::Layout::PatternLayout
+    log4perl.appender.Screen.layout.ConversionPattern = %d | %H | %p | %M - %m%n
+
+    log4perl.appender.CLIENTLOGFILE           = Log::Log4perl::Appender::File
+    log4perl.appender.CLIENTLOGFILE.filename  = $log_path/nebulous_client.log
+    log4perl.appender.CLIENTLOGFILE.mode      = append
+    log4perl.appender.CLIENTLOGFILE.layout    = Log::Log4perl::Layout::PatternLayout
+    log4perl.appender.CLIENTLOGFILE.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} | %H | %p | %M - %m%n
+END
+
+    Log::Log4perl::init( \$conf );
+}
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Client/QuickStart.pod
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Client/QuickStart.pod	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Client/QuickStart.pod	(revision 21994)
@@ -0,0 +1,177 @@
+=pod 
+
+=head1 NAME
+
+Nebulous::Server::QuickStart - Nebulous QuickStart Guide 
+
+=head1 Perl CLIENT
+
+The Nebulous Perl Client is composed of several modules but the user interface
+is accessed via the L<Nebulous::Client> module.  The API is also documented in
+the L<Nebulous::Client> Pod.
+
+=head2 Tracing
+
+There is extensive support for execution tracing.  This is set by passing
+parameters to the L<Nebulous::Client> module when it is imported. e.g.
+
+    use Nebulous::Client trace => qw( debug );
+
+Please see the L<Nebulous::Client> documentation for further details.
+
+=head2 Example program
+
+    #!/usr/bin/env perl
+
+    use strict;
+    use warnings FATAL => qw( all );
+
+    use Nebulous::Client;
+
+    my $neb = Nebulous::Client->new(
+        proxy   => 'http://podb1.ifa.hawaii.edu:80/nebulous'
+    );
+
+    my $key = shift || 'foobarbaz';
+
+    # make sure there isn't already a file named "foobarbaz" so this example
+    # doesn't cause an error
+    $neb->delete($key);
+
+    my $fh = $neb->open_create($key);
+    die "can't create file $key " unless $fh;
+    close($fh);
+
+    if (!$neb->replicate($key)) {
+        die "can't replicate object $key";
+    }
+
+    if (!$neb->delete($key)) {
+        die "can't delete object $key";
+    }
+
+=head1 C CLIENT
+
+The Nebulous C Client consists of a single library named
+F<libnebclient-x.x.x.so> (there is also a static lib, F<libnebclient.a>) and a
+single header file named F<nebclient.h>. The API is documented in
+C<nebclient(3)>. As a convince, pkgconfig configuration information is provided
+for linking against the shared library.
+
+=head2 pkgconfig
+
+The C<pkg-config> utility needs to be able to find the pkgconfig info file
+(F<nebulous.pc>) that Nebulous installed. If Nebulous was installed to a path
+other than F</usr> you may need to set the environment variable
+C<PKG_CONFIG_PATH> so that C<pkg-config> can find it.  For example, if Nebulous
+was installed under F</usr/local> you would set:
+
+    export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
+
+=head2 Autoconf
+
+If you are using Autoconf to configure your software, it is highly recommended
+that you use pkgconfig to link against Nebulous.  Below is an example suitable
+for inclusion in your F<configure.ac> file.
+
+    PKG_CHECK_MODULES([NEBCLIENT], [nebclient >= 0.0.1])
+
+This will setup the variables C<NEBLCLIENT_CFLAGS> and C<NEBCLIENT_LIBS> for
+you and C<AC_SUBST()> them.
+
+=head2 Example makefile
+
+    NEB_CFLAGS=`pkg-config nebclient --cflags`
+    NEB_LIBS=`pkg-config nebclient --libs`
+
+    nebexample: nebexample.c
+    	$(CC) $(NEB_CFLAGS) $(CFLAGS) $(NEB_LIBS) $< -o $@
+
+=head2 Example program
+
+    #include <stdio.h>
+    #include <stdlib.h>
+    #include <unistd.h>
+    #include <nebclient.h>
+
+    #define NEB_SERVER  "http://podb1.ifa.hawaii.edu:80/nebulous"
+    #define NEB_KEY     "foobarbaz"
+
+    int main (int argc, char **argv) {
+        nebServer       *server = NULL;
+        char            *key = NEB_KEY;
+
+        server = nebServerAlloc(NEB_SERVER);
+        if (!server) {
+            printf("nebServerAlloc() failed\n");
+            exit(EXIT_FAILURE);
+        }
+
+        // make sure there isn't already a file named "foobarbaz" so this
+        // example doesn't cause an error
+        nebDelete(server, key);
+
+        int fh = nebOpenCreate(server, key, 0, NULL, NULL, NULL);
+        if (fh < 0) {
+            printf( "nebOpenCreate() failed: %s\n", nebErr(server));
+            exit(EXIT_FAILURE);
+        }
+
+        // fh is a file descriptor
+        close(fh);
+
+        if (!nebReplicate(server, key, NULL, NULL)) {
+            printf( "nebReplicate() failed: %s\n", nebErr(server));
+            exit(EXIT_FAILURE);
+        }
+
+        if (!nebDelete(server, key)) {
+            printf( "nebDelete() failed: %s\n", nebErr(server));
+            exit(EXIT_FAILURE);
+        }
+
+        exit(EXIT_SUCCESS);
+    }
+
+=head1 DEVELOPER NOTES
+
+All of the examples in this guide are included with the Nebulous distribution
+under the F<./examples> directory.
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2005  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the LICENSE file included with
+this module, or in the L<perlgpl> Pod as supplied with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Client>, L<nebclient(3)>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server.pm	(revision 21994)
@@ -0,0 +1,1304 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: Server.pm,v 1.49 2008-01-25 02:11:23 jhoblitt Exp $
+
+package Nebulous::Server;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = '0.06';
+
+use base qw( Class::Accessor::Fast );
+
+use DBI;
+use File::ExtAttr qw( setfattr );
+use Log::Log4perl;
+use Nebulous::Server::Config;
+use Nebulous::Server::Log;
+use Nebulous::Server::SQL;
+use Nebulous::Util qw( :standard );
+use Params::Validate qw( validate_pos SCALAR SCALARREF );
+use URI::file;
+
+__PACKAGE__->mk_accessors(qw( log sql config ));
+
+sub new {
+    my $class = shift;
+
+    # let Nebulous::Server::Config validate our params
+    my $config = Nebulous::Server::Config->init( @_ );
+
+    # log4perl is not avaliable until we call init()
+    Nebulous::Server::Log->init($config);
+    my $log = Log::Log4perl::get_logger( "Nebulous::Server" );
+
+    my $sql = Nebulous::Server::SQL->new;
+
+    $log->debug( "entered - @_" );
+
+    my $db;
+    eval {
+        $db = DBI->connect(
+            $config->dsn,
+            $config->dbuser,
+            $config->dbpasswd,
+            {
+                RaiseError => 1,
+                PrintError => 0,
+                AutoCommit => 0,
+            },
+        );
+
+        $db->do( $sql->set_transaction_model );
+
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ( $@ ) {
+        $db->rollback if $db;
+        $log->debug("rollback");
+        $log->logdie( "database error: $@" );
+    }
+
+    $log->debug( "connected to database: ", sub { $db->data_sources; } );
+
+    my $self = bless {}, ref $class || $class;
+    $self->log($log);
+    $self->sql($sql);
+    $self->db($db);
+    $self->config($config);
+
+    $log->debug( "leaving" );
+    
+    return $self;
+}
+
+sub db {
+    my $self = shift;
+
+    if (@_) {
+        $self->{db} = $_[0];
+        return $self;
+    }
+
+    my $log     = $self->log;
+    my $sql     = $self->sql;
+    my $config  = $self->config;
+
+    # if the dbh is still alive, return it
+    if (defined $self->{db} and $self->{db}->ping) {
+        $log->debug("db handle is still alive");
+        return $self->{db};
+    }
+    # otherwise create a new connection
+    $log->debug("db handle is dead");
+
+    # if we're running under mod_perl & Apache::DBI is loaded we want to
+    # reconnect to the database everytime the dbh is requested.  The rational is
+    # that if we're running under mod_perl this is probably a log running
+    # processes and the database might have gone away on us.  Apache::DBI will
+    # take care of getting a valid dbh back.
+    if ($INC{'Apache/DBI.pm'} && $ENV{MOD_PERL}) {
+        my $db;
+        eval {
+            $db = DBI->connect(
+                $config->dsn,
+                $config->dbuser,
+                $config->dbpasswd,
+                {
+                    RaiseError => 1,
+                    PrintError => 0,
+                    AutoCommit => 0,
+                },
+            );
+
+            $db->do( $sql->set_transaction_model );
+
+            $db->commit;
+            $log->debug("commit");
+        };
+        if ( $@ ) {
+            $db->rollback if $db;
+            $log->debug("rollback");
+            $log->logdie( "database error: $@" );
+        }
+
+        $self->{db} = $db;
+
+        return $db;
+    }
+
+    return $self->{db};
+}
+
+
+sub create_object
+{
+    my $self = shift;
+
+    my ($key, $vol_name) = validate_pos(@_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                # check that the volume requested is valid
+                'is valid volume name' => sub { $self->_is_valid_volume_name($_[0]) },
+            },
+            optional    => 1,
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug( "entered - @_" );
+
+    {
+        my $volume;
+        ($volume, $key) = parse_neb_key($key);
+        if (defined $volume) {
+            die "$volume is not a valid volume name"
+                unless $self->_is_valid_volume_name($volume);
+        }
+        $vol_name ||= $volume;
+
+    }
+
+    my ($uri, $vol_id);
+    eval {
+        {
+            # create storage_object
+            my $query = $db->prepare_cached( $sql->new_object ); 
+            $query->execute('NULL', $key);
+        }
+
+        my $object_id;
+        {
+            # get object ID
+            my $query = $db->prepare_cached( $sql->last_insert_id );
+            $query->execute;
+            ($object_id) = $query->fetchrow_array;
+            # XXX finish seems to be required when using LAST_INSERT_ID() or we
+            # get a warning about the stmt handling still be active the next
+            # time LAST_INSERT_ID() is invoked
+            $query->finish;
+        }
+
+        {
+            # create storage_object_attr
+            my $query = $db->prepare_cached( $sql->new_object_attr ); 
+            $query->execute($object_id);
+        }
+
+        {
+            # create instance with no URI
+            my $query = $db->prepare_cached( $sql->new_object_instance );
+            $query->execute;
+        }
+
+        my $ins_id;
+        {
+            # get instance ID
+            my $query = $db->prepare_cached( $sql->last_insert_id );
+            $query->execute;
+            ($ins_id) = $query->fetchrow_array;
+            # XXX finish seems to be required when using LAST_INSERT_ID() or we
+            # get a warning about the stmt handling still be active the next
+            # time LAST_INSERT_ID() is invoked
+            $query->finish;
+        }
+
+        # Unfortunately, since we want to use the instance row's ID as part of the
+        # actual on disk file name we can't try to create the file until after
+        # we've create both a new storage_storage object and instance.
+
+        # TODO add some stuff here to retry if unsucessful
+        ($uri, $vol_id) = $self->_create_empty_instance_file($key, $ins_id, $vol_name);
+        $log->debug("created $uri on volume ID: $vol_id");
+
+        {
+            # update the instance with URI & vol_id that the file is on
+            my $query = $db->prepare_cached( $sql->update_instance_uri );
+            # vol_id, uri, ins_id
+            $query->execute($vol_id, "$uri", $ins_id);
+        }
+
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("error: $@");
+    }
+
+    $log->debug("leaving");
+
+    return "$uri";
+}
+
+sub rename_object
+{
+    my $self = shift;
+
+    my ($key, $newkey) = validate_pos(@_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+        # make sure the "newkey" doesn't already exist
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is not valid object key' => sub { not $self->_is_valid_object_key($_[0]) },
+            },
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug("entered - @_");
+
+    # ignore volumes
+    $key    = parse_neb_key($key);
+    $newkey = parse_neb_key($newkey);
+
+    eval {
+        # rename storage_object
+        my $query = $db->prepare_cached($sql->rename_object); 
+        # this SQL statment takes the new key name as the first param
+        my $rows = $query->execute($newkey, $key);
+
+        # if we affected more then one row something very bad has happened.
+        unless ($rows == 1) {
+            $log->logdie("affected row count is $rows instead of 1");
+        }
+
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    $log->debug("leaving");
+
+    return $newkey;
+}
+
+
+sub replicate_object
+{
+    my $self = shift;
+
+    my ($key, $vol_name) = validate_pos(@_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                # check that the volume name requested is valid
+                'is valid volume name' => sub { $self->_is_valid_volume_name($_[0]) },
+            },
+            optional    => 1,
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug("entered - @_");
+
+    {
+        my $volume;
+        ($volume, $key) = parse_neb_key($key);
+        if (defined $volume) {
+            die "$volume is not a valid volume name"
+                unless $self->_is_valid_volume_name($volume);
+        }
+        $vol_name ||= $volume;
+    }
+
+    my ($uri, $vol_id);
+    eval {
+        my $so_id;
+        {
+            my $query = $db->prepare_cached( $sql->get_object_instances );
+            my $rows = $query->execute($key, 1);
+
+            unless ( $rows > 0 ) {
+                $query->finish;
+                $db->rollback;
+                $log->debug("rollback");
+                $log->logdie( "storage object does not exist" );
+            }
+
+            $so_id = $query->fetchrow_hashref->{ 'so_id' };
+            $query->finish;
+        }
+
+        {
+            my $query = $db->prepare_cached( $sql->new_instance );
+            $query->execute($so_id);
+        }
+
+        my $ins_id;
+        {
+            my $query = $db->prepare_cached( $sql->last_insert_id );
+            $query->execute();
+            ($ins_id) = $query->fetchrow_array;
+            # XXX finish seems to be required when using LAST_INSERT_ID() or we
+            # get a warning about the stmt handling still be active the next
+            # time LAST_INSERT_ID() is invoked
+            $query->finish;
+        }
+
+        # Unfortunately, since we want to use the instance row's ID as part of
+        # the actual on disk file name we can't try to create the file until
+        # after we've create both a new storage_storage object and instance.
+
+        # TODO add some stuff here to retry if unsucessful
+        ($uri, $vol_id) = $self->_create_empty_instance_file($key, $ins_id, $vol_name);
+
+        {
+            my $query = $db->prepare_cached( $sql->update_instance_uri );
+            # vol_id, uri, ins_id
+            $query->execute($vol_id, $uri, $ins_id);
+        }
+
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("error: $@");
+    }
+
+    $log->debug("leaving");
+
+    return "$uri";
+}
+
+sub lock_object
+{
+    my $self = shift;
+
+    my ( $key, $type ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is read or write' => sub { $_[0] =~ /^(?:read|write)$/ },
+            },
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug( "entered - @_" );
+
+    # ignore volume
+    $key = parse_neb_key($key);
+
+    my $so_id;
+    my $read_lock;
+    my $write_lock;
+    my $query;
+
+    eval {
+        {
+            # this will set update locks
+            $query = $db->prepare_cached( $sql->get_object_locks );
+            my $rows = $query->execute( $key );
+            unless ( $rows == 1 ) {
+                $log->logdie( "storage object does not exist" );
+            }
+
+            my $row = $query->fetchrow_hashref;
+            $query->finish;
+
+            $so_id      = $row->{ 'so_id' };
+            $read_lock  = $row->{ 'read_lock' };
+            $write_lock = $row->{ 'write_lock' };
+        }
+
+        if ($type eq 'write') {
+            # can't set a write lock twice and
+            # can't set a write lock if there are read locks
+            if ($write_lock) {
+                $log->logdie("can not write lock twice");
+            }
+            
+            if ($read_lock > 0) {
+                $log->logdie("can not write lock after read lock");
+            }
+
+            {
+                my $query = $db->prepare_cached( $sql->set_write_lock );
+                my $rows = $query->execute($key);
+            
+                # if we affected more then one row something very bad has happened.
+                unless ($rows == 1) {
+                    $log->logdie("affected row count is $rows instead of 1");
+                }
+
+            }
+        } elsif ($type eq 'read') {
+            # can't set a read lock if there's a write lock
+            if ($write_lock) {
+                $log->logdie("can not read lock after write lock");
+            }
+
+            {
+                my $query = $db->prepare_cached( $sql->increment_read_lock );
+                my $rows = $query->execute($key);
+            
+                # if we affected more then one row something very bad has happened.
+                unless ($rows == 1) {
+                    $log->logdie("affected row count is $rows instead of 1");
+                }
+            }
+        }
+
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("error: $@");
+    }
+
+    $log->debug("leaving");
+
+    return 1;
+}
+
+sub unlock_object
+{
+    my $self = shift;
+
+    my ( $key, $type ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is read or write' => sub { $_[0] =~ /^(?:read|write)$/ },
+            },
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug( "entered - @_" );
+
+    # ignore volume
+    $key = parse_neb_key($key);
+
+    my $so_id;
+    my $read_lock;
+    my $write_lock;
+    my $query;
+
+    eval {
+        {
+            # this will set update locks
+            $query = $db->prepare_cached( $sql->get_object_locks );
+            my $rows = $query->execute($key);
+            unless ($rows == 1) {
+                $log->logdie("storage object does not exist");
+            }
+
+            my $row = $query->fetchrow_hashref;
+            $query->finish;
+
+            $so_id      = $row->{ 'so_id' };
+            $read_lock  = $row->{ 'read_lock' };
+            $write_lock = $row->{ 'write_lock' };
+        }
+
+        if ($type eq 'write') {
+            # can't remove a write lock if it doesn't exist
+            if ($read_lock) {
+                $log->logdie("can not have a write lock under a read lock");
+            }
+
+            unless ($write_lock) {
+                $log->logdie("can not remove non-existant write lock");
+            }
+
+            {
+                my $query = $db->prepare_cached( $sql->delete_write_lock );
+                my $rows = $query->execute($key);
+            
+                # if we affected more then one row something very bad has happened.
+                unless ($rows == 1) {
+                    $log->logdie("affected row count is $rows instead of 1");
+                }
+            }
+        } elsif ($type eq 'read') {
+            # can't remove a read lock if there's a write lock and
+            # can't remove a read lock if there aren't any
+            if ($write_lock) {
+                $log->logdie("can not have a read lock under a write lock");
+            }
+               
+            if ($read_lock == 0) {
+                $log->logdie("can not remove non-existant read lock");
+            }
+
+            {
+                my $query = $db->prepare_cached( $sql->decrement_read_lock );
+                my $rows = $query->execute($key);
+            
+                # if we affected more then one row something very bad has happened.
+                unless ($rows == 1) {
+                    $log->logdie("affected row count is $rows instead of 1");
+                }
+
+            }
+        }
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("error: $@");
+    }
+
+    $log->debug( "leaving" );
+
+    return 1;
+}
+
+
+sub setxattr_object
+{
+    my $self = shift;
+
+    my ($key, $name, $value, $flags) = validate_pos(@_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is read or write' => sub { $_[0] =~ /^(?:create|replace)$/i },
+            },
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug("entered - @_");
+
+    # ignore volume
+    $key = parse_neb_key($key);
+
+    eval {
+        my $query;
+
+        if ($flags eq 'create') {
+            $query = $db->prepare_cached( $sql->new_object_xattr );
+        } else {
+            # replace
+            $query = $db->prepare_cached( $sql->replace_object_xattr );
+        }
+
+        # name, value, ext_id
+        my $rows = $query->execute($name, $value, $key);
+
+        # if we affected more then one row something very bad has happened.
+        if ($flags eq 'create') {
+            unless ($rows == 1) {
+                $log->logdie( "affected row count is $rows instead of 1" );
+            }
+        } else {
+            unless ($rows == 2) {
+                $log->logdie( "affected row count is $rows instead of 2" );
+            }
+        }
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    eval { 
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    $log->debug("leaving");
+
+    return 1;
+}
+
+
+sub getxattr_object
+{
+    my $self = shift;
+
+    my ($key, $name) = validate_pos(@_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+        {
+            type        => SCALAR,
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug("entered - @_");
+
+    # ignore volume
+    $key = parse_neb_key($key);
+
+    my $query;
+    eval {
+        $query = $db->prepare_cached( $sql->get_object_xattr );
+        # ext_id, name
+        my $rows = $query->execute($key, $name);
+
+        # if we affected more then one row something very bad has happened.
+        unless ($rows == 1) {
+            $log->logdie( "affected row count is $rows instead of 1" );
+        }
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    my $row = $query->fetchrow_hashref;
+    my $value = $row->{ 'value' };
+    $query->finish;
+
+    $log->debug("leaving");
+
+    return $value;
+}
+
+
+sub listxattr_object
+{
+    my $self = shift;
+
+    my ($key) = validate_pos(@_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug("entered - @_");
+
+    # ignore volume
+    $key = parse_neb_key($key);
+
+    my $query;
+    eval {
+        $query = $db->prepare_cached( $sql->list_object_xattr );
+        # ext_id
+        my $rows = $query->execute($key);
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    my @xattrs;
+    while (my $row = $query->fetchrow_hashref) {
+        push @xattrs, $row->{ 'name' };
+    }
+
+    $log->debug("leaving");
+
+    return @xattrs;
+}
+
+
+sub removexattr_object
+{
+    my $self = shift;
+
+    my ($key, $name) = validate_pos(@_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+        {
+            type        => SCALAR,
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug("entered - @_");
+
+    # ignore volume
+    $key = parse_neb_key($key);
+
+    my $query;
+    eval {
+        $query = $db->prepare_cached( $sql->remove_object_xattr );
+        # ext_id, name
+        my $rows = $query->execute($key, $name);
+
+        # if we affected more then one row something very bad has happened.
+        unless ($rows == 1) {
+            $log->logdie( "affected row count is $rows instead of 1" );
+        }
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    eval { 
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    $log->debug("leaving");
+
+    return 1;
+}
+
+
+sub find_objects
+{
+    my $self = shift;
+
+    my ( $pattern ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug( "entered - @_" );
+
+    my $query;
+
+    eval {
+        $query = $db->prepare_cached( $sql->find_objects );
+        $query->execute( $pattern );
+    };
+    $log->logdie( "database error: $@" ) if $@;
+
+    my @keys;
+
+    while ( my $row = $query->fetchrow_hashref ) {
+        my $key = $row->{ 'ext_id' };
+        push @keys, $key if $key;
+    }
+
+    $log->debug( "no keys found" ) unless ( scalar @keys );
+
+    $log->debug( "leaving" );
+
+    return \@keys;
+}
+
+
+sub find_instances
+{
+    my $self = shift;
+
+    my ($key, $vol_name) = validate_pos(@_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                # check that the volume name requested is valid
+                'is valid volume name' => sub { $self->_is_valid_volume_name($_[0]) },
+            },
+            optional    => 1,
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug("entered - @_");
+
+    {
+        my $volume;
+        ($volume, $key) = parse_neb_key($key);
+        if (defined $volume) {
+            die "$volume is not a valid volume name"
+                unless $self->_is_valid_volume_name($volume);
+        }
+        $vol_name ||= $volume;
+    }
+
+    my $query;
+    eval {
+        if ($vol_name) {
+            $query = $db->prepare_cached( $sql->get_object_instances_by_vol_name );
+            # ext_id, name, available
+            my $rows = $query->execute($key, $vol_name, 1);
+            unless ($rows > 0) {
+                $query->finish;
+                $log->logdie("no instances on storage volume: $vol_name or volume is not available");
+            }
+        } else {
+            $query = $db->prepare_cached( $sql->get_object_instances );
+            # ext_id, available
+            my $rows = $query->execute($key, 1);
+            unless ($rows > 0) {
+                $query->finish;
+                $log->logdie("no instances available");
+            }
+        }
+    };
+    $log->logdie("database error: $@") if $@;
+
+    my @locations;
+
+    while (my $row = $query->fetchrow_hashref) {
+        my $instance = $row->{ 'uri' };
+        push @locations, $instance if $instance;
+    }
+
+    # XXX remove this?
+    $log->logdie("no instances found") unless (scalar @locations);
+
+    $log->debug("found: @locations");
+
+    $log->debug("leaving");
+
+    return \@locations;
+}
+
+
+sub delete_instance
+{
+    my $self = shift;
+
+    my ( $uri ) = validate_pos( @_,
+        {
+            type => SCALAR|SCALARREF,
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug( "entered - @_" );
+
+    eval {
+        my $so_id;
+        my $instances;
+        # get so_id
+        {
+            my $query = $db->prepare_cached( $sql->get_object_from_uri );
+            my $rows = $query->execute( $uri );
+
+            unless ( $rows > 0 ) {
+                $query->finish;
+                $log->logdie( "no instance is associated with uri" );
+            }
+
+            $so_id = $query->fetchrow_hashref->{ 'so_id' };
+            $query->finish;
+
+        }
+
+        {
+            my $query = $db->prepare_cached( $sql->get_instance_count );
+            $query->execute( $so_id );
+
+            $instances = $query->fetchrow_hashref->{ 'count(ins_id)' };
+            $query->finish;
+        }
+
+        # remove instance
+        {
+            my $query = $db->prepare_cached( $sql->delete_instance );
+            my $rows = $query->execute( $uri );
+            $query->finish;
+            
+            # if we affected something other then one row something very bad
+            # has happened
+            unless ( $rows == 1 ) {
+                $log->logdie( "affected row count is $rows instead of 1" );
+            }
+        }
+
+        # if we just deleted the last instance associated with a storage object
+        # remove it too
+        if ( $instances == 1 ) {
+            # we just removed the last instance
+            my $query = $db->prepare_cached( $sql->delete_object );
+            my $rows = $query->execute( $so_id );
+            $query->finish;
+
+            # if we affected something other then two rows something very bad
+            # has happened
+            # this will have to be changed in order to support hardlinks
+            unless ( $rows == 2 ) {
+                $log->logdie( "affected row count is $rows instead of 2" );
+            }
+        }
+
+        $db->commit;
+        $log->debug("commit");
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie( "database error: $@" );
+    }
+
+    $log->debug( "leaving" );
+
+    return 1;
+}
+
+
+sub stat_object
+{
+    my $self = shift;
+
+    my ( $key ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
+    );
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug("entered - @_");
+
+    # ignore volume
+    $key = parse_neb_key($key);
+
+    my $stat;
+    eval {
+        my $query = $db->prepare_cached( $sql->stat_object );
+        my $rows = $query->execute($key);
+
+        unless ($rows == 1) {
+            $log->logdie("no storage object found");
+        }
+
+        $stat = $query->fetchrow_arrayref;
+        $query->finish;
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    $log->debug("leaving");
+
+    return $stat;
+}
+
+
+sub _get_storage_volume
+{
+    my $self = shift;
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    no warnings qw( uninitialized );
+    $log->debug( "entered - @_" );
+    use warnings;
+
+    my $name = shift;
+
+    my ($vol_id, $vol_path, $xattr);
+    eval {
+        # TODO cache this?
+        my $query;
+        my $rows;
+        if ( $name ) {
+            $query = $db->prepare_cached( $sql->get_storage_volume_by_name );
+            # %free, name, avaiable, allocate
+            $rows = $query->execute(0.95, $name, 1, 1);
+            # XXX destinguish between non-existant and unaviable
+            unless ($rows > 0) {
+                $query->finish;
+                $log->logdie("storage volume: $name is not available");
+            }
+            # when matching by name we shouldn't ever match more than once
+            if ($rows > 1) {
+                $query->finish;
+                $log->logdie("affected row count is $rows instead of 1");
+            }
+        } else {
+            $query = $db->prepare_cached( $sql->get_storage_volume );
+            # %free, avaiable, allocate
+            $rows = $query->execute(0.95, 1, 1);
+            # there has to be atleast one storage volume
+            unless ($rows > 0) {
+                $query->finish;
+                $log->logdie("no storage volume is available");
+            }
+        }
+
+        my $free;
+        ($vol_id, $vol_path, $xattr, $free) = $query->fetchrow_array;
+        $query->finish;
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie("database error: $@");
+    }
+
+    $log->logdie("failed to find a suitable volume" )
+        unless defined $vol_id and defined $vol_path;
+
+    $log->debug( "leaving" );
+
+    return ($vol_id, $vol_path, $xattr);
+}
+
+
+sub _is_valid_object_key
+{
+    my ($self, $key) = @_;
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    my $ext_id;
+    eval {
+        my $query = $db->prepare_cached( $sql->get_object ); 
+        $query->execute($key);
+        ($ext_id) = $query->fetchrow_array;
+        $query->finish;
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie( "database error: $@" );
+    }
+
+    if (defined $ext_id) {
+        return 1;
+    } 
+
+    return;
+}
+
+
+sub _is_valid_volume_name
+{
+    my ($self, $vol_name) = @_;
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    my ($vol_id, $vol_path);
+    eval {
+        my $query = $db->prepare_cached( $sql->get_volume_by_name ); 
+        $query->execute( $vol_name );
+        my $free;
+        ($vol_id, $vol_path, $free) = $query->fetchrow_array;
+        $query->finish;
+    };
+    if ($@) {
+        $db->rollback;
+        $log->debug("rollback");
+        $log->logdie( "database error: $@" );
+    }
+
+    if (defined $vol_id and defined $vol_path) {
+        return 1;
+    } 
+
+    return;
+}
+
+sub _create_empty_instance_file
+{
+    my $self = shift;
+
+    my ($key, $ins_id, $volume) = @_;
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    # Find the storage volume to use. 
+    # ->_get_storage_volume() throws an exception on failure.
+    my ($vol_id, $vol_path, $xattr);
+    my ($storage_filename);
+    my ($uri);
+    eval {
+        ($vol_id, $vol_path, $xattr) = $self->_get_storage_volume($volume);
+        $storage_filename = $self->_generate_storage_filename($key, $ins_id);
+        # XXX put a hook for directory hashing here
+        $uri = URI::file->new("$vol_path/$storage_filename");
+        $log->debug("generated uri $uri");
+        $self->_create_empty_file($uri->file);
+    };
+    if ($@) {
+        $log->logdie($@);
+    }
+
+    if ($xattr) {
+        my $path = $uri->file;
+        die "can not set xattr on $path: $!"
+            unless (setfattr($path, 'user.nebulous_key', $key));
+    }
+
+    return ($uri, $vol_id);
+}
+
+
+sub _create_empty_file
+{
+    my $self = shift;
+
+    my ($path) = @_;
+
+    # perl's open() can't do an O_CREAT | O_EXCL
+    die "file $path already exists" if (-e $path);
+
+    my $fh;
+    die "can not open $path: $!"
+        unless (open($fh, '>', $path));
+
+    die "can not close $path: $!"
+        unless (close($fh));
+
+    die "can not chmod $path: $!"
+        unless (chmod 0664, $path);
+
+    return $path;
+}
+
+
+sub _generate_storage_filename
+{
+    my $self = shift;
+
+    my ($key, $ins_id) = @_;
+
+    my $filename = $key;
+    # mangle '/'s into ':'
+    $filename =~ s|/|:|g;
+
+    return "$ins_id.$filename"
+}
+
+
+sub DESTROY
+{
+    my $self = shift;
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    $log->debug( "entered" );
+
+    $self->db->disconnect;        
+
+    $log->debug( "disconnected from database: ", sub { $db->data_sources; } );
+
+    $log->debug( "leaving" );
+}
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server.pod
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server.pod	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server.pod	(revision 21994)
@@ -0,0 +1,134 @@
+=pod
+
+=head1 NAME
+
+Nebulous::Server - Nebulous server component
+
+=head1 SYNOPSIS
+
+    use Nebulous::Server;
+
+    Nebulous::Server->new( $dsn, $username, $passwd );
+    Nebulous::Server->db( $db );
+    Nebulous::Server->log( $log );
+    Nebulous::Server->sql( $sql );
+    Nebulous::Server->config( $config );
+    Nebulous::Server->create_object( $key, $volume );
+    Nebulous::Server->rename_object( $key, $newkey );
+    Nebulous::Server->replicate_object( $key, $volume );
+    Nebulous::Server->lock_object( $key, $type );
+    Nebulous::Server->unlock_object( $key, $type );
+    Nebulous::Server->setxattr_object( $key, $name, $value, $flags );
+    Nebulous::Server->getxattr_object( $key, $name );
+    Nebulous::Server->listxattr_object( $key );
+    Nebulous::Server->removexattr_object( $key );
+    Nebulous::Server->find_objects( $pattern );
+    Nebulous::Server->find_instances( $key, $volume );
+    Nebulous::Server->delete_instance( $uri );
+    Nebulous::Server->stat_object( $key );
+
+=head1 DESCRIPTION
+
+This is the server side component of the Nebulous system.  It is primarily a
+middle-ware abstraction of an SQL database.
+
+=head1 USAGE
+
+Typically, this module would not be directly interacted with (although, it is
+possible to do so).  It is intended that one or more intermediate transport
+layers are used (SOAP, XML-RPC, etc.)
+
+=head2 Import Parameters
+
+This module accepts no arguments to it's C<import> method and exports no
+I<symbols>.
+
+=head2 Methods
+
+=head3 Class Methods
+
+=over 4
+
+=item * setup( $dsn, $username, $passwd );
+
+Accepts 3 parameters, all are mandatory.  Returns Boolean true.  Throws an
+exception on error.
+
+=item * create_object( $key, $volume );
+
+Accepts 4 parameters, only the first is mandatory.  Returns a URI.  Throws an
+exception on error.
+
+=item * replicate_object( $key, $volume );
+
+Accepts 2 parameters, only the first is mandatory.  Returns a URI.  Throws an
+exception on error.
+
+=item * lock_object( $key, $type );
+
+Accepts 2 parameters, all are mandatory.  Returns Boolean true.   Throws an
+exception on error.
+
+=item * unlock_object( $key, $type );
+
+Accepts 2 parameters, all are mandatory.  Returns Boolean true.   Throws an
+exception on error.
+
+=item * find_instance( $key, $volume );
+
+Accepts 2 parameters, only the first is mandatory.  Returns an arrayref.
+Throws an exception on error.
+
+=item * delete_instance( $uri );
+
+Accepts 1 parameters, it is mandatory.  Returns Boolean true.  Throws an
+exception on error.
+
+=item * stat_object( $key );
+
+Accepts 1 parameters, it is mandatory.  Returns a list of: so_id, ext_id,
+read_lock, write_lock, epoch.
+
+=back
+
+=head1 DEVELOPER NOTES
+
+=head2 REFERENCES
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2004-2005  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the LICENSE file included with
+this module, or in the L<perlgpl> Pod as supplied with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+L<Nebulous::Client>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server/Apache.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server/Apache.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server/Apache.pm	(revision 21994)
@@ -0,0 +1,25 @@
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id
+
+package Nebulous::Server::Apache;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = 0.01;
+
+use Nebulous::Server::SOAP;
+use SOAP::Transport::HTTP;
+
+my $server = SOAP::Transport::HTTP::Apache
+    ->dispatch_to( 'Nebulous::Server::SOAP' )
+    ->options({ compress_threshold => 10 * 1024 });
+
+no warnings qw( redefine );
+sub handler { $server->handler(@_); }
+use warnings;
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server/Config.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server/Config.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server/Config.pm	(revision 21994)
@@ -0,0 +1,52 @@
+# Copyright (C) 2005  Joshua Hoblitt
+#
+# $Id: Config.pm,v 1.2 2006-12-12 00:06:27 jhoblitt Exp $
+
+package Nebulous::Server::Config;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = 0.02;
+
+use base qw( Class::Accessor::Fast );
+
+use Nebulous::Util qw( %LEVELS );
+use Params::Validate qw( validate SCALAR );
+
+my $new_validate = {
+    dsn         => { type => SCALAR },
+    dbuser      => { type => SCALAR },
+    dbpasswd    => { type => SCALAR },
+    log_level   => {
+        type        => SCALAR,
+        optional    => 1,
+        default     => 'all',
+        callbacks   => {
+            'is valid level' => sub {
+                defined $LEVELS{ lc $_[0] };
+            },
+        },
+    },
+};
+
+__PACKAGE__->mk_ro_accessors( keys %$new_validate );
+
+sub init {
+    my $class = shift;
+
+    my %p = validate( @_, $new_validate );
+
+    # normalize log levels to lower-case
+    $p{ log_level } = lc $p{ log_level };
+
+    my $self = \%p;
+
+    bless $self, $class || ref $class;
+
+    return $self;
+}
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server/Log.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server/Log.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server/Log.pm	(revision 21994)
@@ -0,0 +1,62 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: Log.pm,v 1.6 2006-12-12 00:02:53 jhoblitt Exp $
+
+package Nebulous::Server::Log;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = '0.02';
+
+use Log::Log4perl;
+use Nebulous::Server::Config;
+
+sub init {
+    my ($self, $config) = @_;
+
+    my $dsn         = $config->dsn;
+    my $dbuser      = $config->dbuser;
+    my $dbpasswd    = $config->dbpasswd;
+
+    my $conf = <<END;
+    log4perl.category.Nebulous.Server = DEBUG, SERVERLOGFILE
+
+    log4perl.appender.SERVERLOGFILE           = Log::Log4perl::Appender::File
+    log4perl.appender.SERVERLOGFILE.filename  = /tmp/nebulous_server.log
+    log4perl.appender.SERVERLOGFILE.mode      = append
+    log4perl.appender.SERVERLOGFILE.layout    = Log::Log4perl::Layout::PatternLayout
+    log4perl.appender.SERVERLOGFILE.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} | %H | %p | %M - %m%n
+#   date | hostname | priority | method/sub - message\n
+
+    log4perl.appender.SQLLOG            = Log::Log4perl::Appender::DBI
+    log4perl.appender.SQLLOG.datasource = $dsn
+    log4perl.appender.SQLLOG.username   = $dbuser
+    log4perl.appender.SQLLOG.password   = $dbpasswd
+    log4perl.appender.SQLLOG.sql        = \
+    INSERT INTO log (timestamp, hostname, level, sub, message) \
+    VALUES          (%d,        %H,       %p,    %M,  %m)
+#        VALUES          (?,         ?,        ?,     ?,   ?)
+#        log4perl.appender.SQLLOG.params.1   = %d
+#        log4perl.appender.SQLLOG.params.2   = %H
+#        log4perl.appender.SQLLOG.params.3   = %p
+#        log4perl.appender.SQLLOG.params.4   = %M
+#        log4perl.appender.SQLLOG.params.5   = %m
+#        log4perl.appender.SQLLOG.usePreparedStmt = 1
+    log4perl.appender.SQLLOG.bufferSize = 2
+    log4perl.appender.SQLLOG.layout     = Log::Log4perl::Layout::NoopLayout
+    log4perl.appender.SQLLOG.warp_message = 0
+END
+
+    if ($INC{'Apache/DBI.pm'} && $ENV{MOD_PERL}) {
+        Log::Log4perl::init_once( \$conf );
+    } else {
+        Log::Log4perl::init( \$conf );
+    }
+
+    return 1;
+}
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server/SOAP.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server/SOAP.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server/SOAP.pm	(revision 21994)
@@ -0,0 +1,78 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: SOAP.pm,v 1.4 2007-05-02 00:42:52 jhoblitt Exp $
+
+package Nebulous::Server::SOAP;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = '0.02';
+
+import SOAP::Data 'name'; 
+use Apache2::Const -compile => qw(OK);
+use Nebulous::Server;
+use SOAP::Lite;
+
+our $AUTOLOAD;
+
+our @args;
+our $neb;
+
+sub new_on_init {
+    my $self = shift;
+
+    require mod_perl2;
+    require Apache2::Module;
+    require Apache2::ServerUtil;
+
+    @args = @_;
+
+    my $s = Apache2::ServerUtil->server;
+    $s->push_handlers(PerlChildInitHandler => \&init);
+
+    return $self;
+}
+
+sub init {
+    my $self = shift;
+
+    $neb = Nebulous::Server->new(@args);        
+
+    return Apache2::Const::OK;
+}
+
+sub AUTOLOAD {
+    my $self = shift;
+
+    my ( $package, $method ) = $AUTOLOAD =~ m/(?:(.+)::)([^:]+)$/;
+    return undef if $method eq 'DESTROY';
+
+    init() unless defined $neb;
+
+    die "process $$ has not been initialized"
+        unless defined $neb;
+
+    die "method $method does not exist in Nebulous::Server"
+        unless defined ${Nebulous::Server::}{$method};
+
+    # create a sub and install it in the package so successive calls to the
+    # same method don't have to go through AUTOLOAD
+    my $method_sub;
+    eval q|
+    $method_sub = sub {
+        my $self = shift;
+        return name( result => $neb->| . $method . q|( @_ ) );
+    }
+    |;
+    die $@ if $@;
+
+    no strict 'refs';
+    *{"${package}::${method}"} = $method_sub;
+    use strict;
+
+    # invoke the method we just created
+    return $self->$method(@_);
+}
+
+1;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server/SQL.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server/SQL.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Server/SQL.pm	(revision 21994)
@@ -0,0 +1,453 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: SQL.pm,v 1.43 2008-01-22 21:27:46 jhoblitt Exp $
+
+package Nebulous::Server::SQL;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = '0.02';
+
+use base qw( Class::Accessor::Fast );
+
+my %sql = (
+    set_transaction_model   => qq{
+        SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
+    },
+    update_instance_uri => qq{
+        UPDATE instance
+        SET vol_id = ?, uri = ?
+        WHERE ins_id = ?
+    },
+    last_insert_id      => qq{
+        SELECT LAST_INSERT_ID()
+    },
+    new_object          => qq{
+        INSERT INTO storage_object
+        (so_id, ext_id, type)
+        VALUES (?, ?, 'REG_FILE')
+    },
+    new_object_attr  => qq{
+        INSERT INTO storage_object_attr
+        (so_id, read_lock, write_lock)
+        VALUES (?, 0, NULL)
+    },
+    delete_object       => qq{
+        DELETE
+            storage_object,
+            storage_object_attr 
+        FROM storage_object
+        JOIN storage_object_attr
+            USING (so_id)
+        WHERE storage_object.so_id = ?
+    },
+    new_object_instance => qq{
+        INSERT INTO instance 
+        VALUES (NULL, LAST_INSERT_ID(), 0, 'error', NULL, NULL, NULL, NULL)
+    },
+    new_instance        => qq{
+        INSERT INTO instance
+        VALUES (NULL, ?, 0, 'error', NULL,NULL, NULL, NULL)
+    },
+    get_object          => qq{
+        SELECT
+            so_id,
+            ext_id,
+            read_lock,
+            write_lock,
+            epoch,
+            mtime
+        FROM storage_object
+        JOIN storage_object_attr
+        USING (so_id)
+        WHERE ext_id = ?
+    },
+    stat_object          => qq{
+        SELECT
+            storage_object.so_id,
+            storage_object.ext_id,
+            read_lock,
+            write_lock,
+            storage_object_attr.epoch,
+            storage_object_attr.mtime,
+            COUNT(instance.so_id) as instances
+        FROM storage_object
+        JOIN storage_object_attr
+            USING (so_id)
+        JOIN instance
+            USING (so_id)
+        WHERE ext_id = ?
+        GROUP BY storage_object.so_id
+    },
+    # Note: this sets an update lock
+    get_object_locks    => qq{
+        SELECT
+            storage_object.so_id,
+            read_lock,
+            write_lock 
+        FROM storage_object
+        JOIN storage_object_attr
+        USING (so_id)
+        WHERE ext_id = ?
+        FOR UPDATE
+    },
+    new_object_xattr  => qq{
+        INSERT INTO storage_object_xattr
+            SELECT
+                so_id,
+                ?,
+                ?        
+            FROM storage_object
+            WHERE ext_id = ?
+    },
+    replace_object_xattr  => qq{
+        REPLACE INTO storage_object_xattr
+            SELECT
+                so_id,
+                ?,
+                ?        
+            FROM storage_object
+            WHERE ext_id = ?
+    },
+    list_object_xattr    => qq{
+        SELECT storage_object_xattr.name
+        FROM storage_object
+        JOIN storage_object_xattr
+        USING (so_id)
+        WHERE ext_id = ?
+    },
+    get_object_xattr    => qq{
+        SELECT storage_object_xattr.value
+        FROM storage_object
+        JOIN storage_object_xattr
+        USING (so_id)
+        WHERE ext_id = ?
+            AND name = ?
+    },
+    remove_object_xattr    => qq{
+        DELETE FROM storage_object_xattr
+        WHERE so_id = (SELECT so_id from storage_object where ext_id = ?)
+            AND name = ?
+    },
+    set_write_lock      => qq{
+        UPDATE storage_object_attr
+        JOIN storage_object
+        USING(so_id)
+        SET write_lock = 'write'
+        WHERE storage_object.ext_id = ?
+    },
+    delete_write_lock   => qq{
+        UPDATE storage_object_attr
+        JOIN storage_object
+        USING(so_id)
+        SET write_lock = NULL
+        WHERE ext_id = ?
+    },
+    increment_read_lock => qq{
+        UPDATE storage_object_attr
+        JOIN storage_object
+        USING(so_id)
+        SET read_lock = read_lock + 1
+        WHERE ext_id = ?
+    },
+    decrement_read_lock => qq{
+        UPDATE storage_object_attr
+        JOIN storage_object
+        USING(so_id)
+        SET read_lock = read_lock - 1
+        WHERE ext_id = ?
+    },
+    delete_instance     => qq{
+        DELETE FROM instance
+        WHERE uri = ?
+    },
+    get_object_from_uri   => qq{
+        SELECT so_id
+        FROM instance
+        WHERE uri = ?
+    },
+    get_instance_count   => qq{
+        SELECT count(ins_id)
+        FROM instance
+        WHERE so_id = ?
+    },
+    get_object_instances    => qq{
+        SELECT
+            storage_object.so_id,
+            uri,
+            assigned_vol_id
+        FROM storage_object
+        JOIN instance
+            USING (so_id)
+        JOIN mountedvol
+            USING(vol_id)
+        WHERE ext_id = ?
+            AND available = ?
+    },
+    get_object_instances_by_vol_name => qq{
+        SELECT
+            storage_object.so_id,
+            uri,
+            assigned_vol_id
+        FROM storage_object
+        JOIN instance
+            USING (so_id)
+        JOIN mountedvol
+            USING(vol_id)
+        WHERE ext_id = ?
+            AND name = ?
+            AND available = ?
+    },
+    get_storage_volume_by_name   => qq{
+        SELECT
+            vol_id,
+            path,
+            xattr,
+            total - used as free
+        FROM mountedvol
+        WHERE
+            used / total < ?
+            AND name = ?
+            AND available = ?
+            AND allocate = ?
+        ORDER BY free DESC
+        LIMIT 1
+    },
+    get_storage_volume          => qq{
+        SELECT
+            vol_id,
+            path,
+            xattr,
+            total - used as free
+        FROM mountedvol
+        WHERE
+            used / total < ?
+            AND available = ?
+            AND allocate = ?
+        ORDER BY free DESC
+        LIMIT 1
+    },
+    new_volume          => qq{
+        INSERT INTO volume (name, path, allocate, available, xattr)
+        VALUES (?, ?, TRUE, TRUE, FALSE)
+    },
+    get_volume_by_name => qq{
+        SELECT vol_id, name, path
+        FROM volume
+        WHERE name = ?
+    },
+    find_objects => qq{
+        SELECT *
+        FROM storage_object
+        WHERE ext_id REGEXP ?
+    },
+    rename_object => qq{
+        UPDATE storage_object
+        SET ext_id = ?
+        WHERE ext_id = ?
+    },
+);
+
+{
+    my @schema;
+
+    local $/ = '###';
+
+    foreach my $statement (<DATA>) {
+        last unless ( $statement =~ /\S+/ );
+        $statement =~ s/###//g;
+        push @schema, $statement;
+    }
+
+    $sql{get_db_schema} = \@schema;
+}
+
+{
+    my @clear = split /;/, <<END;
+SET FOREIGN_KEY_CHECKS=0;
+DROP TABLE IF EXISTS storage_object;
+DROP TABLE IF EXISTS storage_object_attr;
+DROP TABLE IF EXISTS storage_object_xattr;
+DROP TABLE IF EXISTS instance;
+DROP TABLE IF EXISTS lock_record;
+DROP TABLE IF EXISTS volume;
+DROP TABLE IF EXISTS mount;
+DROP TABLE IF EXISTS log;
+DROP TABLE IF EXISTS mountedvol;
+DROP PROCEDURE IF EXISTS getmountedvol;
+SET FOREIGN_KEY_CHECKS=1
+END
+    $sql{get_db_clear} = \@clear;
+}
+
+__PACKAGE__->mk_ro_accessors( keys %sql );
+
+sub new {
+    my $class = shift;
+
+    my $self = \%sql;
+
+    bless $self, $class || ref $class;
+
+    return $self;
+}
+
+1;
+
+__DATA__
+CREATE TABLE storage_object (
+    so_id BIGINT NOT NULL AUTO_INCREMENT,
+    ext_id VARCHAR(255) NOT NULL UNIQUE,
+    type enum('REG_FILE'),
+    PRIMARY KEY(so_id),
+    KEY(ext_id(64)),
+    KEY(type)
+) ENGINE=innodb;
+
+###
+
+CREATE TABLE storage_object_attr (
+    so_id BIGINT NOT NULL AUTO_INCREMENT,
+    read_lock TINYINT DEFAULT 0 NOT NULL,
+    write_lock ENUM( 'write' ),
+    epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    mtime TIMESTAMP,
+    PRIMARY KEY(so_id)
+) ENGINE=innodb;
+
+###
+
+CREATE TABLE storage_object_xattr (
+    so_id BIGINT NOT NULL AUTO_INCREMENT,
+    name VARCHAR(255),
+    value BLOB,
+    PRIMARY KEY(so_id, name)
+) ENGINE=innodb;
+
+###
+
+CREATE TABLE instance (
+    ins_id BIGINT NOT NULL AUTO_INCREMENT,
+    so_id BIGINT NOT NULL,
+    vol_id INT NOT NULL,
+    uri VARCHAR(255) NOT NULL UNIQUE,
+    sha1sum CHAR(40) ASCII,
+    assigned_vol_id INT,
+    epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    mtime TIMESTAMP,
+    PRIMARY KEY(ins_id),
+    KEY(so_id),
+    KEY(vol_id),
+    KEY(uri(64))
+) ENGINE=innodb;
+
+###
+
+CREATE TABLE lock_record (
+    so_id BIGINT NOT NULL,
+    type ENUM( 'read', 'write' ) NOT NULL,
+    epoch TIMESTAMP,
+    KEY(so_ID)
+) ENGINE=innodb;
+
+###
+
+CREATE TABLE volume (
+    vol_id INT NOT NULL AUTO_INCREMENT,
+    name VARCHAR(255) UNIQUE NOT NULL,
+    path VARCHAR(255) NOT NULL,
+    allocate BOOLEAN DEFAULT FALSE,
+    available BOOLEAN DEFAULT FALSE,
+    xattr BOOLEAN DEFAULT FALSE,
+    PRIMARY KEY(vol_id),
+    KEY(name(16)),
+    KEY(allocate),
+    KEY(available)
+) ENGINE=innodb;
+
+###
+
+CREATE TABLE mount (
+    mountpoint VARCHAR(255) NOT NULL,
+    total BIGINT NOT NULL,
+    used BIGINT NOT NULL,
+    PRIMARY KEY(mountpoint)
+) ENGINE=innodb;
+
+###
+
+CREATE TABLE log (
+    timestamp TIMESTAMP,
+    hostname VARCHAR(255),
+    level VARCHAR(255),
+    sub VARCHAR(255),
+    message VARCHAR(2048) NOT NULL,
+    PRIMARY KEY(timestamp)
+) ENGINE=innodb;
+
+###
+
+CREATE TABLE mountedvol(
+    mountpoint VARCHAR(255) NOT NULL,
+    total BIGINT NOT NULL,
+    used BIGINT NOT NULL,
+    vol_id INT NOT NULL,
+    name VARCHAR(255) NOT NULL,
+    path VARCHAR(255) NOT NULL,
+    allocate BOOLEAN DEFAULT FALSE,
+    available BOOLEAN DEFAULT FALSE,
+    xattr BOOLEAN DEFAULT FALSE,
+    KEY(vol_id),
+    KEY(allocate),
+    KEY(available)
+) ENGINE=innodb;
+
+###
+
+CREATE PROCEDURE getmountedvol() DETERMINISTIC
+BEGIN
+    DECLARE done BOOLEAN DEFAULT FALSE;
+    DECLARE vol_idvar INT;
+    DECLARE namevar VARCHAR(255);
+    DECLARE pathvar VARCHAR(255);
+    DECLARE allocatevar BOOLEAN;
+    DECLARE availablevar BOOLEAN;
+    DECLARE xattrvar BOOLEAN;
+    DECLARE trans_level VARCHAR(255);
+    DECLARE cur1 CURSOR FOR SELECT vol_id, name, path, allocate, available, xattr FROM volume;
+    DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = TRUE;
+
+    -- store the current transaction level
+    SELECT @@session.tx_isolation INTO trans_level; 
+
+    -- set trans level to repeatable-read so the volume table does not change
+    -- out from under our cursor
+    SET @@session.tx_isolation = 'REPEATABLE-READ';
+
+    -- iterate over the volume table finding the coresponding entry in the
+    -- mount table and inserting union of the volume & mount row into the
+    -- mountedvol table
+    OPEN cur1;
+
+    DELETE FROM mountedvol;
+
+    myloop: LOOP
+        FETCH cur1 INTO vol_idvar, namevar, pathvar, allocatevar, availablevar, xattrvar;
+        IF `done` THEN LEAVE myloop; END IF;
+        INSERT INTO mountedvol
+            SELECT mountpoint, total, used, vol_idvar, namevar, pathvar, allocatevar, availablevar, xattrvar
+            FROM
+                (SELECT *, INSTR(pathvar, mountpoint) = 1 as substring
+                FROM mount
+                ORDER BY substring DESC, LENGTH(mountpoint) DESC
+                LIMIT 1) as bar;
+    END LOOP myloop;
+    
+    CLOSE cur1;
+
+    -- restore the original transaction level
+    SET @@session.tx_isolation = trans_level;
+
+    COMMIT;
+END 
Index: /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Util.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Util.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/lib/Nebulous/Util.pm	(revision 21994)
@@ -0,0 +1,129 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: Util.pm,v 1.9 2008-01-23 22:46:44 jhoblitt Exp $
+
+package Nebulous::Util;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = '0.01';
+
+use base qw( Exporter );
+
+use File::Spec::Functions;
+use Log::Log4perl qw( :levels );
+use URI::file;
+use URI;
+
+my @symbols = qw(
+    %LEVELS
+    _nuke_file
+    _get_file_path
+    _get_filehandle
+    _open_uri
+    parse_neb_key
+);
+
+our @EXPORT_OK      = @symbols;
+our %EXPORT_TAGS    = ( standard => [ @symbols ] );
+
+our %LEVELS = (
+    off     => $OFF,
+    fatal   => $FATAL,
+    error   => $ERROR,
+    warn    => $WARN,
+    info    => $INFO,
+    debug   => $DEBUG,
+    all     => $ALL,
+);
+
+sub _nuke_file {
+    my $path = shift;
+
+    die "can't unlink file $path: it's a directory" 
+        if -d $path;
+    die "can't unlink file $path: it doesn't exist"
+        unless -e $path;
+    unlink $path or die "can't unlink file $path: $!";
+
+    return 1;
+}
+
+sub _get_file_path {
+    my $uri = shift;
+
+    my $path = URI->new( $uri )->path;
+
+    return $path;
+}
+
+sub _get_filehandle {
+    my ( $path, $flags ) = @_;
+
+    die "can't open file $path: file doesn't exist" 
+        unless -e $path;
+    CORE::open( my $fh, $flags, $path )
+        or die "can't open file $path: $!";
+
+    return $fh;
+}
+
+sub _open_uri {
+    my ( $uri , $flags ) = @_;
+
+    $uri = URI->new("$uri");
+
+    my $fh = _get_filehandle($uri->file, $flags);
+
+    return $fh;
+}
+
+sub parse_neb_key
+{
+    my $text = shift;
+
+    # white space is not allowed
+    if ($text =~ qr/\s+/) {
+        die "keys and URIs may not contain whitespace";
+    }
+
+    my $uri = URI->new($text);
+    my $scheme = $uri->scheme;
+    my $path = $uri->opaque;
+    
+    my $volume;
+    # if this is a valid uri 
+    if (defined $scheme) {
+        # if so, does it use the neb scheme?
+        die "URI does not use the 'neb' scheme"
+            unless $scheme eq 'neb'; 
+
+        # neb:path (not allowed)
+        # neb://<volume name>/...
+        # neb:/path... (leading '/' is stripped)
+        # neb:///path... (same as neb:/path)
+
+        # volume specifier must be at least one character
+        # strip off volume component if it exists
+        $path =~ s|^//([^/]+)||;
+        $volume = $1;
+
+        # require a leading slash if there is no volume name
+        if ((not defined $volume) and (not $path =~ m|^/|)) {
+            die "neb URI scheme requires a leading slash, eg. neb:/";
+        }
+    }
+
+    # strip leading slashes
+    $path =~ s|^/+||;
+
+    # remove multiple /'s and trailing slashes
+    $path = canonpath($path);
+
+    return ($volume, $path);
+}
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/.cvsignore	(revision 21994)
@@ -0,0 +1,21 @@
+Doxyfile
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+compile
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+depcomp
+docs
+install-sh
+libtool
+ltmain.sh
+missing
+nebclient.pc
+stamp-h1
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/Doxyfile.in
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/Doxyfile.in	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/Doxyfile.in	(revision 21994)
@@ -0,0 +1,1219 @@
+# Doxyfile 1.4.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = @PACKAGE_NAME@
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = @PACKAGE_VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+# @top_builddir@ doesn't work for some reason
+OUTPUT_DIRECTORY       = @builddir@/docs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# This tag can be used to specify the encoding used in the generated output. 
+# The encoding is not always determined by the language that is chosen, 
+# but also whether or not the output is meant for Windows or non-Windows users. 
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
+# forces the Windows encoding (this is the default for the Windows binary), 
+# whereas setting the tag to NO uses a Unix-style encoding (the default for 
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING   = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like the Qt-style comments (thus requiring an 
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
+# only. Doxygen will then generate output that is more tailored for Java. 
+# For instance, namespaces will be presented as packages, qualified scopes 
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation.
+
+SHOW_DIRECTORIES       = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from the 
+# version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the progam writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = @top_srcdir@/src
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS          = *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories.
+
+EXCLUDE_PATTERNS       = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = YES
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = @PERL@
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# generate a call dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable call graphs for selected 
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that a graph may be further truncated if the graph's 
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH 
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), 
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, which results in a white background. 
+# Warning: Depending on the platform used, enabling this option may lead to 
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to 
+# read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/Makefile.am	(revision 21994)
@@ -0,0 +1,21 @@
+# Copyright (C) 2005  Joshua Hoblitt
+#
+# $Id: Makefile.am,v 1.13 2007-05-04 02:14:04 jhoblitt Exp $
+
+SUBDIRS = src tests
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA= @PACKAGE@.pc
+
+EXTRA_DIST = nebulous.wsdl
+
+if HAVE_DOXYGEN
+man_MANS = \
+    $(top_builddir)/docs/man/man3/@PACKAGE@.3
+
+docs/man/man3/@PACKAGE@.3:
+	$(DOXYGEN)
+endif
+
+clean-local:
+	-rm -rf docs
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/autogen.sh
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/autogen.sh	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/autogen.sh	(revision 21994)
@@ -0,0 +1,116 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+PROJECT=nebclient
+TEST_TYPE=-f
+# change this to be a unique filename in the top level dir
+FILE=nebulous.wsdl
+
+DIE=0
+
+LIBTOOLIZE=libtoolize
+ACLOCAL="aclocal $ACLOCAL_FLAGS"
+AUTOHEADER=autoheader
+AUTOMAKE=automake
+AUTOCONF=autoconf
+
+($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $LIBTOOLIZE installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/libtool/"
+        DIE=1
+}
+
+($ACLOCAL --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $ACLOCAL installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
+        DIE=1
+}
+
+($AUTOHEADER --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOHEADER installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
+        DIE=1
+}
+
+($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOMAKE installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
+        DIE=1
+}
+
+($AUTOCONF --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOCONF installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
+        DIE=1
+}
+
+if test "$DIE" -eq 1; then
+        exit 1
+fi
+
+test $TEST_TYPE $FILE || {
+        echo "You must run this script in the top-level $PROJECT directory"
+        exit 1
+}
+
+if test -z "$*"; then
+        echo "I am going to run ./configure with no arguments - if you wish "
+        echo "to pass any to it, please specify them on the $0 command line."
+fi
+
+$LIBTOOLIZE --copy --force || echo "$LIBTOOlIZE failed"
+$ACLOCAL || echo "$ACLOCAL failed"
+$AUTOHEADER || echo "$AUTOHEADER failed"
+$AUTOMAKE --add-missing --force-missing --copy || echo "$AUTOMAKE failed"
+$AUTOCONF || echo "$AUTOCONF failed"
+
+# bypass taps bootstrap.sh
+cd ./tests/tap
+$LIBTOOLIZE --copy --force || echo "$LIBTOOlIZE failed"
+$ACLOCAL || echo "$ACLOCAL failed"
+$AUTOHEADER || echo "$AUTOHEADER failed"
+$AUTOMAKE --add-missing --force-missing --copy || echo "$AUTOMAKE failed"
+$AUTOCONF || echo "$AUTOCONF failed"
+cd $ORIGDIR
+
+if test -n `which wsdl2h`; then
+    wsdl2h -o src/nebulous.h -c nebulous.wsdl \
+    && soapcpp2 -d src -c src/nebulous.h \
+    && rm -f src/*.xml
+fi
+
+run_configure=true
+for arg in $*; do
+    case $arg in
+        --no-configure)
+            run_configure=false
+            ;;
+        *)
+            ;;
+    esac
+done
+
+if $run_configure; then
+    $srcdir/configure --enable-maintainer-mode "$@"
+    echo
+    echo "Now type 'make' to compile $PROJECT."
+else
+    echo
+    echo "Now run 'configure' and 'make' to compile $PROJECT."
+fi
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/configure.ac
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/configure.ac	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/configure.ac	(revision 21994)
@@ -0,0 +1,52 @@
+dnl Copyright (C) 2005  Joshua Hoblitt
+dnl
+dnl $Id: configure.ac,v 1.18 2007-07-13 01:06:00 jhoblitt Exp $
+
+AC_PREREQ(2.61)
+
+AC_INIT([nebclient], [0.05], [jhoblitt@cpan.org])
+AC_CONFIG_SRCDIR([nebulous.wsdl])
+
+dnl this enables the building of libtap
+AC_CONFIG_SUBDIRS([tests/tap])
+
+AM_INIT_AUTOMAKE([1.6 foreign dist-bzip2])
+AM_CONFIG_HEADER([config.h])
+AM_MAINTAINER_MODE
+
+AC_LANG(C)
+AC_PROG_CC_C99
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+
+AC_ARG_ENABLE(doxygen,
+  [AS_HELP_STRING(--enable-doxygen ,enable manpage generation)],
+  [AC_MSG_RESULT(doxygen enabled)
+    AC_PATH_PROG([DOXYGEN], [doxygen], [])
+  ],
+  [AC_MSG_RESULT([doxygen disabled])
+    doxygen=off
+  ]
+)
+AM_CONDITIONAL([HAVE_DOXYGEN], test -n "$DOXYGEN" -a "x$doxygen" != "xoff")
+
+dnl needed by doxygen
+AC_PATH_PROG([PERL], [perl], [missing])
+if test "$PERL" = "missing" ; then
+  AC_MSG_ERROR([perl is required])
+fi
+
+AM_CFLAGS="-Wall -fno-strict-aliasing"
+AC_SUBST([AM_CFLAGS])
+
+dnl default install prefix
+AC_PREFIX_DEFAULT([/usr])
+
+AC_CONFIG_FILES([
+  Makefile
+  nebclient.pc
+  Doxyfile
+  src/Makefile
+  tests/Makefile
+])
+AC_OUTPUT
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/nebclient.pc.in
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/nebclient.pc.in	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/nebclient.pc.in	(revision 21994)
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: @PACKAGE@
+Description: Nebulous C client
+Version: @VERSION@
+Libs: -L${libdir} -l@PACKAGE@
+Cflags: -I${includedir}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/nebulous.wsdl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/nebulous.wsdl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/nebulous.wsdl	(revision 21994)
@@ -0,0 +1,288 @@
+<?xml version="1.0"?>
+<definitions name="NebulousServer"
+    targetNamespace="urn:Nebulous/Server/SOAP"
+    xmlns:tns="urn:Nebulous/Server/SOAP"
+    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+    xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/"
+    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+    xmlns="http://schemas.xmlsoap.org/wsdl/"
+    xmlns:ns="urn:Nebulous/Server/SOAP">
+
+    <types>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+            targetNamespace="urn:Nebulous/Server/SOAP"
+            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+            xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
+ 
+            <complexType name="ArrayOfString">
+                <complexContent>
+                    <restriction base="soapenc:Array">
+                        <attribute ref="soapenc:arrayType" 
+                            wsdl:arrayType="string[]"/>
+                    </restriction>
+                </complexContent>
+            </complexType>
+        </schema>
+    </types>
+
+    <message name="create_objectRequest">
+        <part name="key" type="xsd:string" />
+        <part name="volume" type="xsd:string" />
+    </message>
+    <message name="create_objectResponse">
+        <part name="result" type="xsd:string" />
+    </message>
+
+    <message name="rename_objectRequest">
+        <part name="key" type="xsd:string" />
+        <part name="newkey" type="xsd:string" />
+    </message>
+    <message name="rename_objectResponse">
+        <part name="result" type="xsd:string" />
+    </message>
+
+    <message name="replicate_objectRequest">
+        <part name="key" type="xsd:string" />
+        <part name="volume" type="xsd:string" />
+    </message>
+    <message name="replicate_objectResponse">
+        <part name="result" type="xsd:string" />
+    </message>
+
+    <message name="lock_objectRequest">
+        <part name="key" type="xsd:string" />
+        <part name="type" type="xsd:string" />
+    </message>
+    <message name="lock_objectResponse">
+        <part name="result" type="xsd:int" />
+    </message>
+
+    <message name="unlock_objectRequest">
+        <part name="key" type="xsd:string" />
+        <part name="type" type="xsd:string" />
+    </message>
+    <message name="unlock_objectResponse">
+        <part name="result" type="xsd:int" />
+    </message>
+
+    <message name="find_objectsRequest">
+        <part name="pattern" type="xsd:string" />
+    </message>
+    <message name="find_objectsResponse">
+        <!-- fixme -->
+        <part name="result" type="tns:ArrayOfString" />
+    </message>
+
+    <message name="find_instancesRequest">
+        <part name="key" type="xsd:string" />
+        <part name="volume" type="xsd:string" />
+    </message>
+    <message name="find_instancesResponse">
+        <!-- fixme -->
+        <part name="result" type="tns:ArrayOfString" />
+    </message>
+
+    <message name="delete_instanceRequest">
+        <part name="uri" type="xsd:string" />
+    </message>
+    <message name="delete_instanceResponse">
+        <part name="result" type="xsd:int" />
+    </message>
+
+    <message name="stat_objectRequest">
+        <part name="key" type="xsd:string" />
+    </message>
+    <message name="stat_objectResponse">
+        <!-- fixme -->
+        <part name="result" type="tns:ArrayOfString" />
+    </message>
+
+
+    <portType name="Nebulous/Server/SOAPPort">
+        <operation name="create_object">
+            <input  message="tns:create_objectRequest" />
+            <output message="tns:create_objectResponse" />
+            <!--
+                <fault name="" message="" />
+            -->
+        </operation>
+        <operation name="rename_object">
+            <input  message="tns:rename_objectRequest" />
+            <output message="tns:rename_objectResponse" />
+            <!--
+                <fault name="" message="" />
+            -->
+        </operation>
+        <operation name="replicate_object">
+            <input  message="tns:replicate_objectRequest" />
+            <output message="tns:replicate_objectResponse" />
+            <!--
+                <fault name="" message="" />
+            -->
+        </operation>
+        <operation name="lock_object">
+            <input  message="tns:lock_objectRequest" />
+            <output message="tns:lock_objectResponse" />
+            <!--
+                <fault name="" message="" />
+            -->
+        </operation>
+        <operation name="unlock_object">
+            <input  message="tns:unlock_objectRequest" />
+            <output message="tns:unlock_objectResponse" />
+            <!--
+                <fault name="" message="" />
+            -->
+        </operation>
+        <operation name="find_objects">
+            <input  message="tns:find_objectsRequest" />
+            <output message="tns:find_objectsResponse" />
+            <!--
+                <fault name="" message="" />
+            -->
+        </operation>
+        <operation name="find_instances">
+            <input  message="tns:find_instancesRequest" />
+            <output message="tns:find_instancesResponse" />
+            <!--
+                <fault name="" message="" />
+            -->
+        </operation>
+        <operation name="delete_instance">
+            <input  message="tns:delete_instanceRequest" />
+            <output message="tns:delete_instanceResponse" />
+            <!--
+                <fault name="" message="" />
+            -->
+        </operation>
+        <operation name="stat_object">
+            <input  message="tns:stat_objectRequest" />
+            <output message="tns:stat_objectResponse" />
+            <!--
+                <fault name="" message="" />
+            -->
+        </operation>
+    </portType>
+
+
+    <binding name="SOAP" type="tns:Nebulous/Server/SOAPPort">
+        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
+        <operation name="create_object">
+            <soap:operation soapAction="urn:Nebulous/Server/SOAP#create_object" />
+            <input>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </input>
+            <output>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </output>
+        </operation>
+        <operation name="rename_object">
+            <soap:operation soapAction="urn:Nebulous/Server/SOAP#create_object" />
+            <input>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </input>
+            <output>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </output>
+        </operation>
+        <operation name="rename_object">
+            <soap:operation soapAction="urn:Nebulous/Server/SOAP#rename_object" />
+            <input>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </input>
+            <output>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </output>
+        </operation>
+        <operation name="replicate_object">
+            <soap:operation soapAction="urn:Nebulous/Server/SOAP#replicate_object" />
+            <input>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </input>
+            <output>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </output>
+        </operation>
+        <operation name="lock_object">
+            <soap:operation soapAction="urn:Nebulous/Server/SOAP#lock_object" />
+            <input>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </input>
+            <output>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </output>
+        </operation>
+        <operation name="unlock_object">
+            <soap:operation soapAction="urn:Nebulous/Server/SOAP#unlock_object" />
+            <input>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </input>
+            <output>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </output>
+        </operation>
+        <operation name="find_objects">
+            <soap:operation soapAction="urn:Nebulous/Server/SOAP#find_objects" />
+            <input>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </input>
+            <output>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </output>
+        </operation>
+        <operation name="find_instances">
+            <soap:operation soapAction="urn:Nebulous/Server/SOAP#find_instances" />
+            <input>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </input>
+            <output>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </output>
+        </operation>
+        <operation name="delete_instance">
+            <soap:operation soapAction="urn:Nebulous/Server/SOAP#delete_instance" />
+            <input>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </input>
+            <output>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </output>
+        </operation>
+        <operation name="stat_object">
+            <soap:operation soapAction="urn:Nebulous/Server/SOAP#stat_object" />
+            <input>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </input>
+            <output>
+                <soap:body use="encoded" namespace="urn:Nebulous/Server/SOAP"
+                    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+            </output>
+        </operation>
+    </binding>
+
+
+    <service name="Nebulous/Server/SOAP">
+        <port name="Nebulous/Server/SOAPPort" binding="tns:SOAP">
+            <soap:address location="http://localhost:80/nebulous" />
+        </port>
+    </service>
+</definitions>
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/.cvsignore	(revision 21994)
@@ -0,0 +1,19 @@
+.deps
+.libs
+Makefile
+Makefile.in
+SOAP.nsmap
+libnebclient.la
+nebclient.lo
+nebulous.h
+soapC.c
+soapC.lo
+soapClient.c
+soapClient.lo
+soapClientLib.c
+soapH.h
+soapServer.c
+soapServerLib.c
+soapStub.h
+stdsoap2.lo
+xmalloc.lo
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/Makefile.am	(revision 21994)
@@ -0,0 +1,19 @@
+# Copyright (C) 2005  Joshua Hoblitt
+#
+# $Id: Makefile.am,v 1.5 2005-07-27 01:28:04 jhoblitt Exp $
+
+include_HEADERS=nebclient.h
+lib_LTLIBRARIES = libnebclient.la
+libnebclient_la_LDFLAGS = -release @PACKAGE_VERSION@
+libnebclient_la_SOURCES =\
+    nebclient.h\
+    nebclient.c\
+    xmalloc.h\
+    xmalloc.c\
+    SOAP.nsmap\
+    soapC.c\
+    soapClient.c\
+    soapH.h\
+    soapStub.h\
+    stdsoap2.c\
+    stdsoap2.h
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/SOAP.nsmap
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/SOAP.nsmap	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/SOAP.nsmap	(revision 21994)
@@ -0,0 +1,11 @@
+
+#include "soapH.h"
+SOAP_NMAC struct Namespace namespaces[] =
+{
+	{"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/", "http://www.w3.org/*/soap-envelope", NULL},
+	{"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/", "http://www.w3.org/*/soap-encoding", NULL},
+	{"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance", NULL},
+	{"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema", NULL},
+	{"ns1", "urn:Nebulous/Server/SOAP", NULL, NULL},
+	{NULL, NULL, NULL, NULL}
+};
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/nebclient.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/nebclient.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/nebclient.c	(revision 21994)
@@ -0,0 +1,916 @@
+/*
+ * nebclient.c - nebulous client
+ *
+ * Copyright (C) 2005  Joshua Hoblitt
+ *
+ * $Id: nebclient.c,v 1.47 2007-05-04 23:42:08 jhoblitt Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <regex.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <time.h>
+#include "xmalloc.h"
+#include "soapH.h"
+#include "SOAP.nsmap"
+#include "nebclient.h"
+
+#define ERRBUF_SIZE 2048
+#define LOCK_TIMEOUT 10
+#define LOCK_INTERVAL 1
+
+#define nebSetErr(server,...) \
+    p_nebSetErr(__FILE__, __LINE__, __func__, server,__VA_ARGS__)
+
+// this is a slightly more useful error message than returned by assert()
+#define REQUIRE_SERVER \
+    if (!server) { \
+        fprintf(stderr, "parameter 'server' may not be NULL"); \
+        abort(); \
+    }
+
+#define NEBCOPYFILE 0
+
+static void p_nebSetErr(const char * filename, unsigned long lineno, const char *function, nebServer *server, const char *format, ...);
+static void nebSetServerErr(nebServer *server);
+#if NEBCOPYFILE
+static off_t nebCopyFile(nebServer *server, const char *source, const char *dest);
+#endif
+static off_t nebCopyFilehandle(nebServer *server, int sourceFH, int destFH);
+
+static size_t nebParseURI(nebServer *server, const char *URI, char **filename);
+static bool nebNukeFile(nebServer *server, const char *filename);
+static char *nullstrncpy(char *dest, const char *src, size_t n);
+
+nebServer *nebServerAlloc(const char *endpoint)
+{
+    nebServer       *server;
+
+    server          = xmalloc(sizeof(nebServer));
+
+    if (endpoint) {
+        server->endpoint = xmalloc(strlen(endpoint) + 1);
+        strcpy(server->endpoint, endpoint);
+    } else {
+        server->endpoint = NULL;
+    }
+
+    server->soap    = xmalloc(sizeof(struct soap));
+    server->err_buf = xmalloc(ERRBUF_SIZE);
+    server->err_buf_size = ERRBUF_SIZE;
+
+    soap_init(server->soap);
+
+    return server;
+}
+
+void nebServerFree(nebServer *server)
+{
+    if (!server) {
+        return;
+    }
+
+    soap_end(server->soap); // remove deserialized data and clean up
+    soap_done(server->soap); // detach the gSOAP environment
+
+    nebFree(server->endpoint);
+    nebFree(server->soap);
+    nebFree(server->err_buf);
+    nebFree(server);
+}
+
+char *nebCreate(nebServer *server, const char *key, const char *volume, char **URI)
+{
+    struct ns1__create_USCOREobjectResponse response;
+    char            *filename;
+
+    REQUIRE_SERVER;
+
+    if (!key) {
+        nebSetErr(server, "parameter 'key' may not be NULL");
+
+        return NULL;
+    }
+
+    if (soap_call_ns1__create_USCOREobject(server->soap, server->endpoint, NULL,
+            (char *)key, (char *)volume, (char **)&response) != SOAP_OK) {
+        nebSetServerErr(server);
+
+        return NULL;
+    }
+
+    if (!(char *)response.result) {
+        nebSetErr(server, "server returned no result");
+        return NULL;
+    }
+
+    if (!nebParseURI(server, (char *)response.result, &filename)) {
+        nebSetErr(server, "can not parse URI");
+        return NULL;
+    }
+
+    // if URI is not NULL
+    if (URI) {
+        *URI = xmalloc(strlen((char *)response.result));
+        strcpy(*URI, (char *)response.result);
+    }
+
+    return filename;
+}
+
+int nebOpenCreate(nebServer *server, const char *key, const char *volume, char **URI)
+{
+    char            *filename;
+    int             file;
+
+    REQUIRE_SERVER;
+
+    if (!key) {
+        nebSetErr(server, "parameter 'key' may not be NULL");
+
+        return -1;
+    }
+
+    filename = nebCreate(server, key, volume, URI);
+
+    file = open(filename, O_RDWR|O_TRUNC, 0660);
+    if (file == -1) {
+        nebSetErr(server, "can not open %s: %s", filename, strerror(errno));
+        nebFree(filename);
+
+        return -1;
+    }
+
+    nebFree(filename);
+
+    return file;
+}
+
+bool nebReplicate(nebServer *server, const char *key, const char *volume, char **URI)
+{
+    struct ns1__replicate_USCOREobjectResponse response;
+    char            *filename;
+    int             sourceFH, destFH;
+
+    REQUIRE_SERVER;
+
+    if (!key) {
+        nebSetErr(server, "parameter 'key' may not be NULL");
+
+        return false;
+    }
+
+
+    // We have to open the instance that we're going to copy from first.  If
+    // we don't do this, it's possible that open will find & open the new
+    // instance that we're in the process of creating
+    sourceFH = nebOpen(server, (char *)key, NEB_READ);
+    if (sourceFH == -1) {
+        nebSetErr(server, "can not open key %s", key);
+        nebFree(filename);
+
+        return false;
+    }
+
+    // ask the server for a new instance attached to our key
+    if (soap_call_ns1__replicate_USCOREobject(server->soap, server->endpoint,
+            NULL, (char *)key, (char *)volume, (char **)&response) != SOAP_OK) {
+        nebSetServerErr(server);
+
+        return false;
+    }
+
+    if (!nebParseURI(server, (char *)response.result, &filename)) {
+        nebSetErr(server, "can not parse URI");
+
+        return false;
+    }
+
+    destFH = open(filename, O_RDWR|O_TRUNC, 0660);
+    if (destFH == -1) {
+        nebSetErr(server, "can not open %s: %s\n", filename, strerror(errno));
+        nebFree(filename);
+
+        return false;
+    }
+
+    nebCopyFilehandle(server, sourceFH, destFH);
+
+    if (close(sourceFH) == -1) {
+        nebSetErr(server, "can not close file: %s", strerror(errno));
+        nebFree(filename);
+
+        return false;
+    }
+
+    if (close(destFH) == -1) {
+        nebSetErr(server, "can not close %s: %s", filename, strerror(errno));
+        nebFree(filename);
+
+        return false;
+    }
+
+    nebFree(filename);
+
+    // if URI is not NULL
+    if (URI) {
+        *URI = xmalloc(strlen((char *)response.result));
+        strcpy(*URI, (char *)response.result);
+    }
+
+    return true;
+}
+
+bool nebCull(nebServer *server, const char *key)
+{
+    nebObjectInstances *locations;
+
+    REQUIRE_SERVER;
+
+    if (!key) {
+        nebSetErr(server, "parameter 'key' may not be NULL");
+
+        return false;
+    }
+
+    locations = nebFindInstances(server, key, NULL);
+    if (!locations) {
+        nebSetErr(server, "can not cull - not enough instances");
+
+        return false;
+    }
+
+    if (!nebDeleteInstance(server, locations->URI[0])) {
+        nebObjectInstancesFree(locations);
+
+        return false;
+    }
+
+    nebObjectInstancesFree(locations);
+
+    return true;
+}
+
+bool nebLock(nebServer *server, const char *key, nebRW flag)
+{
+    time_t          endtime;
+    char            *type;
+    int             response;
+
+    REQUIRE_SERVER;
+
+    if (!key) {
+        nebSetErr(server, "parameter 'key' may not be NULL");
+
+        return false;
+    }
+
+    type = flag == NEB_READ ? "read" : "write";
+
+    endtime = time(NULL) + LOCK_TIMEOUT;
+
+    while (time(NULL) < endtime) {
+        if (soap_call_ns1__lock_USCOREobject(server->soap, server->endpoint,
+            NULL, (char *)key, type, &response) != SOAP_OK) {
+            nebSetServerErr(server);
+            return false;
+        }
+
+        if (response) {
+            return true;
+        }
+
+        sleep(LOCK_INTERVAL);
+    }
+
+    // else, we never got a lock
+    nebSetErr(server, "can not get a %s lock", type);
+
+    return false;
+}
+
+bool nebUnlock(nebServer *server, const char *key, nebRW flag)
+{
+    char            *type;
+    int             response;
+
+    REQUIRE_SERVER;
+
+    if (!key) {
+        nebSetErr(server, "parameter 'key' may not be NULL");
+
+        return false;
+    }
+
+    type = flag == NEB_READ ? "read" : "write";
+
+    if (soap_call_ns1__unlock_USCOREobject(server->soap, server->endpoint,
+        NULL, (char *)key, type, &response) != SOAP_OK) {
+        nebSetServerErr(server);
+        return false;
+    }
+
+    if (response) {
+        return true;
+    }
+
+    // else, we never got a lock
+    nebSetErr(server, "can not release %s lock", type);
+
+    return false;
+}
+
+nebObjectInstances *nebFindInstances(nebServer *server, const char *key, const char *volume)
+{
+    struct ns1__find_USCOREinstancesResponse response;
+    int             resultElements = 0;
+    char            **resultArray;
+    nebObjectInstances *locations = NULL;
+
+    REQUIRE_SERVER;
+
+    if (!key) {
+        nebSetErr(server, "parameter 'key' may not be NULL");
+
+        return NULL;
+    }
+
+    // FIXME is this leaking memory when response goes out of scope?  the gsoap
+    // manual seems to 'suggest' that this is temporary data that gets cleaed
+    // up on the next soap function call
+    if (soap_call_ns1__find_USCOREinstances(server->soap, server->endpoint,
+            NULL, (char *)key, (char *)volume, &response) != SOAP_OK) {
+        nebSetServerErr(server);
+        return NULL;
+    }
+
+    resultElements = response.result->__size;
+
+    if (resultElements) {
+        locations = xmalloc(sizeof(nebObjectInstances));
+        locations->n = resultElements;
+        
+        resultArray    = response.result->__ptr;
+
+        locations->URI = xmalloc(sizeof(char*) * resultElements);
+
+        for (int i = 0; i < resultElements; i++) {
+            locations->URI[i] = xmalloc(strlen(resultArray[i]) + 1);
+            strcpy(locations->URI[i], resultArray[i]);
+        }
+
+    }
+
+    return locations;
+}
+
+void nebObjectInstancesFree(nebObjectInstances *locations)
+{
+    if (!locations) {
+        return;
+    }
+
+    for (int i = 0; i < locations->n; i++) {
+        nebFree(locations->URI[i]);
+    }
+
+    nebFree(locations);
+}
+
+char *nebFind(nebServer *server, const char *key)
+{
+    nebObjectInstances *locations;
+    char            *filename;
+
+    REQUIRE_SERVER;
+
+    if (!key) {
+        nebSetErr(server, "parameter 'key' may not be NULL");
+
+        return NULL;
+    }
+    
+    locations = nebFindInstances(server, key, NULL);
+    if (!locations) {
+        nebSetErr(server, "no instances found");
+
+        return NULL;
+    }
+
+    if (!nebParseURI(server, locations->URI[0], &filename)) {
+        nebSetErr(server, "can not parse URI");
+        nebObjectInstancesFree(locations);
+
+        return NULL;
+    }
+
+    nebObjectInstancesFree(locations);
+
+    return filename;
+}
+
+int nebOpen(nebServer *server, const char *key, nebRW flag)
+{
+    nebObjectInstances *locations;
+    char            *filename;
+    int             fh;
+
+    REQUIRE_SERVER;
+
+    if (!key) {
+        nebSetErr(server, "parameter 'key' may not be NULL");
+
+        return -1;
+    }
+
+    locations = nebFindInstances(server, key, NULL);
+    if (!locations) {
+        nebSetErr(server, "no instances found");
+
+        return -1;
+    }
+
+    if (!nebParseURI(server, locations->URI[0], &filename)) {
+        nebSetErr(server, "can not parse URI");
+        nebObjectInstancesFree(locations);
+
+        return -1;
+    }
+
+    if (flag == NEB_WRITE) {
+        if (locations->n > 1) {
+            nebSetErr(server, "write not allowed with multiple instances");
+            nebFree(filename);
+            nebObjectInstancesFree(locations);
+
+            return -1;
+        }
+        fh = open(filename, O_RDWR);
+    } else {
+        fh = open(filename, O_RDONLY);
+    }
+
+    nebFree(filename);
+    nebObjectInstancesFree(locations);
+
+    if (fh < 0) {
+        nebSetErr(server, "open: %s", strerror(errno));
+
+        return -1;
+    }
+
+    return fh;
+}
+
+bool nebDelete(nebServer *server, const char *key)
+{
+    nebObjectInstances *locations;
+
+    REQUIRE_SERVER;
+
+    if (!key) {
+        nebSetErr(server, "parameter 'key' may not be NULL");
+
+        return false;
+    }
+
+    locations = nebFindInstances(server, key, NULL);
+    if (!locations) {
+        nebSetErr(server, "no instances found");
+
+        return false;
+    }
+
+    for (int i = 0; i < locations->n; i++) {
+        if (!nebDeleteInstance(server, locations->URI[i])) {
+            nebSetErr(server, "can not delete instance");
+            nebObjectInstancesFree(locations);
+
+            return false;
+        }
+    }
+
+    nebObjectInstancesFree(locations);
+
+    return true;
+}
+
+bool nebCopy(nebServer *server, const char *key, const char *newKey)
+{
+    int             sourceFH;
+    int             destFH;
+
+    REQUIRE_SERVER;
+
+    if (!key) {
+        nebSetErr(server, "parameter 'key' may not be NULL");
+
+        return false;
+    }
+
+    if (!newKey) {
+        nebSetErr(server, "parameter 'newKey' may not be NULL");
+
+        return false;
+    }
+
+    sourceFH = nebOpen(server, (char *)key, NEB_READ);
+    if (sourceFH < 0) {
+        // propigate nebOpen() error
+
+        return false;
+    }
+
+    destFH = nebOpenCreate(server, newKey, NULL, NULL);
+    if (destFH < 0) {
+        // propigate nebCreate() error
+
+        return false;
+    }
+
+    nebCopyFilehandle(server, sourceFH, destFH);
+
+    if (close(sourceFH) == -1) {
+        nebSetErr(server, "can not close file: %s", strerror(errno));
+
+        return false;
+    }
+
+    if (close(destFH) == -1) {
+        nebSetErr(server, "can not close file: %s", strerror(errno));
+
+        return false;
+    }
+
+    return true;
+}
+
+bool nebMove(nebServer *server, const char *key, const char *newKey)
+{
+    REQUIRE_SERVER;
+
+    if (!key) {
+        nebSetErr(server, "parameter 'key' may not be NULL");
+
+        return false;
+    }
+
+    if (!newKey) {
+        nebSetErr(server, "parameter 'newKey' may not be NULL");
+
+        return false;
+    }
+
+    if (!nebCopy(server, key, newKey)) {
+        return false;
+    }
+
+    if (!nebDelete(server, key)) {
+        return false;
+    }
+
+    return true;
+}
+
+bool nebDeleteInstance(nebServer *server, const char *URI)
+{
+    int             response;
+    char            *filename;
+    bool            status;
+
+    REQUIRE_SERVER;
+
+    if (!URI) {
+        nebSetErr(server, "parameter 'URI' may not be NULL");
+
+        return false;
+    }
+
+    if (!nebParseURI(server, URI, &filename)) {
+        nebSetErr(server, "can not parse URI");
+
+        return false;
+    }
+
+    if (soap_call_ns1__delete_USCOREinstance(server->soap, server->endpoint,
+            NULL, (char *)URI, &response) != SOAP_OK) {
+        nebFree(filename);
+
+        return false;
+    }
+
+    if (response > 0) {
+        status = nebNukeFile(server, filename);
+    } else {
+        status = false;
+    }
+
+    nebFree(filename);
+
+    return status;
+}
+
+nebObjectStat *nebStat(nebServer *server, const char *key)
+{
+    struct ns1__stat_USCOREobjectResponse response;
+    nebObjectStat   *stat;
+    int             resultElements = 0;
+    char            **resultArray = NULL;
+
+    REQUIRE_SERVER;
+
+    if (!key) {
+        nebSetErr(server, "parameter 'key' may not be NULL");
+
+        return NULL;
+    }
+
+    stat = xmalloc(sizeof(nebObjectStat));
+
+    // FIXME is this leaking memory when response goes out of scope?  the gsoap
+    // manual seems to 'suggest' that this is temporary data that gets cleaed
+    // up on the next soap function call
+    if (soap_call_ns1__stat_USCOREobject(server->soap, server->endpoint,
+            NULL, (char *)key, &response) != SOAP_OK) {
+        nebSetServerErr(server);
+        return NULL;
+    }
+
+    resultElements = response.result->__size;
+    resultArray    = response.result->__ptr;
+
+    if (resultElements != 7) {
+        nebSetErr(server, "server didn't return the proper number of stat elements");
+        return NULL;
+    }
+
+    nullstrncpy(stat->so_id, resultArray[0], 256);
+    nullstrncpy(stat->ext_id, resultArray[1], 256);
+    nullstrncpy(stat->read_lock, resultArray[2], 256);
+    nullstrncpy(stat->write_lock, resultArray[3], 256);
+    nullstrncpy(stat->epoch, resultArray[4], 256);
+    nullstrncpy(stat->mtime, resultArray[5], 256);
+    stat->instances = atoi(resultArray[6]);
+
+    return stat;
+}
+
+char *nebErr(nebServer *server)
+{
+    return server->err_buf;
+}
+
+void nebFree(void *ptr) {
+    xfree(ptr);
+}
+
+
+static void p_nebSetErr(const char * filename, unsigned long lineno, const char *function, nebServer *server, const char *format, ...)
+{
+    va_list         args;
+    size_t          err_size;
+    char            err_location[ERRBUF_SIZE];
+    size_t          err_location_size; 
+
+    err_location_size = snprintf(err_location, ERRBUF_SIZE, "%s:%lu %s() - ",
+            filename, lineno, function);
+
+    if (err_location_size < 0) {
+        fprintf(stderr, "failed to set error info");
+
+        abort();
+    }
+
+    // copy error location info to start of error string
+    strncpy(server->err_buf, err_location, ERRBUF_SIZE);
+
+    while (1) {
+        va_start(args, format);
+        // append error string after error location info
+        err_size = vsnprintf(
+                server->err_buf + err_location_size,
+                server->err_buf_size - err_location_size,
+                format, args);
+        va_end(args);
+
+        if (err_size < 0) {
+            fprintf(stderr, "failed to set error message");
+
+            abort();
+        }
+
+        if (err_size < server->err_buf_size) {
+            break;
+        }
+
+        // else: expand err_buf
+        // account for '\0'
+        server->err_buf_size = err_size + 1;
+        xrealloc(server->err_buf, server->err_buf_size);
+    }
+
+}
+
+static void nebSetServerErr(nebServer *server)
+{
+    const char      **code;
+    const char      **string;
+
+    REQUIRE_SERVER;
+
+    code   = soap_faultcode(server->soap);
+    string = soap_faultstring(server->soap);
+
+    nebSetErr(server, "%s - %s", *code, *string);
+}
+
+#if NEBCOPYFILE
+static off_t nebCopyFile(nebServer *server, const char *source, const char *dest)
+{
+    int             sourceFH;
+    int             destFH; 
+    off_t           bytesCopied;
+
+    REQUIRE_SERVER;
+
+    sourceFH = open(source, O_RDONLY);
+    if (sourceFH == -1) {
+        nebSetErr(server, "can not open %s: %s", source, strerror(errno));
+
+        return -1;
+    }
+
+    destFH = open(dest, O_WRONLY|O_CREAT|O_CREAT, 0600);
+    if (destFH == -1) {
+        nebSetErr(server, "can not open %s: %s", dest, strerror(errno));
+
+        return -1;
+    }
+
+    bytesCopied = nebCopyFilehandle(server, sourceFH, destFH);
+    if (bytesCopied < 0) {
+        return -1;
+    }
+
+    if (close(sourceFH) == -1) {
+        nebSetErr(server, "can not close %s: %s", source, strerror(errno));
+
+        return -1;
+    }
+
+    if (close(destFH) == -1) {
+        nebSetErr(server, "can not close %s: %s", dest, strerror(errno));
+
+        return -1;
+    }
+
+    return bytesCopied;
+}
+#endif
+
+static off_t nebCopyFilehandle(nebServer *server, int sourceFH, int destFH)
+{
+    off_t           bytesTotal;
+    off_t           bytesRemaining;
+    off_t           writeSize;
+    char            writeBuf[64 * 1024];
+    struct stat     sourceStat;
+
+    REQUIRE_SERVER;
+
+    if(fstat(sourceFH, &sourceStat)) {
+        nebSetErr(server, "can not stat filehandles: %s", strerror(errno));
+
+        return -1;
+    }
+
+    // the size of the file to copied
+    bytesTotal = sourceStat.st_size;
+
+    /*
+     * If the file size is <= the buffer size call write(2) with the
+     * file size.  If the file size is > the buffer call write with the
+     * buffer size and loop until file size <= buffer size is true.
+    */
+
+    bytesRemaining = bytesTotal;
+
+    while (bytesRemaining) {
+        if (bytesRemaining <= sizeof(writeBuf)) {
+            writeSize = bytesRemaining;
+        } else {
+            writeSize = sizeof(writeBuf);
+        }
+
+        if (read(sourceFH, writeBuf, writeSize) != writeSize) {
+            nebSetErr(server, "can not read filehandle: %s", strerror(errno));
+
+            return -1;
+        }
+
+        if (write(destFH, writeBuf, writeSize) != writeSize) {
+            nebSetErr(server, "can not write filehandles: %s", strerror(errno));
+
+            return -1;
+        }
+
+        bytesRemaining -= writeSize;
+    }
+
+    return bytesTotal;
+}
+
+static size_t nebParseURI(nebServer *server, const char *URI, char **filename)
+{
+    regex_t         myregex;
+    regmatch_t      mymatch[2];
+    char            errbuf[ERRBUF_SIZE];
+    char            *pattern = "^file://(.*)$";
+    int             status;
+    size_t          matchStart, matchEnd;
+    size_t          matchLength;
+    size_t          filename_size;
+
+    REQUIRE_SERVER;
+
+    if (!URI) {
+        nebSetErr(server, "parameter 'URI' may not be NULL");
+
+        return 0;
+    }
+
+    if (!filename) {
+        nebSetErr(server, "parameter 'filename' may not be NULL");
+
+        return 0;
+    }
+
+    status = regcomp(&myregex, pattern, REG_EXTENDED);
+    if (status != 0) {
+        regerror(status, &myregex, errbuf, ERRBUF_SIZE);
+        nebSetErr(server, "regcomp error: %s", errbuf);
+
+        return 0;
+    }
+
+    status = regexec(&myregex, URI, 2, mymatch, 0);
+    if (status != 0) {
+        regerror(status, &myregex, errbuf, ERRBUF_SIZE);
+        nebSetErr(server, "regexec error: %s", errbuf);
+
+        return 0;
+    }
+
+    regfree(&myregex);
+
+    matchStart = (size_t)mymatch[1].rm_so;
+    matchEnd   = (size_t)mymatch[1].rm_eo;
+    matchLength = matchEnd - matchStart;
+
+    if (matchStart == -1) {
+        return 0;
+    }
+
+    filename_size = matchLength + 1;
+    *filename = xmalloc(filename_size);
+
+    snprintf(*filename, filename_size, "%.*s", (int)matchLength, URI + matchStart);
+
+    return strlen(*filename);
+}
+
+static bool nebNukeFile(nebServer *server, const char *filename)
+{
+    REQUIRE_SERVER;
+
+    if (!filename) {
+        nebSetErr(server, "parameter 'filename' may not be NULL");
+
+        return false;
+    }
+
+    if (unlink(filename) < 0) {
+        nebSetErr(server, "unlink: %s", strerror(errno));
+
+        return false;
+    }
+
+    return true;
+}
+
+static char *nullstrncpy(char *dest, const char *src, size_t n) {
+    if (!src) {
+        dest = NULL;
+        return dest;
+    }
+
+    return strncpy(dest, src, n);
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/nebclient.h
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/nebclient.h	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/nebclient.h	(revision 21994)
@@ -0,0 +1,263 @@
+/*
+ * nebclient.h -  nebulous client header
+ * 
+ * Copyright (C) 2005  Joshua Hoblitt
+ *
+ * $Id: nebclient.h,v 1.32 2007-05-03 21:26:55 jhoblitt Exp $
+ */
+
+#include <stdbool.h>
+
+#ifndef NEBCLIENT_H
+#define NEBCLIENT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// @addtogroup nebclient
+/// @{
+
+typedef enum { NEB_READ, NEB_WRITE } nebRW;
+
+/** Represents a "connection" to a Nebulous server
+ */
+
+typedef struct {
+    void            *soap;
+    char            *err_buf;
+    size_t          err_buf_size;
+    char            *endpoint;
+} nebServer;
+
+/** The properties of a storage object
+ */
+
+typedef struct {
+    char            so_id[256];         ///< storage object ID
+    char            ext_id[256];        ///< storage object key (name)
+    char            read_lock[256];     ///< read lock value
+    char            write_lock[256];    ///< write lock value
+    char            epoch[256];         ///< creation time stamp
+    char            mtime[256];         ///< modification time stamp
+    int             instances;          ///< number of instances
+} nebObjectStat;
+
+/** The storage location of a storage object's instances
+ */
+
+typedef struct {
+    unsigned int    n;                  ///< number of instances
+    char            **URI;              ///< URLs of instances 
+} nebObjectInstances;
+
+/** Allocates a nebServer object
+ *
+ * Structure used for communicating with a Nebulous server.  If endpoint is
+ * NULL then the default value of "http://localhost:80/nebulous" is used.
+ *
+ * @return A nebServer object or NULL on failure.
+ */
+
+nebServer *nebServerAlloc(
+    const char *endpoint                ///< URL of server
+);
+
+/** Deallocates a nebServer object
+ */
+
+void nebServerFree(
+    nebServer *server                   ///< nebServer object
+);
+
+/** Creates a new storage object
+ *
+ * @return A local filename
+ */
+
+char *nebCreate(
+    nebServer *server,                  ///< nebServer object
+    const char *key,                    ///< storage object key (name)
+    const char *volume,                 ///< preferred storage location of initial instance
+    char **URI                          ///< URL of initial instance, can be NULL
+);
+
+/** Creates and opens new storage object
+ *
+ * @return A filehandle on success or a negative value on failure.
+ */
+
+int nebOpenCreate(
+    nebServer *server,                  ///< nebServer object
+    const char *key,                    ///< storage object key (name)
+    const char *volume,                 ///< preferred storage location of initial instance
+    char **URI                          ///< URL of initial instance, can be NULL
+);
+
+/** Adds an instance to a storage object
+ *
+ * @return true on success
+ */
+
+bool nebReplicate(
+    nebServer *server,                  ///< nebServer object
+    const char *key,                    ///< storage object key (name)
+    const char *volume,                 ///< preferred storage location of new instance
+    char **URI                          ///< URL of new instance, can be NULL
+);
+
+/** Removes an instance from a storage object
+ *
+ * This function can not remove the last instance of a storage object.
+ *
+ * @return true on success
+ */
+
+bool nebCull(
+    nebServer *server,                  ///< nebServer object
+    const char *key                     ///< storage object key (name)
+);
+
+/** Trys to acquire a lock on a storage object
+ *
+ * This function times out after a default interval of 10s (compile time
+ * configurable).
+ *
+ * @return true on success
+ */
+bool nebLock(
+    nebServer *server,                  ///< nebServer object
+    const char *key,                    ///< storage object key (name)
+    nebRW flag                          ///< read only or write lock
+);
+
+/** Trys to release a lock on a storage object
+ *
+ * @return true on success
+ */
+bool nebUnlock(
+    nebServer *server,                  ///< nebServer object
+    const char *key,                    ///< storage object key (name)
+    nebRW flag                          ///< read only or write lock
+);
+
+/** Lists all instances of a storage object
+ *
+ * @return A nebObjectInstances object or NULL on failure.
+ */
+
+nebObjectInstances *nebFindInstances(
+    nebServer *server,                  ///< nebServer object
+    const char *key,                    ///< storage object key (name)
+    const char *volume                  ///< restrict search to this storage volume (non-working)
+);
+
+/** Deallocates a nebObjectInstances object
+ */
+
+void nebObjectInstancesFree(
+    nebObjectInstances *locations       ///< nebObjectInstances object to free 
+);
+
+/** Find any instance of a storage object
+ *
+ * @return A string of the files storage path (not a URL) or NULL on failure.
+ */
+
+char *nebFind(
+    nebServer *server,                  ///< nebServer object
+    const char *key                     ///< storage object key (name)
+);
+
+/** Open a storage object for read or write
+ *
+ * @return A filehandle on success or a negative value on failure.
+ */
+
+int nebOpen(
+    nebServer *server,                  ///< nebServer object
+    const char *key,                    ///< storage object key (name)
+    nebRW flag                          ///< read only or write lock
+);
+
+/** Delete a storage object and all of it's instances
+ *
+ * @return true on success
+ */
+
+bool nebDelete(
+    nebServer *server,                  ///< nebServer object
+    const char *key                     ///< storage object key (name)
+);
+
+/** Copy a storage object
+ *
+ * The new storage object will be created with only one instance.
+ *
+ * @return true on success
+ */
+
+bool nebCopy(
+    nebServer *server,                  ///< nebServer object
+    const char *key,                    ///< storage object key (name)
+    const char *newKey                  ///< new storage object key (name)
+);
+
+/** Rename a storage object
+ *
+ * Currently this operation will remove all but one instance of the storage
+ * object and may change it's storage location.
+ */
+bool nebMove(
+    nebServer *server,                  ///< nebServer object
+    const char *key,                    ///< storage object key (name)
+    const char *newKey                  ///< new storage object key (name)
+);
+
+/** Remove a storage object instance
+ *
+ * Removing the last instance of a storage object with destroy the storage
+ * object as well.
+ *
+ * @return true on success
+ */
+
+bool nebDeleteInstance(
+    nebServer *server,                  ///< nebServer object
+    const char *URI                     ///< URL of instance to remove
+);
+
+/** View the properties of a storage object
+ *
+ * @return A nebObjectStat object or NULL on failure.
+ */
+
+nebObjectStat *nebStat(
+    nebServer *server,                  ///< nebServer object
+    const char *key                     /// storage object key (name)
+);
+
+/** Returns the error message from the last nebclient function that failed.
+ *
+ * This function may not be called unless an error has occurred.  The string
+ * return by this function does not need to be freed but the value will change
+ * at the next nebclient function failure.
+ *
+ * @return A string
+ */
+
+char *nebErr(
+    nebServer *server                   ///< nebServer object
+);
+
+/** Free nebclient allocated memory
+ */
+void nebFree(void *ptr);
+
+/// @}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NEBLIENT_H
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/nebulous.h
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/nebulous.h	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/nebulous.h	(revision 21994)
@@ -0,0 +1,531 @@
+/* src/nebulous.h
+   Generated by wsdl2h 1.2.1 from nebulous.wsdl and typemap.dat
+   2007-05-01 02:53:36 GMT
+   Copyright (C) 2001-2005 Robert van Engelen, Genivia Inc. All Rights Reserved.
+   This part of the software is released under one of the following licenses:
+   GPL or Genivia's license for commercial use.
+*/
+
+/* NOTE:
+
+ - Compile this file with soapcpp2 to complete the code generation process.
+ - Use wsdl2h option -l to view the software license terms.
+ - Use wsdl2h options -c and -s to generate pure C code or C++ code without STL.
+ - To build with STL, stlvector.h from the gSOAP distribution must be in the
+   current directory. Or use soapcpp2 option -I<path> with path to stlvector.h.
+ - Use typemap.dat to control schema namespace bindings and type mappings.
+   It is strongly recommended to customize the names of the namespace prefixes
+   generated by wsdl2h. To do so, modify the prefix bindings in the Namespaces
+   section below and add the modified lines to typemap.dat to rerun wsdl2h.
+ - Use Doxygen (www.doxygen.org) to browse this file.
+
+*/
+
+/******************************************************************************\
+ *                                                                            *
+ * urn:Nebulous/Server/SOAP                                                   *
+ *                                                                            *
+\******************************************************************************/
+
+//gsoapopt cw
+
+
+/******************************************************************************\
+ *                                                                            *
+ * Schema Namespaces                                                          *
+ *                                                                            *
+\******************************************************************************/
+
+
+/* NOTE:
+
+It is strongly recommended to customize the names of the namespace prefixes
+generated by wsdl2h. To do so, modify the prefix bindings below and add the
+modified lines to typemap.dat to rerun wsdl2h:
+
+ns1 = "urn:Nebulous/Server/SOAP"
+
+*/
+
+//gsoap ns1   schema namespace:	urn:Nebulous/Server/SOAP
+//gsoap ns1   schema form:	unqualified
+
+/******************************************************************************\
+ *                                                                            *
+ * Schema Types                                                               *
+ *                                                                            *
+\******************************************************************************/
+
+
+/// Built-in attribute "SOAP-ENC:arrayType"
+typedef char* SOAP_ENC__arrayType;
+
+
+/// Schema urn:Nebulous/Server/SOAP:"ArrayOfString"
+
+/// SOAP encoded array of xs:string
+struct ArrayOfString
+{
+/// Pointer to an array of char*
+    char*                               *__ptr                         ;
+/// Size of the dynamic array
+    int                                  __size                        ;
+};
+
+/******************************************************************************\
+ *                                                                            *
+ * Services                                                                   *
+ *                                                                            *
+\******************************************************************************/
+
+//gsoap ns1  service name:	SOAP 
+//gsoap ns1  service type:	Nebulous_x002fServer_x002fSOAPPort 
+//gsoap ns1  service port:	http://localhost:80/nebulous 
+//gsoap ns1  service namespace:	urn:Nebulous/Server/SOAP 
+//gsoap ns1  service transport:	http://schemas.xmlsoap.org/soap/http 
+
+/** @mainpage NebulousServer Definitions
+
+@section NebulousServer_bindings Bindings
+  - @ref SOAP
+
+*/
+
+/**
+
+@page SOAP Binding "SOAP"
+
+@section SOAP_operations Operations of Binding  "SOAP"
+  - @ref ns1__create_USCOREobject
+  - @ref ns1__rename_USCOREobject
+  - @ref ns1__rename_USCOREobject_
+  - @ref ns1__replicate_USCOREobject
+  - @ref ns1__lock_USCOREobject
+  - @ref ns1__unlock_USCOREobject
+  - @ref ns1__find_USCOREobjects
+  - @ref ns1__find_USCOREinstances
+  - @ref ns1__delete_USCOREinstance
+  - @ref ns1__stat_USCOREobject
+
+@section SOAP_ports Endpoints of Binding  "SOAP"
+  - http://localhost:80/nebulous
+
+*/
+
+/******************************************************************************\
+ *                                                                            *
+ * SOAP                                                                       *
+ *                                                                            *
+\******************************************************************************/
+
+
+/******************************************************************************\
+ *                                                                            *
+ * ns1__create_USCOREobject                                                   *
+ *                                                                            *
+\******************************************************************************/
+
+
+/// Operation "ns1__create_USCOREobject" of service binding "SOAP"
+
+/**
+
+Operation details:
+
+  - SOAP RPC encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  - SOAP action="urn:Nebulous/Server/SOAP#create_object"
+
+C stub function (defined in soapClient.c[pp]):
+@code
+  int soap_call_ns1__create_USCOREobject(struct soap *soap,
+    NULL, // char *endpoint = NULL selects default endpoint for this operation
+    NULL, // char *action = NULL selects default action for this operation
+    // request parameters:
+    char*                               key,
+    char*                               volume,
+    // response parameters:
+    char*                              *result
+  );
+@endcode
+
+*/
+
+//gsoap ns1  service method-style:	create_USCOREobject rpc
+//gsoap ns1  service method-encoding:	create_USCOREobject http://schemas.xmlsoap.org/soap/encoding/
+//gsoap ns1  service method-action:	create_USCOREobject urn:Nebulous/Server/SOAP#create_object
+int ns1__create_USCOREobject(
+    char*                               key,
+    char*                               volume,
+    char*                              *result ///< response parameter
+);
+
+/******************************************************************************\
+ *                                                                            *
+ * ns1__rename_USCOREobject                                                   *
+ *                                                                            *
+\******************************************************************************/
+
+
+/// Operation "ns1__rename_USCOREobject" of service binding "SOAP"
+
+/**
+
+Operation details:
+
+  - SOAP RPC encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  - SOAP action="urn:Nebulous/Server/SOAP#create_object"
+
+C stub function (defined in soapClient.c[pp]):
+@code
+  int soap_call_ns1__rename_USCOREobject(struct soap *soap,
+    NULL, // char *endpoint = NULL selects default endpoint for this operation
+    NULL, // char *action = NULL selects default action for this operation
+    // request parameters:
+    char*                               key,
+    char*                               newkey,
+    // response parameters:
+    char*                              *result
+  );
+@endcode
+
+*/
+
+//gsoap ns1  service method-style:	rename_USCOREobject rpc
+//gsoap ns1  service method-encoding:	rename_USCOREobject http://schemas.xmlsoap.org/soap/encoding/
+//gsoap ns1  service method-action:	rename_USCOREobject urn:Nebulous/Server/SOAP#create_object
+int ns1__rename_USCOREobject(
+    char*                               key,
+    char*                               newkey,
+    char*                              *result ///< response parameter
+);
+
+/******************************************************************************\
+ *                                                                            *
+ * ns1__rename_USCOREobject_                                                  *
+ *                                                                            *
+\******************************************************************************/
+
+
+/// Operation "ns1__rename_USCOREobject_" of service binding "SOAP"
+
+/**
+
+Operation details:
+
+  - SOAP RPC encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  - SOAP action="urn:Nebulous/Server/SOAP#rename_object"
+
+C stub function (defined in soapClient.c[pp]):
+@code
+  int soap_call_ns1__rename_USCOREobject_(struct soap *soap,
+    NULL, // char *endpoint = NULL selects default endpoint for this operation
+    NULL, // char *action = NULL selects default action for this operation
+    // request parameters:
+    char*                               key,
+    char*                               newkey,
+    // response parameters:
+    char*                              *result
+  );
+@endcode
+
+*/
+
+//gsoap ns1  service method-style:	rename_USCOREobject_ rpc
+//gsoap ns1  service method-encoding:	rename_USCOREobject_ http://schemas.xmlsoap.org/soap/encoding/
+//gsoap ns1  service method-action:	rename_USCOREobject_ urn:Nebulous/Server/SOAP#rename_object
+int ns1__rename_USCOREobject_(
+    char*                               key,
+    char*                               newkey,
+    char*                              *result ///< response parameter
+);
+
+/******************************************************************************\
+ *                                                                            *
+ * ns1__replicate_USCOREobject                                                *
+ *                                                                            *
+\******************************************************************************/
+
+
+/// Operation "ns1__replicate_USCOREobject" of service binding "SOAP"
+
+/**
+
+Operation details:
+
+  - SOAP RPC encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  - SOAP action="urn:Nebulous/Server/SOAP#replicate_object"
+
+C stub function (defined in soapClient.c[pp]):
+@code
+  int soap_call_ns1__replicate_USCOREobject(struct soap *soap,
+    NULL, // char *endpoint = NULL selects default endpoint for this operation
+    NULL, // char *action = NULL selects default action for this operation
+    // request parameters:
+    char*                               key,
+    char*                               volume,
+    // response parameters:
+    char*                              *result
+  );
+@endcode
+
+*/
+
+//gsoap ns1  service method-style:	replicate_USCOREobject rpc
+//gsoap ns1  service method-encoding:	replicate_USCOREobject http://schemas.xmlsoap.org/soap/encoding/
+//gsoap ns1  service method-action:	replicate_USCOREobject urn:Nebulous/Server/SOAP#replicate_object
+int ns1__replicate_USCOREobject(
+    char*                               key,
+    char*                               volume,
+    char*                              *result ///< response parameter
+);
+
+/******************************************************************************\
+ *                                                                            *
+ * ns1__lock_USCOREobject                                                     *
+ *                                                                            *
+\******************************************************************************/
+
+
+/// Operation "ns1__lock_USCOREobject" of service binding "SOAP"
+
+/**
+
+Operation details:
+
+  - SOAP RPC encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  - SOAP action="urn:Nebulous/Server/SOAP#lock_object"
+
+C stub function (defined in soapClient.c[pp]):
+@code
+  int soap_call_ns1__lock_USCOREobject(struct soap *soap,
+    NULL, // char *endpoint = NULL selects default endpoint for this operation
+    NULL, // char *action = NULL selects default action for this operation
+    // request parameters:
+    char*                               key,
+    char*                               type,
+    // response parameters:
+    int                                *result
+  );
+@endcode
+
+*/
+
+//gsoap ns1  service method-style:	lock_USCOREobject rpc
+//gsoap ns1  service method-encoding:	lock_USCOREobject http://schemas.xmlsoap.org/soap/encoding/
+//gsoap ns1  service method-action:	lock_USCOREobject urn:Nebulous/Server/SOAP#lock_object
+int ns1__lock_USCOREobject(
+    char*                               key,
+    char*                               type,
+    int                                *result ///< response parameter
+);
+
+/******************************************************************************\
+ *                                                                            *
+ * ns1__unlock_USCOREobject                                                   *
+ *                                                                            *
+\******************************************************************************/
+
+
+/// Operation "ns1__unlock_USCOREobject" of service binding "SOAP"
+
+/**
+
+Operation details:
+
+  - SOAP RPC encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  - SOAP action="urn:Nebulous/Server/SOAP#unlock_object"
+
+C stub function (defined in soapClient.c[pp]):
+@code
+  int soap_call_ns1__unlock_USCOREobject(struct soap *soap,
+    NULL, // char *endpoint = NULL selects default endpoint for this operation
+    NULL, // char *action = NULL selects default action for this operation
+    // request parameters:
+    char*                               key,
+    char*                               type,
+    // response parameters:
+    int                                *result
+  );
+@endcode
+
+*/
+
+//gsoap ns1  service method-style:	unlock_USCOREobject rpc
+//gsoap ns1  service method-encoding:	unlock_USCOREobject http://schemas.xmlsoap.org/soap/encoding/
+//gsoap ns1  service method-action:	unlock_USCOREobject urn:Nebulous/Server/SOAP#unlock_object
+int ns1__unlock_USCOREobject(
+    char*                               key,
+    char*                               type,
+    int                                *result ///< response parameter
+);
+
+/******************************************************************************\
+ *                                                                            *
+ * ns1__find_USCOREobjects                                                    *
+ *                                                                            *
+\******************************************************************************/
+
+/// Operation response struct "ns1__find_USCOREobjectsResponse" of service binding "SOAP" operation "ns1__find_USCOREobjects"
+struct ns1__find_USCOREobjectsResponse
+{
+    struct ArrayOfString*               result;
+};
+
+/// Operation "ns1__find_USCOREobjects" of service binding "SOAP"
+
+/**
+
+Operation details:
+
+  - SOAP RPC encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  - SOAP action="urn:Nebulous/Server/SOAP#find_objects"
+
+C stub function (defined in soapClient.c[pp]):
+@code
+  int soap_call_ns1__find_USCOREobjects(struct soap *soap,
+    NULL, // char *endpoint = NULL selects default endpoint for this operation
+    NULL, // char *action = NULL selects default action for this operation
+    // request parameters:
+    char*                               pattern,
+    // response parameters:
+    struct ns1__find_USCOREobjectsResponse*
+  );
+@endcode
+
+*/
+
+//gsoap ns1  service method-style:	find_USCOREobjects rpc
+//gsoap ns1  service method-encoding:	find_USCOREobjects http://schemas.xmlsoap.org/soap/encoding/
+//gsoap ns1  service method-action:	find_USCOREobjects urn:Nebulous/Server/SOAP#find_objects
+int ns1__find_USCOREobjects(
+    char*                               pattern,
+    struct ns1__find_USCOREobjectsResponse* ///< response parameter
+);
+
+/******************************************************************************\
+ *                                                                            *
+ * ns1__find_USCOREinstances                                                  *
+ *                                                                            *
+\******************************************************************************/
+
+/// Operation response struct "ns1__find_USCOREinstancesResponse" of service binding "SOAP" operation "ns1__find_USCOREinstances"
+struct ns1__find_USCOREinstancesResponse
+{
+    struct ArrayOfString*               result;
+};
+
+/// Operation "ns1__find_USCOREinstances" of service binding "SOAP"
+
+/**
+
+Operation details:
+
+  - SOAP RPC encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  - SOAP action="urn:Nebulous/Server/SOAP#find_instances"
+
+C stub function (defined in soapClient.c[pp]):
+@code
+  int soap_call_ns1__find_USCOREinstances(struct soap *soap,
+    NULL, // char *endpoint = NULL selects default endpoint for this operation
+    NULL, // char *action = NULL selects default action for this operation
+    // request parameters:
+    char*                               key,
+    char*                               volume,
+    // response parameters:
+    struct ns1__find_USCOREinstancesResponse*
+  );
+@endcode
+
+*/
+
+//gsoap ns1  service method-style:	find_USCOREinstances rpc
+//gsoap ns1  service method-encoding:	find_USCOREinstances http://schemas.xmlsoap.org/soap/encoding/
+//gsoap ns1  service method-action:	find_USCOREinstances urn:Nebulous/Server/SOAP#find_instances
+int ns1__find_USCOREinstances(
+    char*                               key,
+    char*                               volume,
+    struct ns1__find_USCOREinstancesResponse* ///< response parameter
+);
+
+/******************************************************************************\
+ *                                                                            *
+ * ns1__delete_USCOREinstance                                                 *
+ *                                                                            *
+\******************************************************************************/
+
+
+/// Operation "ns1__delete_USCOREinstance" of service binding "SOAP"
+
+/**
+
+Operation details:
+
+  - SOAP RPC encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  - SOAP action="urn:Nebulous/Server/SOAP#delete_instance"
+
+C stub function (defined in soapClient.c[pp]):
+@code
+  int soap_call_ns1__delete_USCOREinstance(struct soap *soap,
+    NULL, // char *endpoint = NULL selects default endpoint for this operation
+    NULL, // char *action = NULL selects default action for this operation
+    // request parameters:
+    char*                               uri,
+    // response parameters:
+    int                                *result
+  );
+@endcode
+
+*/
+
+//gsoap ns1  service method-style:	delete_USCOREinstance rpc
+//gsoap ns1  service method-encoding:	delete_USCOREinstance http://schemas.xmlsoap.org/soap/encoding/
+//gsoap ns1  service method-action:	delete_USCOREinstance urn:Nebulous/Server/SOAP#delete_instance
+int ns1__delete_USCOREinstance(
+    char*                               uri,
+    int                                *result ///< response parameter
+);
+
+/******************************************************************************\
+ *                                                                            *
+ * ns1__stat_USCOREobject                                                     *
+ *                                                                            *
+\******************************************************************************/
+
+/// Operation response struct "ns1__stat_USCOREobjectResponse" of service binding "SOAP" operation "ns1__stat_USCOREobject"
+struct ns1__stat_USCOREobjectResponse
+{
+    struct ArrayOfString*               result;
+};
+
+/// Operation "ns1__stat_USCOREobject" of service binding "SOAP"
+
+/**
+
+Operation details:
+
+  - SOAP RPC encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  - SOAP action="urn:Nebulous/Server/SOAP#stat_object"
+
+C stub function (defined in soapClient.c[pp]):
+@code
+  int soap_call_ns1__stat_USCOREobject(struct soap *soap,
+    NULL, // char *endpoint = NULL selects default endpoint for this operation
+    NULL, // char *action = NULL selects default action for this operation
+    // request parameters:
+    char*                               key,
+    // response parameters:
+    struct ns1__stat_USCOREobjectResponse*
+  );
+@endcode
+
+*/
+
+//gsoap ns1  service method-style:	stat_USCOREobject rpc
+//gsoap ns1  service method-encoding:	stat_USCOREobject http://schemas.xmlsoap.org/soap/encoding/
+//gsoap ns1  service method-action:	stat_USCOREobject urn:Nebulous/Server/SOAP#stat_object
+int ns1__stat_USCOREobject(
+    char*                               key,
+    struct ns1__stat_USCOREobjectResponse* ///< response parameter
+);
+
+/* End of src/nebulous.h */
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapC.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapC.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapC.c	(revision 21994)
@@ -0,0 +1,3280 @@
+/* soapC.c
+   Generated by gSOAP 2.7.2 from src/nebulous.h
+   Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc. All Rights Reserved.
+   This part of the software is released under one of the following licenses:
+   GPL, the gSOAP public license, or Genivia's license for commercial use.
+*/
+#include "soapH.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SOAP_BEGIN_NAMESPACE(soap)
+
+SOAP_SOURCE_STAMP("@(#) soapC.c ver 2.7.2 2007-05-01 02:53:36 GMT")
+
+
+#ifndef WITH_NOGLOBAL
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serializeheader(struct soap *soap)
+{
+	if (soap->header)
+		soap_serialize_SOAP_ENV__Header(soap, soap->header);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_putheader(struct soap *soap)
+{
+	if (soap->header)
+	{	soap->part = SOAP_IN_HEADER;
+		soap_out_SOAP_ENV__Header(soap, "SOAP-ENV:Header", 0, soap->header, NULL);
+		soap->part = SOAP_END_HEADER;
+	}
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_getheader(struct soap *soap)
+{
+	soap->part = SOAP_IN_HEADER;
+	soap->header = soap_in_SOAP_ENV__Header(soap, "SOAP-ENV:Header", NULL, NULL);
+	soap->part = SOAP_END_HEADER;
+	return soap->header == NULL;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_fault(struct soap *soap)
+{
+	if (!soap->fault)
+	{	soap->fault = (struct SOAP_ENV__Fault*)soap_malloc(soap, sizeof(struct SOAP_ENV__Fault));
+		soap_default_SOAP_ENV__Fault(soap, soap->fault);
+	}
+	if (soap->version != 1 && !soap->fault->SOAP_ENV__Code)
+	{	soap->fault->SOAP_ENV__Code = (struct SOAP_ENV__Code*)soap_malloc(soap, sizeof(struct SOAP_ENV__Code));
+		soap_default_SOAP_ENV__Code(soap, soap->fault->SOAP_ENV__Code);
+	}
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serializefault(struct soap *soap)
+{
+	if (soap->fault)
+		soap_serialize_SOAP_ENV__Fault(soap, soap->fault);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_putfault(struct soap *soap)
+{
+	if (soap->fault)
+		return soap_put_SOAP_ENV__Fault(soap, soap->fault, "SOAP-ENV:Fault", NULL);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_getfault(struct soap *soap)
+{
+	return (soap->fault = soap_get_SOAP_ENV__Fault(soap, NULL, "SOAP-ENV:Fault", NULL)) == NULL;
+}
+
+SOAP_FMAC3 const char ** SOAP_FMAC4 soap_faultcode(struct soap *soap)
+{
+	soap_fault(soap);
+	if (soap->version == 2)
+		return (const char**)&soap->fault->SOAP_ENV__Code->SOAP_ENV__Value;
+	return (const char**)&soap->fault->faultcode;
+}
+
+SOAP_FMAC3 const char ** SOAP_FMAC4 soap_faultstring(struct soap *soap)
+{
+	soap_fault(soap);
+	if (soap->version == 2)
+		return (const char**)&soap->fault->SOAP_ENV__Reason;
+	return (const char**)&soap->fault->faultstring;
+}
+
+SOAP_FMAC3 const char ** SOAP_FMAC4 soap_faultdetail(struct soap *soap)
+{
+	soap_fault(soap);
+	if (soap->version == 1)
+	{	if (!soap->fault->detail)
+		{	soap->fault->detail = (struct SOAP_ENV__Detail*)soap_malloc(soap, sizeof(struct SOAP_ENV__Detail));
+			soap_default_SOAP_ENV__Detail(soap, soap->fault->detail);
+		}
+		return (const char**)&soap->fault->detail->__any;
+	}
+	if (!soap->fault->SOAP_ENV__Detail)
+	{	soap->fault->SOAP_ENV__Detail = (struct SOAP_ENV__Detail*)soap_malloc(soap, sizeof(struct SOAP_ENV__Detail));
+		soap_default_SOAP_ENV__Detail(soap, soap->fault->SOAP_ENV__Detail);
+	}
+	return (const char**)&soap->fault->SOAP_ENV__Detail->__any;
+}
+
+#endif
+
+#ifndef WITH_NOIDREF
+SOAP_FMAC3 int SOAP_FMAC4 soap_getindependent(struct soap *soap)
+{
+	int t;
+	for (;;)
+		if (!soap_getelement(soap, &t))
+			if (soap->error || soap_ignore_element(soap))
+				break;
+	if (soap->error == SOAP_NO_TAG || soap->error == SOAP_EOF)
+		soap->error = SOAP_OK;
+	return soap->error;
+}
+#endif
+
+#ifndef WITH_NOIDREF
+SOAP_FMAC3 void * SOAP_FMAC4 soap_getelement(struct soap *soap, int *type)
+{
+	if (soap_peek_element(soap))
+		return NULL;
+	if (!*soap->id || !(*type = soap_lookup_type(soap, soap->id)))
+		*type = soap_lookup_type(soap, soap->href);
+	switch (*type)
+	{
+	case SOAP_TYPE_byte:
+		return soap_in_byte(soap, NULL, NULL, "xsd:byte");
+	case SOAP_TYPE_int:
+		return soap_in_int(soap, NULL, NULL, "xsd:int");
+	case SOAP_TYPE_ns1__stat_USCOREobject:
+		return soap_in_ns1__stat_USCOREobject(soap, NULL, NULL, "ns1:stat_object");
+	case SOAP_TYPE_ns1__stat_USCOREobjectResponse:
+		return soap_in_ns1__stat_USCOREobjectResponse(soap, NULL, NULL, "ns1:stat_objectResponse");
+	case SOAP_TYPE_ns1__delete_USCOREinstance:
+		return soap_in_ns1__delete_USCOREinstance(soap, NULL, NULL, "ns1:delete_instance");
+	case SOAP_TYPE_ns1__delete_USCOREinstanceResponse:
+		return soap_in_ns1__delete_USCOREinstanceResponse(soap, NULL, NULL, "ns1:delete_instanceResponse");
+	case SOAP_TYPE_ns1__find_USCOREinstances:
+		return soap_in_ns1__find_USCOREinstances(soap, NULL, NULL, "ns1:find_instances");
+	case SOAP_TYPE_ns1__find_USCOREinstancesResponse:
+		return soap_in_ns1__find_USCOREinstancesResponse(soap, NULL, NULL, "ns1:find_instancesResponse");
+	case SOAP_TYPE_ns1__find_USCOREobjects:
+		return soap_in_ns1__find_USCOREobjects(soap, NULL, NULL, "ns1:find_objects");
+	case SOAP_TYPE_ns1__find_USCOREobjectsResponse:
+		return soap_in_ns1__find_USCOREobjectsResponse(soap, NULL, NULL, "ns1:find_objectsResponse");
+	case SOAP_TYPE_ns1__unlock_USCOREobject:
+		return soap_in_ns1__unlock_USCOREobject(soap, NULL, NULL, "ns1:unlock_object");
+	case SOAP_TYPE_ns1__unlock_USCOREobjectResponse:
+		return soap_in_ns1__unlock_USCOREobjectResponse(soap, NULL, NULL, "ns1:unlock_objectResponse");
+	case SOAP_TYPE_ns1__lock_USCOREobject:
+		return soap_in_ns1__lock_USCOREobject(soap, NULL, NULL, "ns1:lock_object");
+	case SOAP_TYPE_ns1__lock_USCOREobjectResponse:
+		return soap_in_ns1__lock_USCOREobjectResponse(soap, NULL, NULL, "ns1:lock_objectResponse");
+	case SOAP_TYPE_ns1__replicate_USCOREobject:
+		return soap_in_ns1__replicate_USCOREobject(soap, NULL, NULL, "ns1:replicate_object");
+	case SOAP_TYPE_ns1__replicate_USCOREobjectResponse:
+		return soap_in_ns1__replicate_USCOREobjectResponse(soap, NULL, NULL, "ns1:replicate_objectResponse");
+	case SOAP_TYPE_ns1__rename_USCOREobject_:
+		return soap_in_ns1__rename_USCOREobject_(soap, NULL, NULL, "ns1:rename_object");
+	case SOAP_TYPE_ns1__rename_USCOREobject_Response:
+		return soap_in_ns1__rename_USCOREobject_Response(soap, NULL, NULL, "ns1:rename_object-Response");
+	case SOAP_TYPE_ns1__rename_USCOREobject:
+		return soap_in_ns1__rename_USCOREobject(soap, NULL, NULL, "ns1:rename_object");
+	case SOAP_TYPE_ns1__rename_USCOREobjectResponse:
+		return soap_in_ns1__rename_USCOREobjectResponse(soap, NULL, NULL, "ns1:rename_objectResponse");
+	case SOAP_TYPE_ns1__create_USCOREobject:
+		return soap_in_ns1__create_USCOREobject(soap, NULL, NULL, "ns1:create_object");
+	case SOAP_TYPE_ns1__create_USCOREobjectResponse:
+		return soap_in_ns1__create_USCOREobjectResponse(soap, NULL, NULL, "ns1:create_objectResponse");
+	case SOAP_TYPE_ArrayOfString:
+		return soap_in_ArrayOfString(soap, NULL, NULL, "xsd:string");
+	case SOAP_TYPE_PointerTons1__stat_USCOREobjectResponse:
+		return soap_in_PointerTons1__stat_USCOREobjectResponse(soap, NULL, NULL, "ns1:stat_objectResponse");
+	case SOAP_TYPE_PointerTons1__find_USCOREinstancesResponse:
+		return soap_in_PointerTons1__find_USCOREinstancesResponse(soap, NULL, NULL, "ns1:find_instancesResponse");
+	case SOAP_TYPE_PointerTons1__find_USCOREobjectsResponse:
+		return soap_in_PointerTons1__find_USCOREobjectsResponse(soap, NULL, NULL, "ns1:find_objectsResponse");
+	case SOAP_TYPE_PointerToArrayOfString:
+		return soap_in_PointerToArrayOfString(soap, NULL, NULL, "xsd:string");
+	case SOAP_TYPE_PointerToint:
+		return soap_in_PointerToint(soap, NULL, NULL, "xsd:int");
+	case SOAP_TYPE_PointerTostring:
+		return soap_in_PointerTostring(soap, NULL, NULL, "xsd:string");
+	case SOAP_TYPE_SOAP_ENC__arrayType:
+	{	char **s;
+		s = soap_in_SOAP_ENC__arrayType(soap, NULL, NULL, "SOAP-ENC:arrayType");
+		return s ? *s : NULL;
+	}
+	case SOAP_TYPE__QName:
+	{	char **s;
+		s = soap_in__QName(soap, NULL, NULL, "QName");
+		return s ? *s : NULL;
+	}
+	case SOAP_TYPE_string:
+	{	char **s;
+		s = soap_in_string(soap, NULL, NULL, "xsd:string");
+		return s ? *s : NULL;
+	}
+	default:
+	{	const char *t = soap->type;
+		if (!*t)
+			t = soap->tag;
+		if (!soap_match_tag(soap, t, "xsd:byte"))
+		{	*type = SOAP_TYPE_byte;
+			return soap_in_byte(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "xsd:int"))
+		{	*type = SOAP_TYPE_int;
+			return soap_in_int(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:stat_object"))
+		{	*type = SOAP_TYPE_ns1__stat_USCOREobject;
+			return soap_in_ns1__stat_USCOREobject(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:stat_objectResponse"))
+		{	*type = SOAP_TYPE_ns1__stat_USCOREobjectResponse;
+			return soap_in_ns1__stat_USCOREobjectResponse(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:delete_instance"))
+		{	*type = SOAP_TYPE_ns1__delete_USCOREinstance;
+			return soap_in_ns1__delete_USCOREinstance(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:delete_instanceResponse"))
+		{	*type = SOAP_TYPE_ns1__delete_USCOREinstanceResponse;
+			return soap_in_ns1__delete_USCOREinstanceResponse(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:find_instances"))
+		{	*type = SOAP_TYPE_ns1__find_USCOREinstances;
+			return soap_in_ns1__find_USCOREinstances(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:find_instancesResponse"))
+		{	*type = SOAP_TYPE_ns1__find_USCOREinstancesResponse;
+			return soap_in_ns1__find_USCOREinstancesResponse(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:find_objects"))
+		{	*type = SOAP_TYPE_ns1__find_USCOREobjects;
+			return soap_in_ns1__find_USCOREobjects(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:find_objectsResponse"))
+		{	*type = SOAP_TYPE_ns1__find_USCOREobjectsResponse;
+			return soap_in_ns1__find_USCOREobjectsResponse(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:unlock_object"))
+		{	*type = SOAP_TYPE_ns1__unlock_USCOREobject;
+			return soap_in_ns1__unlock_USCOREobject(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:unlock_objectResponse"))
+		{	*type = SOAP_TYPE_ns1__unlock_USCOREobjectResponse;
+			return soap_in_ns1__unlock_USCOREobjectResponse(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:lock_object"))
+		{	*type = SOAP_TYPE_ns1__lock_USCOREobject;
+			return soap_in_ns1__lock_USCOREobject(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:lock_objectResponse"))
+		{	*type = SOAP_TYPE_ns1__lock_USCOREobjectResponse;
+			return soap_in_ns1__lock_USCOREobjectResponse(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:replicate_object"))
+		{	*type = SOAP_TYPE_ns1__replicate_USCOREobject;
+			return soap_in_ns1__replicate_USCOREobject(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:replicate_objectResponse"))
+		{	*type = SOAP_TYPE_ns1__replicate_USCOREobjectResponse;
+			return soap_in_ns1__replicate_USCOREobjectResponse(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:rename_object"))
+		{	*type = SOAP_TYPE_ns1__rename_USCOREobject_;
+			return soap_in_ns1__rename_USCOREobject_(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:rename_object-Response"))
+		{	*type = SOAP_TYPE_ns1__rename_USCOREobject_Response;
+			return soap_in_ns1__rename_USCOREobject_Response(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:rename_object"))
+		{	*type = SOAP_TYPE_ns1__rename_USCOREobject;
+			return soap_in_ns1__rename_USCOREobject(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:rename_objectResponse"))
+		{	*type = SOAP_TYPE_ns1__rename_USCOREobjectResponse;
+			return soap_in_ns1__rename_USCOREobjectResponse(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:create_object"))
+		{	*type = SOAP_TYPE_ns1__create_USCOREobject;
+			return soap_in_ns1__create_USCOREobject(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "ns1:create_objectResponse"))
+		{	*type = SOAP_TYPE_ns1__create_USCOREobjectResponse;
+			return soap_in_ns1__create_USCOREobjectResponse(soap, NULL, NULL, NULL);
+		}
+		if (*soap->arrayType && !soap_match_array(soap, "xsd:string"))
+		{	*type = SOAP_TYPE_ArrayOfString;
+			return soap_in_ArrayOfString(soap, NULL, NULL, NULL);
+		}
+		if (!soap_match_tag(soap, t, "SOAP-ENC:arrayType"))
+		{	char **s;
+			*type = SOAP_TYPE_SOAP_ENC__arrayType;
+			s = soap_in_SOAP_ENC__arrayType(soap, NULL, NULL, NULL);
+			return s ? *s : NULL;
+		}
+		if (!soap_match_tag(soap, t, "QName"))
+		{	char **s;
+			*type = SOAP_TYPE__QName;
+			s = soap_in__QName(soap, NULL, NULL, NULL);
+			return s ? *s : NULL;
+		}
+		if (!soap_match_tag(soap, t, "xsd:string"))
+		{	char **s;
+			*type = SOAP_TYPE_string;
+			s = soap_in_string(soap, NULL, NULL, NULL);
+			return s ? *s : NULL;
+		}
+	}
+	}
+	soap->error = SOAP_TAG_MISMATCH;
+	return NULL;
+}
+#endif
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_ignore_element(struct soap *soap)
+{	if (!soap_peek_element(soap))
+	{	int t;
+		if (soap->mustUnderstand && !soap->other)
+			return soap->error = SOAP_MUSTUNDERSTAND;
+		if (((soap->mode & SOAP_XML_STRICT) && soap->part != SOAP_IN_HEADER) || !soap_match_tag(soap, soap->tag, "SOAP-ENV:"))
+			return soap->error = SOAP_TAG_MISMATCH;
+		if (!*soap->id || !soap_getelement(soap, &t))
+		{	soap->peeked = 0;
+			DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unknown element '%s' (level=%u, %d)\n", soap->tag, soap->level, soap->body));
+			if (soap->fignore)
+				soap->error = soap->fignore(soap, soap->tag);
+			else
+				soap->error = SOAP_OK;
+			DBGLOG(TEST, if (!soap->error) SOAP_MESSAGE(fdebug, "IGNORING element '%s'\n", soap->tag));
+			if (!soap->error && soap->body)
+			{	soap->level++;
+				while (!soap_ignore_element(soap))
+					;
+				if (soap->error == SOAP_NO_TAG)
+					soap->error = soap_element_end_in(soap, NULL);
+			}
+		}
+	}
+	return soap->error;
+}
+
+#ifndef WITH_NOIDREF
+SOAP_FMAC3 int SOAP_FMAC4 soap_putindependent(struct soap *soap)
+{
+	int i;
+	struct soap_plist *pp;
+	if (soap->version == 1 && soap->encodingStyle && !(soap->mode & (SOAP_XML_TREE | SOAP_XML_GRAPH)))
+		for (i = 0; i < SOAP_PTRHASH; i++)
+			for (pp = soap->pht[i]; pp; pp = pp->next)
+				if (pp->mark1 == 2 || pp->mark2 == 2)
+					if (soap_putelement(soap, pp->ptr, "id", pp->id, pp->type))
+						return soap->error;
+	return SOAP_OK;
+}
+#endif
+
+#ifndef WITH_NOIDREF
+SOAP_FMAC3 int SOAP_FMAC4 soap_putelement(struct soap *soap, const void *ptr, const char *tag, int id, int type)
+{
+	switch (type)
+	{
+	case SOAP_TYPE_byte:
+		return soap_out_byte(soap, tag, id, (const char *)ptr, "xsd:byte");
+	case SOAP_TYPE_int:
+		return soap_out_int(soap, tag, id, (const int *)ptr, "xsd:int");
+	case SOAP_TYPE_ns1__stat_USCOREobject:
+		return soap_out_ns1__stat_USCOREobject(soap, tag, id, (const struct ns1__stat_USCOREobject *)ptr, "ns1:stat_object");
+	case SOAP_TYPE_ns1__stat_USCOREobjectResponse:
+		return soap_out_ns1__stat_USCOREobjectResponse(soap, tag, id, (const struct ns1__stat_USCOREobjectResponse *)ptr, "ns1:stat_objectResponse");
+	case SOAP_TYPE_ns1__delete_USCOREinstance:
+		return soap_out_ns1__delete_USCOREinstance(soap, tag, id, (const struct ns1__delete_USCOREinstance *)ptr, "ns1:delete_instance");
+	case SOAP_TYPE_ns1__delete_USCOREinstanceResponse:
+		return soap_out_ns1__delete_USCOREinstanceResponse(soap, tag, id, (const struct ns1__delete_USCOREinstanceResponse *)ptr, "ns1:delete_instanceResponse");
+	case SOAP_TYPE_ns1__find_USCOREinstances:
+		return soap_out_ns1__find_USCOREinstances(soap, tag, id, (const struct ns1__find_USCOREinstances *)ptr, "ns1:find_instances");
+	case SOAP_TYPE_ns1__find_USCOREinstancesResponse:
+		return soap_out_ns1__find_USCOREinstancesResponse(soap, tag, id, (const struct ns1__find_USCOREinstancesResponse *)ptr, "ns1:find_instancesResponse");
+	case SOAP_TYPE_ns1__find_USCOREobjects:
+		return soap_out_ns1__find_USCOREobjects(soap, tag, id, (const struct ns1__find_USCOREobjects *)ptr, "ns1:find_objects");
+	case SOAP_TYPE_ns1__find_USCOREobjectsResponse:
+		return soap_out_ns1__find_USCOREobjectsResponse(soap, tag, id, (const struct ns1__find_USCOREobjectsResponse *)ptr, "ns1:find_objectsResponse");
+	case SOAP_TYPE_ns1__unlock_USCOREobject:
+		return soap_out_ns1__unlock_USCOREobject(soap, tag, id, (const struct ns1__unlock_USCOREobject *)ptr, "ns1:unlock_object");
+	case SOAP_TYPE_ns1__unlock_USCOREobjectResponse:
+		return soap_out_ns1__unlock_USCOREobjectResponse(soap, tag, id, (const struct ns1__unlock_USCOREobjectResponse *)ptr, "ns1:unlock_objectResponse");
+	case SOAP_TYPE_ns1__lock_USCOREobject:
+		return soap_out_ns1__lock_USCOREobject(soap, tag, id, (const struct ns1__lock_USCOREobject *)ptr, "ns1:lock_object");
+	case SOAP_TYPE_ns1__lock_USCOREobjectResponse:
+		return soap_out_ns1__lock_USCOREobjectResponse(soap, tag, id, (const struct ns1__lock_USCOREobjectResponse *)ptr, "ns1:lock_objectResponse");
+	case SOAP_TYPE_ns1__replicate_USCOREobject:
+		return soap_out_ns1__replicate_USCOREobject(soap, tag, id, (const struct ns1__replicate_USCOREobject *)ptr, "ns1:replicate_object");
+	case SOAP_TYPE_ns1__replicate_USCOREobjectResponse:
+		return soap_out_ns1__replicate_USCOREobjectResponse(soap, tag, id, (const struct ns1__replicate_USCOREobjectResponse *)ptr, "ns1:replicate_objectResponse");
+	case SOAP_TYPE_ns1__rename_USCOREobject_:
+		return soap_out_ns1__rename_USCOREobject_(soap, tag, id, (const struct ns1__rename_USCOREobject_ *)ptr, "ns1:rename_object");
+	case SOAP_TYPE_ns1__rename_USCOREobject_Response:
+		return soap_out_ns1__rename_USCOREobject_Response(soap, tag, id, (const struct ns1__rename_USCOREobject_Response *)ptr, "ns1:rename_object-Response");
+	case SOAP_TYPE_ns1__rename_USCOREobject:
+		return soap_out_ns1__rename_USCOREobject(soap, tag, id, (const struct ns1__rename_USCOREobject *)ptr, "ns1:rename_object");
+	case SOAP_TYPE_ns1__rename_USCOREobjectResponse:
+		return soap_out_ns1__rename_USCOREobjectResponse(soap, tag, id, (const struct ns1__rename_USCOREobjectResponse *)ptr, "ns1:rename_objectResponse");
+	case SOAP_TYPE_ns1__create_USCOREobject:
+		return soap_out_ns1__create_USCOREobject(soap, tag, id, (const struct ns1__create_USCOREobject *)ptr, "ns1:create_object");
+	case SOAP_TYPE_ns1__create_USCOREobjectResponse:
+		return soap_out_ns1__create_USCOREobjectResponse(soap, tag, id, (const struct ns1__create_USCOREobjectResponse *)ptr, "ns1:create_objectResponse");
+	case SOAP_TYPE_ArrayOfString:
+		return soap_out_ArrayOfString(soap, tag, id, (const struct ArrayOfString *)ptr, "xsd:string");
+	case SOAP_TYPE_PointerTons1__stat_USCOREobjectResponse:
+		return soap_out_PointerTons1__stat_USCOREobjectResponse(soap, tag, id, (struct ns1__stat_USCOREobjectResponse *const*)ptr, "ns1:stat_objectResponse");
+	case SOAP_TYPE_PointerTons1__find_USCOREinstancesResponse:
+		return soap_out_PointerTons1__find_USCOREinstancesResponse(soap, tag, id, (struct ns1__find_USCOREinstancesResponse *const*)ptr, "ns1:find_instancesResponse");
+	case SOAP_TYPE_PointerTons1__find_USCOREobjectsResponse:
+		return soap_out_PointerTons1__find_USCOREobjectsResponse(soap, tag, id, (struct ns1__find_USCOREobjectsResponse *const*)ptr, "ns1:find_objectsResponse");
+	case SOAP_TYPE_PointerToArrayOfString:
+		return soap_out_PointerToArrayOfString(soap, tag, id, (struct ArrayOfString *const*)ptr, "xsd:string");
+	case SOAP_TYPE_PointerToint:
+		return soap_out_PointerToint(soap, tag, id, (int *const*)ptr, "xsd:int");
+	case SOAP_TYPE_PointerTostring:
+		return soap_out_PointerTostring(soap, tag, id, (char **const*)ptr, "xsd:string");
+	case SOAP_TYPE_SOAP_ENC__arrayType:
+		return soap_out_string(soap, tag, id, (char**)&ptr, "SOAP-ENC:arrayType");
+	case SOAP_TYPE__QName:
+		return soap_out_string(soap, "QName", id, (char**)&ptr, NULL);
+	case SOAP_TYPE_string:
+		return soap_out_string(soap, tag, id, (char**)&ptr, "xsd:string");
+	}
+	return SOAP_OK;
+}
+#endif
+
+#ifndef WITH_NOIDREF
+SOAP_FMAC3 void SOAP_FMAC4 soap_markelement(struct soap *soap, const void *ptr, int type)
+{
+	(void)soap; (void)ptr; (void)type; /* appease -Wall -Werror */
+	switch (type)
+	{
+	case SOAP_TYPE_ns1__stat_USCOREobject:
+		soap_serialize_ns1__stat_USCOREobject(soap, (const struct ns1__stat_USCOREobject *)ptr);
+		break;
+	case SOAP_TYPE_ns1__stat_USCOREobjectResponse:
+		soap_serialize_ns1__stat_USCOREobjectResponse(soap, (const struct ns1__stat_USCOREobjectResponse *)ptr);
+		break;
+	case SOAP_TYPE_ns1__delete_USCOREinstance:
+		soap_serialize_ns1__delete_USCOREinstance(soap, (const struct ns1__delete_USCOREinstance *)ptr);
+		break;
+	case SOAP_TYPE_ns1__delete_USCOREinstanceResponse:
+		soap_serialize_ns1__delete_USCOREinstanceResponse(soap, (const struct ns1__delete_USCOREinstanceResponse *)ptr);
+		break;
+	case SOAP_TYPE_ns1__find_USCOREinstances:
+		soap_serialize_ns1__find_USCOREinstances(soap, (const struct ns1__find_USCOREinstances *)ptr);
+		break;
+	case SOAP_TYPE_ns1__find_USCOREinstancesResponse:
+		soap_serialize_ns1__find_USCOREinstancesResponse(soap, (const struct ns1__find_USCOREinstancesResponse *)ptr);
+		break;
+	case SOAP_TYPE_ns1__find_USCOREobjects:
+		soap_serialize_ns1__find_USCOREobjects(soap, (const struct ns1__find_USCOREobjects *)ptr);
+		break;
+	case SOAP_TYPE_ns1__find_USCOREobjectsResponse:
+		soap_serialize_ns1__find_USCOREobjectsResponse(soap, (const struct ns1__find_USCOREobjectsResponse *)ptr);
+		break;
+	case SOAP_TYPE_ns1__unlock_USCOREobject:
+		soap_serialize_ns1__unlock_USCOREobject(soap, (const struct ns1__unlock_USCOREobject *)ptr);
+		break;
+	case SOAP_TYPE_ns1__unlock_USCOREobjectResponse:
+		soap_serialize_ns1__unlock_USCOREobjectResponse(soap, (const struct ns1__unlock_USCOREobjectResponse *)ptr);
+		break;
+	case SOAP_TYPE_ns1__lock_USCOREobject:
+		soap_serialize_ns1__lock_USCOREobject(soap, (const struct ns1__lock_USCOREobject *)ptr);
+		break;
+	case SOAP_TYPE_ns1__lock_USCOREobjectResponse:
+		soap_serialize_ns1__lock_USCOREobjectResponse(soap, (const struct ns1__lock_USCOREobjectResponse *)ptr);
+		break;
+	case SOAP_TYPE_ns1__replicate_USCOREobject:
+		soap_serialize_ns1__replicate_USCOREobject(soap, (const struct ns1__replicate_USCOREobject *)ptr);
+		break;
+	case SOAP_TYPE_ns1__replicate_USCOREobjectResponse:
+		soap_serialize_ns1__replicate_USCOREobjectResponse(soap, (const struct ns1__replicate_USCOREobjectResponse *)ptr);
+		break;
+	case SOAP_TYPE_ns1__rename_USCOREobject_:
+		soap_serialize_ns1__rename_USCOREobject_(soap, (const struct ns1__rename_USCOREobject_ *)ptr);
+		break;
+	case SOAP_TYPE_ns1__rename_USCOREobject_Response:
+		soap_serialize_ns1__rename_USCOREobject_Response(soap, (const struct ns1__rename_USCOREobject_Response *)ptr);
+		break;
+	case SOAP_TYPE_ns1__rename_USCOREobject:
+		soap_serialize_ns1__rename_USCOREobject(soap, (const struct ns1__rename_USCOREobject *)ptr);
+		break;
+	case SOAP_TYPE_ns1__rename_USCOREobjectResponse:
+		soap_serialize_ns1__rename_USCOREobjectResponse(soap, (const struct ns1__rename_USCOREobjectResponse *)ptr);
+		break;
+	case SOAP_TYPE_ns1__create_USCOREobject:
+		soap_serialize_ns1__create_USCOREobject(soap, (const struct ns1__create_USCOREobject *)ptr);
+		break;
+	case SOAP_TYPE_ns1__create_USCOREobjectResponse:
+		soap_serialize_ns1__create_USCOREobjectResponse(soap, (const struct ns1__create_USCOREobjectResponse *)ptr);
+		break;
+	case SOAP_TYPE_ArrayOfString:
+		soap_serialize_ArrayOfString(soap, (const struct ArrayOfString *)ptr);
+		break;
+	case SOAP_TYPE_PointerTons1__stat_USCOREobjectResponse:
+		soap_serialize_PointerTons1__stat_USCOREobjectResponse(soap, (struct ns1__stat_USCOREobjectResponse *const*)ptr);
+		break;
+	case SOAP_TYPE_PointerTons1__find_USCOREinstancesResponse:
+		soap_serialize_PointerTons1__find_USCOREinstancesResponse(soap, (struct ns1__find_USCOREinstancesResponse *const*)ptr);
+		break;
+	case SOAP_TYPE_PointerTons1__find_USCOREobjectsResponse:
+		soap_serialize_PointerTons1__find_USCOREobjectsResponse(soap, (struct ns1__find_USCOREobjectsResponse *const*)ptr);
+		break;
+	case SOAP_TYPE_PointerToArrayOfString:
+		soap_serialize_PointerToArrayOfString(soap, (struct ArrayOfString *const*)ptr);
+		break;
+	case SOAP_TYPE_PointerToint:
+		soap_serialize_PointerToint(soap, (int *const*)ptr);
+		break;
+	case SOAP_TYPE_PointerTostring:
+		soap_serialize_PointerTostring(soap, (char **const*)ptr);
+		break;
+	case SOAP_TYPE_SOAP_ENC__arrayType:
+		soap_serialize_string(soap, (char**)&ptr);
+		break;
+	case SOAP_TYPE__QName:
+		soap_serialize_string(soap, (char**)&ptr);
+		break;
+	case SOAP_TYPE_string:
+		soap_serialize_string(soap, (char**)&ptr);
+		break;
+	}
+}
+#endif
+
+#ifndef WITH_LEANER
+SOAP_FMAC3 int SOAP_FMAC4 soap_resolve_attachments(struct soap *soap)
+{
+	if (!(soap->mode & SOAP_ENC_DIME))
+		return SOAP_OK;
+	while (soap->dime.flags & SOAP_DIME_CF)
+	{	if (soap_getdimehdr(soap))
+			return soap->error;
+		if (soap_move(soap, soap->dime.size))
+			return soap->error = SOAP_EOF;
+	}
+	if (soap_move(soap, ((soap->dime.size+3)&(~3))-soap_tell(soap)))
+		return soap->error = SOAP_EOF;
+	for (;;)
+	{	if (soap_getdime(soap))
+			break;
+		switch (soap_lookup_type(soap, soap->dime.id))
+		{
+		}
+	}
+	if (soap->error == SOAP_DIME_END)
+		soap->error = SOAP_OK;
+	return soap->error;
+}
+#endif
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_byte(struct soap *soap, char *a)
+{
+(void)soap; /* appease -Wall -Werror */
+#ifdef SOAP_DEFAULT_byte
+	*a = SOAP_DEFAULT_byte;
+#else
+	*a = (char)0;
+#endif
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_byte(struct soap *soap, const char *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_byte);
+	if (soap_out_byte(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_byte(struct soap *soap, const char *tag, int id, const char *a, const char *type)
+{
+	return soap_outbyte(soap, tag, id, a, type, SOAP_TYPE_byte);
+}
+
+SOAP_FMAC3 char * SOAP_FMAC4 soap_get_byte(struct soap *soap, char *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_byte(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 char * SOAP_FMAC4 soap_in_byte(struct soap *soap, const char *tag, char *a, const char *type)
+{
+	return soap_inbyte(soap, tag, a, type, SOAP_TYPE_byte);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_int(struct soap *soap, int *a)
+{
+(void)soap; /* appease -Wall -Werror */
+#ifdef SOAP_DEFAULT_int
+	*a = SOAP_DEFAULT_int;
+#else
+	*a = (int)0;
+#endif
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_int(struct soap *soap, const int *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_int);
+	if (soap_out_int(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_int(struct soap *soap, const char *tag, int id, const int *a, const char *type)
+{
+	return soap_outint(soap, tag, id, a, type, SOAP_TYPE_int);
+}
+
+SOAP_FMAC3 int * SOAP_FMAC4 soap_get_int(struct soap *soap, int *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_int(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 int * SOAP_FMAC4 soap_in_int(struct soap *soap, const char *tag, int *a, const char *type)
+{
+	return soap_inint(soap, tag, a, type, SOAP_TYPE_int);
+}
+
+#ifndef WITH_NOGLOBAL
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Fault(struct soap *soap, const struct SOAP_ENV__Fault *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->faultcode, SOAP_TYPE__QName);
+	soap_serialize__QName(soap, &a->faultcode);
+	soap_embedded(soap, &a->faultstring, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->faultstring);
+	soap_embedded(soap, &a->faultactor, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->faultactor);
+	soap_embedded(soap, &a->detail, SOAP_TYPE_PointerToSOAP_ENV__Detail);
+	soap_serialize_PointerToSOAP_ENV__Detail(soap, &a->detail);
+	soap_embedded(soap, &a->SOAP_ENV__Code, SOAP_TYPE_PointerToSOAP_ENV__Code);
+	soap_serialize_PointerToSOAP_ENV__Code(soap, &a->SOAP_ENV__Code);
+	soap_embedded(soap, &a->SOAP_ENV__Reason, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->SOAP_ENV__Reason);
+	soap_embedded(soap, &a->SOAP_ENV__Node, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->SOAP_ENV__Node);
+	soap_embedded(soap, &a->SOAP_ENV__Role, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->SOAP_ENV__Role);
+	soap_embedded(soap, &a->SOAP_ENV__Detail, SOAP_TYPE_PointerToSOAP_ENV__Detail);
+	soap_serialize_PointerToSOAP_ENV__Detail(soap, &a->SOAP_ENV__Detail);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Fault(struct soap *soap, struct SOAP_ENV__Fault *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_default__QName(soap, &a->faultcode);
+	soap_default_string(soap, &a->faultstring);
+	soap_default_string(soap, &a->faultactor);
+	a->detail = NULL;
+	a->SOAP_ENV__Code = NULL;
+	soap_default_string(soap, &a->SOAP_ENV__Reason);
+	soap_default_string(soap, &a->SOAP_ENV__Node);
+	soap_default_string(soap, &a->SOAP_ENV__Role);
+	a->SOAP_ENV__Detail = NULL;
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Fault(struct soap *soap, const struct SOAP_ENV__Fault *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_SOAP_ENV__Fault);
+	if (soap_out_SOAP_ENV__Fault(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Fault(struct soap *soap, const char *tag, int id, const struct SOAP_ENV__Fault *a, const char *type)
+{
+	const char *soap_tmp_faultcode = soap_QName2s(soap, a->faultcode);
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_SOAP_ENV__Fault), type);
+	soap_out__QName(soap, "faultcode", -1, (char*const*)&soap_tmp_faultcode, "");
+	soap_out_string(soap, "faultstring", -1, &a->faultstring, "");
+	soap_out_string(soap, "faultactor", -1, &a->faultactor, "");
+	soap_out_PointerToSOAP_ENV__Detail(soap, "detail", -1, &a->detail, "");
+	soap_out_PointerToSOAP_ENV__Code(soap, "SOAP-ENV:Code", -1, &a->SOAP_ENV__Code, "");
+	soap_out_string(soap, "SOAP-ENV:Reason", -1, &a->SOAP_ENV__Reason, "");
+	soap_out_string(soap, "SOAP-ENV:Node", -1, &a->SOAP_ENV__Node, "");
+	soap_out_string(soap, "SOAP-ENV:Role", -1, &a->SOAP_ENV__Role, "");
+	soap_out_PointerToSOAP_ENV__Detail(soap, "SOAP-ENV:Detail", -1, &a->SOAP_ENV__Detail, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct SOAP_ENV__Fault * SOAP_FMAC4 soap_get_SOAP_ENV__Fault(struct soap *soap, struct SOAP_ENV__Fault *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_SOAP_ENV__Fault(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct SOAP_ENV__Fault * SOAP_FMAC4 soap_in_SOAP_ENV__Fault(struct soap *soap, const char *tag, struct SOAP_ENV__Fault *a, const char *type)
+{
+	short soap_flag_faultcode = 1, soap_flag_faultstring = 1, soap_flag_faultactor = 1, soap_flag_detail = 1, soap_flag_SOAP_ENV__Code = 1, soap_flag_SOAP_ENV__Reason = 1, soap_flag_SOAP_ENV__Node = 1, soap_flag_SOAP_ENV__Role = 1, soap_flag_SOAP_ENV__Detail = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct SOAP_ENV__Fault *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_SOAP_ENV__Fault, sizeof(struct SOAP_ENV__Fault), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_SOAP_ENV__Fault(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_faultcode && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in__QName(soap, "faultcode", &a->faultcode, ""))
+				{	soap_flag_faultcode = 0;
+					continue;
+				}
+			if (soap_flag_faultstring && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "faultstring", &a->faultstring, ""))
+				{	soap_flag_faultstring = 0;
+					continue;
+				}
+			if (soap_flag_faultactor && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "faultactor", &a->faultactor, ""))
+				{	soap_flag_faultactor = 0;
+					continue;
+				}
+			if (soap_flag_detail && soap->error == SOAP_TAG_MISMATCH)
+				if (soap_in_PointerToSOAP_ENV__Detail(soap, "detail", &a->detail, ""))
+				{	soap_flag_detail = 0;
+					continue;
+				}
+			if (soap_flag_SOAP_ENV__Code && soap->error == SOAP_TAG_MISMATCH)
+				if (soap_in_PointerToSOAP_ENV__Code(soap, "SOAP-ENV:Code", &a->SOAP_ENV__Code, ""))
+				{	soap_flag_SOAP_ENV__Code = 0;
+					continue;
+				}
+			if (soap_flag_SOAP_ENV__Reason && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "SOAP-ENV:Reason", &a->SOAP_ENV__Reason, ""))
+				{	soap_flag_SOAP_ENV__Reason = 0;
+					continue;
+				}
+			if (soap_flag_SOAP_ENV__Node && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "SOAP-ENV:Node", &a->SOAP_ENV__Node, ""))
+				{	soap_flag_SOAP_ENV__Node = 0;
+					continue;
+				}
+			if (soap_flag_SOAP_ENV__Role && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "SOAP-ENV:Role", &a->SOAP_ENV__Role, ""))
+				{	soap_flag_SOAP_ENV__Role = 0;
+					continue;
+				}
+			if (soap_flag_SOAP_ENV__Detail && soap->error == SOAP_TAG_MISMATCH)
+				if (soap_in_PointerToSOAP_ENV__Detail(soap, "SOAP-ENV:Detail", &a->SOAP_ENV__Detail, ""))
+				{	soap_flag_SOAP_ENV__Detail = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct SOAP_ENV__Fault *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_SOAP_ENV__Fault, 0, sizeof(struct SOAP_ENV__Fault), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+#endif
+
+#ifndef WITH_NOGLOBAL
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Detail(struct soap *soap, const struct SOAP_ENV__Detail *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_markelement(soap, a->fault, a->__type);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	a->__type = 0;
+	a->fault = NULL;
+	a->__any = NULL;
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Detail(struct soap *soap, const struct SOAP_ENV__Detail *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_SOAP_ENV__Detail);
+	if (soap_out_SOAP_ENV__Detail(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Detail(struct soap *soap, const char *tag, int id, const struct SOAP_ENV__Detail *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_SOAP_ENV__Detail), type);
+	soap_putelement(soap, a->fault, "fault", -1, a->__type);
+	soap_outliteral(soap, "-any", &a->__any);
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct SOAP_ENV__Detail * SOAP_FMAC4 soap_get_SOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_SOAP_ENV__Detail(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct SOAP_ENV__Detail * SOAP_FMAC4 soap_in_SOAP_ENV__Detail(struct soap *soap, const char *tag, struct SOAP_ENV__Detail *a, const char *type)
+{
+	short soap_flag_fault = 1, soap_flag___any = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct SOAP_ENV__Detail *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_SOAP_ENV__Detail, sizeof(struct SOAP_ENV__Detail), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_SOAP_ENV__Detail(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_fault && soap->error == SOAP_TAG_MISMATCH)
+				if ((a->fault = soap_getelement(soap, &a->__type)))
+				{	soap_flag_fault = 0;
+					continue;
+				}
+			if (soap_flag___any && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_inliteral(soap, "-any", &a->__any))
+				{	soap_flag___any = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct SOAP_ENV__Detail *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_SOAP_ENV__Detail, 0, sizeof(struct SOAP_ENV__Detail), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+#endif
+
+#ifndef WITH_NOGLOBAL
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Code(struct soap *soap, const struct SOAP_ENV__Code *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->SOAP_ENV__Value, SOAP_TYPE__QName);
+	soap_serialize__QName(soap, &a->SOAP_ENV__Value);
+	soap_embedded(soap, &a->SOAP_ENV__Subcode, SOAP_TYPE_PointerToSOAP_ENV__Code);
+	soap_serialize_PointerToSOAP_ENV__Code(soap, &a->SOAP_ENV__Subcode);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_default__QName(soap, &a->SOAP_ENV__Value);
+	a->SOAP_ENV__Subcode = NULL;
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Code(struct soap *soap, const struct SOAP_ENV__Code *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_SOAP_ENV__Code);
+	if (soap_out_SOAP_ENV__Code(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Code(struct soap *soap, const char *tag, int id, const struct SOAP_ENV__Code *a, const char *type)
+{
+	const char *soap_tmp_SOAP_ENV__Value = soap_QName2s(soap, a->SOAP_ENV__Value);
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_SOAP_ENV__Code), type);
+	soap_out__QName(soap, "SOAP-ENV:Value", -1, (char*const*)&soap_tmp_SOAP_ENV__Value, "");
+	soap_out_PointerToSOAP_ENV__Code(soap, "SOAP-ENV:Subcode", -1, &a->SOAP_ENV__Subcode, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct SOAP_ENV__Code * SOAP_FMAC4 soap_get_SOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_SOAP_ENV__Code(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct SOAP_ENV__Code * SOAP_FMAC4 soap_in_SOAP_ENV__Code(struct soap *soap, const char *tag, struct SOAP_ENV__Code *a, const char *type)
+{
+	short soap_flag_SOAP_ENV__Value = 1, soap_flag_SOAP_ENV__Subcode = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct SOAP_ENV__Code *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_SOAP_ENV__Code, sizeof(struct SOAP_ENV__Code), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_SOAP_ENV__Code(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_SOAP_ENV__Value && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in__QName(soap, "SOAP-ENV:Value", &a->SOAP_ENV__Value, ""))
+				{	soap_flag_SOAP_ENV__Value = 0;
+					continue;
+				}
+			if (soap_flag_SOAP_ENV__Subcode && soap->error == SOAP_TAG_MISMATCH)
+				if (soap_in_PointerToSOAP_ENV__Code(soap, "SOAP-ENV:Subcode", &a->SOAP_ENV__Subcode, ""))
+				{	soap_flag_SOAP_ENV__Subcode = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct SOAP_ENV__Code *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_SOAP_ENV__Code, 0, sizeof(struct SOAP_ENV__Code), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+#endif
+
+#ifndef WITH_NOGLOBAL
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Header(struct soap *soap, const struct SOAP_ENV__Header *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	/* transient dummy skipped */
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Header(struct soap *soap, struct SOAP_ENV__Header *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	/* transient dummy skipped */
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Header(struct soap *soap, const struct SOAP_ENV__Header *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_SOAP_ENV__Header);
+	if (soap_out_SOAP_ENV__Header(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Header(struct soap *soap, const char *tag, int id, const struct SOAP_ENV__Header *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_SOAP_ENV__Header), type);
+	/* transient dummy skipped */
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct SOAP_ENV__Header * SOAP_FMAC4 soap_get_SOAP_ENV__Header(struct soap *soap, struct SOAP_ENV__Header *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_SOAP_ENV__Header(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct SOAP_ENV__Header * SOAP_FMAC4 soap_in_SOAP_ENV__Header(struct soap *soap, const char *tag, struct SOAP_ENV__Header *a, const char *type)
+{;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct SOAP_ENV__Header *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_SOAP_ENV__Header, sizeof(struct SOAP_ENV__Header), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_SOAP_ENV__Header(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+		/* transient dummy skipped */
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct SOAP_ENV__Header *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_SOAP_ENV__Header, 0, sizeof(struct SOAP_ENV__Header), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+#endif
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__stat_USCOREobject(struct soap *soap, const struct ns1__stat_USCOREobject *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->key, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->key);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__stat_USCOREobject(struct soap *soap, struct ns1__stat_USCOREobject *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_default_string(soap, &a->key);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__stat_USCOREobject(struct soap *soap, const struct ns1__stat_USCOREobject *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__stat_USCOREobject);
+	if (soap_out_ns1__stat_USCOREobject(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__stat_USCOREobject(struct soap *soap, const char *tag, int id, const struct ns1__stat_USCOREobject *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__stat_USCOREobject), type);
+	soap_out_string(soap, "key", -1, &a->key, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__stat_USCOREobject * SOAP_FMAC4 soap_get_ns1__stat_USCOREobject(struct soap *soap, struct ns1__stat_USCOREobject *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__stat_USCOREobject(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__stat_USCOREobject * SOAP_FMAC4 soap_in_ns1__stat_USCOREobject(struct soap *soap, const char *tag, struct ns1__stat_USCOREobject *a, const char *type)
+{
+	short soap_flag_key = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__stat_USCOREobject *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__stat_USCOREobject, sizeof(struct ns1__stat_USCOREobject), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__stat_USCOREobject(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_key && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "key", &a->key, ""))
+				{	soap_flag_key = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__stat_USCOREobject *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__stat_USCOREobject, 0, sizeof(struct ns1__stat_USCOREobject), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__stat_USCOREobjectResponse(struct soap *soap, const struct ns1__stat_USCOREobjectResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->result, SOAP_TYPE_PointerToArrayOfString);
+	soap_serialize_PointerToArrayOfString(soap, &a->result);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__stat_USCOREobjectResponse(struct soap *soap, struct ns1__stat_USCOREobjectResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	a->result = NULL;
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__stat_USCOREobjectResponse(struct soap *soap, const struct ns1__stat_USCOREobjectResponse *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__stat_USCOREobjectResponse);
+	if (soap_out_ns1__stat_USCOREobjectResponse(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__stat_USCOREobjectResponse(struct soap *soap, const char *tag, int id, const struct ns1__stat_USCOREobjectResponse *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__stat_USCOREobjectResponse), type);
+	if (a->result)
+		soap_element_result(soap, "result");
+	soap_out_PointerToArrayOfString(soap, "result", -1, &a->result, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__stat_USCOREobjectResponse * SOAP_FMAC4 soap_get_ns1__stat_USCOREobjectResponse(struct soap *soap, struct ns1__stat_USCOREobjectResponse *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__stat_USCOREobjectResponse(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__stat_USCOREobjectResponse * SOAP_FMAC4 soap_in_ns1__stat_USCOREobjectResponse(struct soap *soap, const char *tag, struct ns1__stat_USCOREobjectResponse *a, const char *type)
+{
+	short soap_flag_result = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__stat_USCOREobjectResponse *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__stat_USCOREobjectResponse, sizeof(struct ns1__stat_USCOREobjectResponse), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__stat_USCOREobjectResponse(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_result && soap->error == SOAP_TAG_MISMATCH)
+				if (soap_in_PointerToArrayOfString(soap, "result", &a->result, "xsd:string"))
+				{	soap_flag_result = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__stat_USCOREobjectResponse *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__stat_USCOREobjectResponse, 0, sizeof(struct ns1__stat_USCOREobjectResponse), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__delete_USCOREinstance(struct soap *soap, const struct ns1__delete_USCOREinstance *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->uri, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->uri);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__delete_USCOREinstance(struct soap *soap, struct ns1__delete_USCOREinstance *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_default_string(soap, &a->uri);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__delete_USCOREinstance(struct soap *soap, const struct ns1__delete_USCOREinstance *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__delete_USCOREinstance);
+	if (soap_out_ns1__delete_USCOREinstance(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__delete_USCOREinstance(struct soap *soap, const char *tag, int id, const struct ns1__delete_USCOREinstance *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__delete_USCOREinstance), type);
+	soap_out_string(soap, "uri", -1, &a->uri, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__delete_USCOREinstance * SOAP_FMAC4 soap_get_ns1__delete_USCOREinstance(struct soap *soap, struct ns1__delete_USCOREinstance *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__delete_USCOREinstance(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__delete_USCOREinstance * SOAP_FMAC4 soap_in_ns1__delete_USCOREinstance(struct soap *soap, const char *tag, struct ns1__delete_USCOREinstance *a, const char *type)
+{
+	short soap_flag_uri = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__delete_USCOREinstance *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__delete_USCOREinstance, sizeof(struct ns1__delete_USCOREinstance), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__delete_USCOREinstance(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_uri && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "uri", &a->uri, ""))
+				{	soap_flag_uri = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__delete_USCOREinstance *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__delete_USCOREinstance, 0, sizeof(struct ns1__delete_USCOREinstance), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__delete_USCOREinstanceResponse(struct soap *soap, const struct ns1__delete_USCOREinstanceResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->result, SOAP_TYPE_PointerToint);
+	soap_serialize_PointerToint(soap, &a->result);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__delete_USCOREinstanceResponse(struct soap *soap, struct ns1__delete_USCOREinstanceResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	a->result = NULL;
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__delete_USCOREinstanceResponse(struct soap *soap, const struct ns1__delete_USCOREinstanceResponse *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__delete_USCOREinstanceResponse);
+	if (soap_out_ns1__delete_USCOREinstanceResponse(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__delete_USCOREinstanceResponse(struct soap *soap, const char *tag, int id, const struct ns1__delete_USCOREinstanceResponse *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__delete_USCOREinstanceResponse), type);
+	if (a->result)
+		soap_element_result(soap, "result");
+	soap_out_PointerToint(soap, "result", -1, &a->result, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__delete_USCOREinstanceResponse * SOAP_FMAC4 soap_get_ns1__delete_USCOREinstanceResponse(struct soap *soap, struct ns1__delete_USCOREinstanceResponse *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__delete_USCOREinstanceResponse(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__delete_USCOREinstanceResponse * SOAP_FMAC4 soap_in_ns1__delete_USCOREinstanceResponse(struct soap *soap, const char *tag, struct ns1__delete_USCOREinstanceResponse *a, const char *type)
+{
+	short soap_flag_result = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__delete_USCOREinstanceResponse *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__delete_USCOREinstanceResponse, sizeof(struct ns1__delete_USCOREinstanceResponse), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__delete_USCOREinstanceResponse(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_result && soap->error == SOAP_TAG_MISMATCH)
+				if (soap_in_PointerToint(soap, "result", &a->result, ""))
+				{	soap_flag_result = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__delete_USCOREinstanceResponse *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__delete_USCOREinstanceResponse, 0, sizeof(struct ns1__delete_USCOREinstanceResponse), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__find_USCOREinstances(struct soap *soap, const struct ns1__find_USCOREinstances *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->key, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->key);
+	soap_embedded(soap, &a->volume, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->volume);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__find_USCOREinstances(struct soap *soap, struct ns1__find_USCOREinstances *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_default_string(soap, &a->key);
+	soap_default_string(soap, &a->volume);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__find_USCOREinstances(struct soap *soap, const struct ns1__find_USCOREinstances *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__find_USCOREinstances);
+	if (soap_out_ns1__find_USCOREinstances(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__find_USCOREinstances(struct soap *soap, const char *tag, int id, const struct ns1__find_USCOREinstances *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__find_USCOREinstances), type);
+	soap_out_string(soap, "key", -1, &a->key, "");
+	soap_out_string(soap, "volume", -1, &a->volume, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__find_USCOREinstances * SOAP_FMAC4 soap_get_ns1__find_USCOREinstances(struct soap *soap, struct ns1__find_USCOREinstances *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__find_USCOREinstances(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__find_USCOREinstances * SOAP_FMAC4 soap_in_ns1__find_USCOREinstances(struct soap *soap, const char *tag, struct ns1__find_USCOREinstances *a, const char *type)
+{
+	short soap_flag_key = 1, soap_flag_volume = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__find_USCOREinstances *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__find_USCOREinstances, sizeof(struct ns1__find_USCOREinstances), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__find_USCOREinstances(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_key && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "key", &a->key, ""))
+				{	soap_flag_key = 0;
+					continue;
+				}
+			if (soap_flag_volume && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "volume", &a->volume, ""))
+				{	soap_flag_volume = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__find_USCOREinstances *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__find_USCOREinstances, 0, sizeof(struct ns1__find_USCOREinstances), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__find_USCOREinstancesResponse(struct soap *soap, const struct ns1__find_USCOREinstancesResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->result, SOAP_TYPE_PointerToArrayOfString);
+	soap_serialize_PointerToArrayOfString(soap, &a->result);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__find_USCOREinstancesResponse(struct soap *soap, struct ns1__find_USCOREinstancesResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	a->result = NULL;
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__find_USCOREinstancesResponse(struct soap *soap, const struct ns1__find_USCOREinstancesResponse *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__find_USCOREinstancesResponse);
+	if (soap_out_ns1__find_USCOREinstancesResponse(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__find_USCOREinstancesResponse(struct soap *soap, const char *tag, int id, const struct ns1__find_USCOREinstancesResponse *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__find_USCOREinstancesResponse), type);
+	if (a->result)
+		soap_element_result(soap, "result");
+	soap_out_PointerToArrayOfString(soap, "result", -1, &a->result, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__find_USCOREinstancesResponse * SOAP_FMAC4 soap_get_ns1__find_USCOREinstancesResponse(struct soap *soap, struct ns1__find_USCOREinstancesResponse *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__find_USCOREinstancesResponse(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__find_USCOREinstancesResponse * SOAP_FMAC4 soap_in_ns1__find_USCOREinstancesResponse(struct soap *soap, const char *tag, struct ns1__find_USCOREinstancesResponse *a, const char *type)
+{
+	short soap_flag_result = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__find_USCOREinstancesResponse *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__find_USCOREinstancesResponse, sizeof(struct ns1__find_USCOREinstancesResponse), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__find_USCOREinstancesResponse(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_result && soap->error == SOAP_TAG_MISMATCH)
+				if (soap_in_PointerToArrayOfString(soap, "result", &a->result, "xsd:string"))
+				{	soap_flag_result = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__find_USCOREinstancesResponse *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__find_USCOREinstancesResponse, 0, sizeof(struct ns1__find_USCOREinstancesResponse), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__find_USCOREobjects(struct soap *soap, const struct ns1__find_USCOREobjects *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->pattern, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->pattern);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__find_USCOREobjects(struct soap *soap, struct ns1__find_USCOREobjects *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_default_string(soap, &a->pattern);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__find_USCOREobjects(struct soap *soap, const struct ns1__find_USCOREobjects *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__find_USCOREobjects);
+	if (soap_out_ns1__find_USCOREobjects(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__find_USCOREobjects(struct soap *soap, const char *tag, int id, const struct ns1__find_USCOREobjects *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__find_USCOREobjects), type);
+	soap_out_string(soap, "pattern", -1, &a->pattern, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__find_USCOREobjects * SOAP_FMAC4 soap_get_ns1__find_USCOREobjects(struct soap *soap, struct ns1__find_USCOREobjects *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__find_USCOREobjects(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__find_USCOREobjects * SOAP_FMAC4 soap_in_ns1__find_USCOREobjects(struct soap *soap, const char *tag, struct ns1__find_USCOREobjects *a, const char *type)
+{
+	short soap_flag_pattern = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__find_USCOREobjects *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__find_USCOREobjects, sizeof(struct ns1__find_USCOREobjects), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__find_USCOREobjects(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_pattern && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "pattern", &a->pattern, ""))
+				{	soap_flag_pattern = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__find_USCOREobjects *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__find_USCOREobjects, 0, sizeof(struct ns1__find_USCOREobjects), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__find_USCOREobjectsResponse(struct soap *soap, const struct ns1__find_USCOREobjectsResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->result, SOAP_TYPE_PointerToArrayOfString);
+	soap_serialize_PointerToArrayOfString(soap, &a->result);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__find_USCOREobjectsResponse(struct soap *soap, struct ns1__find_USCOREobjectsResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	a->result = NULL;
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__find_USCOREobjectsResponse(struct soap *soap, const struct ns1__find_USCOREobjectsResponse *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__find_USCOREobjectsResponse);
+	if (soap_out_ns1__find_USCOREobjectsResponse(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__find_USCOREobjectsResponse(struct soap *soap, const char *tag, int id, const struct ns1__find_USCOREobjectsResponse *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__find_USCOREobjectsResponse), type);
+	if (a->result)
+		soap_element_result(soap, "result");
+	soap_out_PointerToArrayOfString(soap, "result", -1, &a->result, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__find_USCOREobjectsResponse * SOAP_FMAC4 soap_get_ns1__find_USCOREobjectsResponse(struct soap *soap, struct ns1__find_USCOREobjectsResponse *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__find_USCOREobjectsResponse(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__find_USCOREobjectsResponse * SOAP_FMAC4 soap_in_ns1__find_USCOREobjectsResponse(struct soap *soap, const char *tag, struct ns1__find_USCOREobjectsResponse *a, const char *type)
+{
+	short soap_flag_result = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__find_USCOREobjectsResponse *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__find_USCOREobjectsResponse, sizeof(struct ns1__find_USCOREobjectsResponse), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__find_USCOREobjectsResponse(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_result && soap->error == SOAP_TAG_MISMATCH)
+				if (soap_in_PointerToArrayOfString(soap, "result", &a->result, "xsd:string"))
+				{	soap_flag_result = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__find_USCOREobjectsResponse *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__find_USCOREobjectsResponse, 0, sizeof(struct ns1__find_USCOREobjectsResponse), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__unlock_USCOREobject(struct soap *soap, const struct ns1__unlock_USCOREobject *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->key, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->key);
+	soap_embedded(soap, &a->type, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->type);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__unlock_USCOREobject(struct soap *soap, struct ns1__unlock_USCOREobject *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_default_string(soap, &a->key);
+	soap_default_string(soap, &a->type);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__unlock_USCOREobject(struct soap *soap, const struct ns1__unlock_USCOREobject *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__unlock_USCOREobject);
+	if (soap_out_ns1__unlock_USCOREobject(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__unlock_USCOREobject(struct soap *soap, const char *tag, int id, const struct ns1__unlock_USCOREobject *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__unlock_USCOREobject), type);
+	soap_out_string(soap, "key", -1, &a->key, "");
+	soap_out_string(soap, "type", -1, &a->type, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__unlock_USCOREobject * SOAP_FMAC4 soap_get_ns1__unlock_USCOREobject(struct soap *soap, struct ns1__unlock_USCOREobject *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__unlock_USCOREobject(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__unlock_USCOREobject * SOAP_FMAC4 soap_in_ns1__unlock_USCOREobject(struct soap *soap, const char *tag, struct ns1__unlock_USCOREobject *a, const char *type)
+{
+	short soap_flag_key = 1, soap_flag_type = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__unlock_USCOREobject *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__unlock_USCOREobject, sizeof(struct ns1__unlock_USCOREobject), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__unlock_USCOREobject(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_key && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "key", &a->key, ""))
+				{	soap_flag_key = 0;
+					continue;
+				}
+			if (soap_flag_type && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "type", &a->type, ""))
+				{	soap_flag_type = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__unlock_USCOREobject *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__unlock_USCOREobject, 0, sizeof(struct ns1__unlock_USCOREobject), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__unlock_USCOREobjectResponse(struct soap *soap, const struct ns1__unlock_USCOREobjectResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->result, SOAP_TYPE_PointerToint);
+	soap_serialize_PointerToint(soap, &a->result);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__unlock_USCOREobjectResponse(struct soap *soap, struct ns1__unlock_USCOREobjectResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	a->result = NULL;
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__unlock_USCOREobjectResponse(struct soap *soap, const struct ns1__unlock_USCOREobjectResponse *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__unlock_USCOREobjectResponse);
+	if (soap_out_ns1__unlock_USCOREobjectResponse(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__unlock_USCOREobjectResponse(struct soap *soap, const char *tag, int id, const struct ns1__unlock_USCOREobjectResponse *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__unlock_USCOREobjectResponse), type);
+	if (a->result)
+		soap_element_result(soap, "result");
+	soap_out_PointerToint(soap, "result", -1, &a->result, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__unlock_USCOREobjectResponse * SOAP_FMAC4 soap_get_ns1__unlock_USCOREobjectResponse(struct soap *soap, struct ns1__unlock_USCOREobjectResponse *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__unlock_USCOREobjectResponse(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__unlock_USCOREobjectResponse * SOAP_FMAC4 soap_in_ns1__unlock_USCOREobjectResponse(struct soap *soap, const char *tag, struct ns1__unlock_USCOREobjectResponse *a, const char *type)
+{
+	short soap_flag_result = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__unlock_USCOREobjectResponse *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__unlock_USCOREobjectResponse, sizeof(struct ns1__unlock_USCOREobjectResponse), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__unlock_USCOREobjectResponse(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_result && soap->error == SOAP_TAG_MISMATCH)
+				if (soap_in_PointerToint(soap, "result", &a->result, ""))
+				{	soap_flag_result = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__unlock_USCOREobjectResponse *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__unlock_USCOREobjectResponse, 0, sizeof(struct ns1__unlock_USCOREobjectResponse), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__lock_USCOREobject(struct soap *soap, const struct ns1__lock_USCOREobject *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->key, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->key);
+	soap_embedded(soap, &a->type, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->type);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__lock_USCOREobject(struct soap *soap, struct ns1__lock_USCOREobject *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_default_string(soap, &a->key);
+	soap_default_string(soap, &a->type);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__lock_USCOREobject(struct soap *soap, const struct ns1__lock_USCOREobject *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__lock_USCOREobject);
+	if (soap_out_ns1__lock_USCOREobject(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__lock_USCOREobject(struct soap *soap, const char *tag, int id, const struct ns1__lock_USCOREobject *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__lock_USCOREobject), type);
+	soap_out_string(soap, "key", -1, &a->key, "");
+	soap_out_string(soap, "type", -1, &a->type, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__lock_USCOREobject * SOAP_FMAC4 soap_get_ns1__lock_USCOREobject(struct soap *soap, struct ns1__lock_USCOREobject *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__lock_USCOREobject(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__lock_USCOREobject * SOAP_FMAC4 soap_in_ns1__lock_USCOREobject(struct soap *soap, const char *tag, struct ns1__lock_USCOREobject *a, const char *type)
+{
+	short soap_flag_key = 1, soap_flag_type = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__lock_USCOREobject *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__lock_USCOREobject, sizeof(struct ns1__lock_USCOREobject), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__lock_USCOREobject(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_key && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "key", &a->key, ""))
+				{	soap_flag_key = 0;
+					continue;
+				}
+			if (soap_flag_type && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "type", &a->type, ""))
+				{	soap_flag_type = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__lock_USCOREobject *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__lock_USCOREobject, 0, sizeof(struct ns1__lock_USCOREobject), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__lock_USCOREobjectResponse(struct soap *soap, const struct ns1__lock_USCOREobjectResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->result, SOAP_TYPE_PointerToint);
+	soap_serialize_PointerToint(soap, &a->result);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__lock_USCOREobjectResponse(struct soap *soap, struct ns1__lock_USCOREobjectResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	a->result = NULL;
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__lock_USCOREobjectResponse(struct soap *soap, const struct ns1__lock_USCOREobjectResponse *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__lock_USCOREobjectResponse);
+	if (soap_out_ns1__lock_USCOREobjectResponse(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__lock_USCOREobjectResponse(struct soap *soap, const char *tag, int id, const struct ns1__lock_USCOREobjectResponse *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__lock_USCOREobjectResponse), type);
+	if (a->result)
+		soap_element_result(soap, "result");
+	soap_out_PointerToint(soap, "result", -1, &a->result, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__lock_USCOREobjectResponse * SOAP_FMAC4 soap_get_ns1__lock_USCOREobjectResponse(struct soap *soap, struct ns1__lock_USCOREobjectResponse *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__lock_USCOREobjectResponse(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__lock_USCOREobjectResponse * SOAP_FMAC4 soap_in_ns1__lock_USCOREobjectResponse(struct soap *soap, const char *tag, struct ns1__lock_USCOREobjectResponse *a, const char *type)
+{
+	short soap_flag_result = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__lock_USCOREobjectResponse *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__lock_USCOREobjectResponse, sizeof(struct ns1__lock_USCOREobjectResponse), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__lock_USCOREobjectResponse(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_result && soap->error == SOAP_TAG_MISMATCH)
+				if (soap_in_PointerToint(soap, "result", &a->result, ""))
+				{	soap_flag_result = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__lock_USCOREobjectResponse *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__lock_USCOREobjectResponse, 0, sizeof(struct ns1__lock_USCOREobjectResponse), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__replicate_USCOREobject(struct soap *soap, const struct ns1__replicate_USCOREobject *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->key, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->key);
+	soap_embedded(soap, &a->volume, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->volume);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__replicate_USCOREobject(struct soap *soap, struct ns1__replicate_USCOREobject *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_default_string(soap, &a->key);
+	soap_default_string(soap, &a->volume);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__replicate_USCOREobject(struct soap *soap, const struct ns1__replicate_USCOREobject *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__replicate_USCOREobject);
+	if (soap_out_ns1__replicate_USCOREobject(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__replicate_USCOREobject(struct soap *soap, const char *tag, int id, const struct ns1__replicate_USCOREobject *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__replicate_USCOREobject), type);
+	soap_out_string(soap, "key", -1, &a->key, "");
+	soap_out_string(soap, "volume", -1, &a->volume, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__replicate_USCOREobject * SOAP_FMAC4 soap_get_ns1__replicate_USCOREobject(struct soap *soap, struct ns1__replicate_USCOREobject *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__replicate_USCOREobject(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__replicate_USCOREobject * SOAP_FMAC4 soap_in_ns1__replicate_USCOREobject(struct soap *soap, const char *tag, struct ns1__replicate_USCOREobject *a, const char *type)
+{
+	short soap_flag_key = 1, soap_flag_volume = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__replicate_USCOREobject *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__replicate_USCOREobject, sizeof(struct ns1__replicate_USCOREobject), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__replicate_USCOREobject(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_key && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "key", &a->key, ""))
+				{	soap_flag_key = 0;
+					continue;
+				}
+			if (soap_flag_volume && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "volume", &a->volume, ""))
+				{	soap_flag_volume = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__replicate_USCOREobject *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__replicate_USCOREobject, 0, sizeof(struct ns1__replicate_USCOREobject), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__replicate_USCOREobjectResponse(struct soap *soap, const struct ns1__replicate_USCOREobjectResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->result, SOAP_TYPE_PointerTostring);
+	soap_serialize_PointerTostring(soap, &a->result);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__replicate_USCOREobjectResponse(struct soap *soap, struct ns1__replicate_USCOREobjectResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	a->result = NULL;
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__replicate_USCOREobjectResponse(struct soap *soap, const struct ns1__replicate_USCOREobjectResponse *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__replicate_USCOREobjectResponse);
+	if (soap_out_ns1__replicate_USCOREobjectResponse(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__replicate_USCOREobjectResponse(struct soap *soap, const char *tag, int id, const struct ns1__replicate_USCOREobjectResponse *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__replicate_USCOREobjectResponse), type);
+	if (a->result)
+		soap_element_result(soap, "result");
+	soap_out_PointerTostring(soap, "result", -1, &a->result, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__replicate_USCOREobjectResponse * SOAP_FMAC4 soap_get_ns1__replicate_USCOREobjectResponse(struct soap *soap, struct ns1__replicate_USCOREobjectResponse *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__replicate_USCOREobjectResponse(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__replicate_USCOREobjectResponse * SOAP_FMAC4 soap_in_ns1__replicate_USCOREobjectResponse(struct soap *soap, const char *tag, struct ns1__replicate_USCOREobjectResponse *a, const char *type)
+{
+	short soap_flag_result = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__replicate_USCOREobjectResponse *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__replicate_USCOREobjectResponse, sizeof(struct ns1__replicate_USCOREobjectResponse), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__replicate_USCOREobjectResponse(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_result && soap->error == SOAP_TAG_MISMATCH)
+				if (soap_in_PointerTostring(soap, "result", &a->result, ""))
+				{	soap_flag_result = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__replicate_USCOREobjectResponse *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__replicate_USCOREobjectResponse, 0, sizeof(struct ns1__replicate_USCOREobjectResponse), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__rename_USCOREobject_(struct soap *soap, const struct ns1__rename_USCOREobject_ *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->key, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->key);
+	soap_embedded(soap, &a->newkey, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->newkey);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__rename_USCOREobject_(struct soap *soap, struct ns1__rename_USCOREobject_ *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_default_string(soap, &a->key);
+	soap_default_string(soap, &a->newkey);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__rename_USCOREobject_(struct soap *soap, const struct ns1__rename_USCOREobject_ *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__rename_USCOREobject_);
+	if (soap_out_ns1__rename_USCOREobject_(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__rename_USCOREobject_(struct soap *soap, const char *tag, int id, const struct ns1__rename_USCOREobject_ *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__rename_USCOREobject_), type);
+	soap_out_string(soap, "key", -1, &a->key, "");
+	soap_out_string(soap, "newkey", -1, &a->newkey, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__rename_USCOREobject_ * SOAP_FMAC4 soap_get_ns1__rename_USCOREobject_(struct soap *soap, struct ns1__rename_USCOREobject_ *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__rename_USCOREobject_(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__rename_USCOREobject_ * SOAP_FMAC4 soap_in_ns1__rename_USCOREobject_(struct soap *soap, const char *tag, struct ns1__rename_USCOREobject_ *a, const char *type)
+{
+	short soap_flag_key = 1, soap_flag_newkey = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__rename_USCOREobject_ *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__rename_USCOREobject_, sizeof(struct ns1__rename_USCOREobject_), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__rename_USCOREobject_(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_key && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "key", &a->key, ""))
+				{	soap_flag_key = 0;
+					continue;
+				}
+			if (soap_flag_newkey && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "newkey", &a->newkey, ""))
+				{	soap_flag_newkey = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__rename_USCOREobject_ *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__rename_USCOREobject_, 0, sizeof(struct ns1__rename_USCOREobject_), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__rename_USCOREobject_Response(struct soap *soap, const struct ns1__rename_USCOREobject_Response *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->result, SOAP_TYPE_PointerTostring);
+	soap_serialize_PointerTostring(soap, &a->result);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__rename_USCOREobject_Response(struct soap *soap, struct ns1__rename_USCOREobject_Response *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	a->result = NULL;
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__rename_USCOREobject_Response(struct soap *soap, const struct ns1__rename_USCOREobject_Response *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__rename_USCOREobject_Response);
+	if (soap_out_ns1__rename_USCOREobject_Response(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__rename_USCOREobject_Response(struct soap *soap, const char *tag, int id, const struct ns1__rename_USCOREobject_Response *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__rename_USCOREobject_Response), type);
+	if (a->result)
+		soap_element_result(soap, "result");
+	soap_out_PointerTostring(soap, "result", -1, &a->result, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__rename_USCOREobject_Response * SOAP_FMAC4 soap_get_ns1__rename_USCOREobject_Response(struct soap *soap, struct ns1__rename_USCOREobject_Response *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__rename_USCOREobject_Response(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__rename_USCOREobject_Response * SOAP_FMAC4 soap_in_ns1__rename_USCOREobject_Response(struct soap *soap, const char *tag, struct ns1__rename_USCOREobject_Response *a, const char *type)
+{
+	short soap_flag_result = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__rename_USCOREobject_Response *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__rename_USCOREobject_Response, sizeof(struct ns1__rename_USCOREobject_Response), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__rename_USCOREobject_Response(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_result && soap->error == SOAP_TAG_MISMATCH)
+				if (soap_in_PointerTostring(soap, "result", &a->result, ""))
+				{	soap_flag_result = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__rename_USCOREobject_Response *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__rename_USCOREobject_Response, 0, sizeof(struct ns1__rename_USCOREobject_Response), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__rename_USCOREobject(struct soap *soap, const struct ns1__rename_USCOREobject *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->key, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->key);
+	soap_embedded(soap, &a->newkey, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->newkey);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__rename_USCOREobject(struct soap *soap, struct ns1__rename_USCOREobject *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_default_string(soap, &a->key);
+	soap_default_string(soap, &a->newkey);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__rename_USCOREobject(struct soap *soap, const struct ns1__rename_USCOREobject *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__rename_USCOREobject);
+	if (soap_out_ns1__rename_USCOREobject(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__rename_USCOREobject(struct soap *soap, const char *tag, int id, const struct ns1__rename_USCOREobject *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__rename_USCOREobject), type);
+	soap_out_string(soap, "key", -1, &a->key, "");
+	soap_out_string(soap, "newkey", -1, &a->newkey, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__rename_USCOREobject * SOAP_FMAC4 soap_get_ns1__rename_USCOREobject(struct soap *soap, struct ns1__rename_USCOREobject *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__rename_USCOREobject(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__rename_USCOREobject * SOAP_FMAC4 soap_in_ns1__rename_USCOREobject(struct soap *soap, const char *tag, struct ns1__rename_USCOREobject *a, const char *type)
+{
+	short soap_flag_key = 1, soap_flag_newkey = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__rename_USCOREobject *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__rename_USCOREobject, sizeof(struct ns1__rename_USCOREobject), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__rename_USCOREobject(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_key && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "key", &a->key, ""))
+				{	soap_flag_key = 0;
+					continue;
+				}
+			if (soap_flag_newkey && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "newkey", &a->newkey, ""))
+				{	soap_flag_newkey = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__rename_USCOREobject *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__rename_USCOREobject, 0, sizeof(struct ns1__rename_USCOREobject), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__rename_USCOREobjectResponse(struct soap *soap, const struct ns1__rename_USCOREobjectResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->result, SOAP_TYPE_PointerTostring);
+	soap_serialize_PointerTostring(soap, &a->result);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__rename_USCOREobjectResponse(struct soap *soap, struct ns1__rename_USCOREobjectResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	a->result = NULL;
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__rename_USCOREobjectResponse(struct soap *soap, const struct ns1__rename_USCOREobjectResponse *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__rename_USCOREobjectResponse);
+	if (soap_out_ns1__rename_USCOREobjectResponse(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__rename_USCOREobjectResponse(struct soap *soap, const char *tag, int id, const struct ns1__rename_USCOREobjectResponse *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__rename_USCOREobjectResponse), type);
+	if (a->result)
+		soap_element_result(soap, "result");
+	soap_out_PointerTostring(soap, "result", -1, &a->result, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__rename_USCOREobjectResponse * SOAP_FMAC4 soap_get_ns1__rename_USCOREobjectResponse(struct soap *soap, struct ns1__rename_USCOREobjectResponse *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__rename_USCOREobjectResponse(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__rename_USCOREobjectResponse * SOAP_FMAC4 soap_in_ns1__rename_USCOREobjectResponse(struct soap *soap, const char *tag, struct ns1__rename_USCOREobjectResponse *a, const char *type)
+{
+	short soap_flag_result = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__rename_USCOREobjectResponse *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__rename_USCOREobjectResponse, sizeof(struct ns1__rename_USCOREobjectResponse), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__rename_USCOREobjectResponse(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_result && soap->error == SOAP_TAG_MISMATCH)
+				if (soap_in_PointerTostring(soap, "result", &a->result, ""))
+				{	soap_flag_result = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__rename_USCOREobjectResponse *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__rename_USCOREobjectResponse, 0, sizeof(struct ns1__rename_USCOREobjectResponse), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__create_USCOREobject(struct soap *soap, const struct ns1__create_USCOREobject *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->key, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->key);
+	soap_embedded(soap, &a->volume, SOAP_TYPE_string);
+	soap_serialize_string(soap, &a->volume);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__create_USCOREobject(struct soap *soap, struct ns1__create_USCOREobject *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_default_string(soap, &a->key);
+	soap_default_string(soap, &a->volume);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__create_USCOREobject(struct soap *soap, const struct ns1__create_USCOREobject *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__create_USCOREobject);
+	if (soap_out_ns1__create_USCOREobject(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__create_USCOREobject(struct soap *soap, const char *tag, int id, const struct ns1__create_USCOREobject *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__create_USCOREobject), type);
+	soap_out_string(soap, "key", -1, &a->key, "");
+	soap_out_string(soap, "volume", -1, &a->volume, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__create_USCOREobject * SOAP_FMAC4 soap_get_ns1__create_USCOREobject(struct soap *soap, struct ns1__create_USCOREobject *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__create_USCOREobject(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__create_USCOREobject * SOAP_FMAC4 soap_in_ns1__create_USCOREobject(struct soap *soap, const char *tag, struct ns1__create_USCOREobject *a, const char *type)
+{
+	short soap_flag_key = 1, soap_flag_volume = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__create_USCOREobject *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__create_USCOREobject, sizeof(struct ns1__create_USCOREobject), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__create_USCOREobject(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_key && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "key", &a->key, ""))
+				{	soap_flag_key = 0;
+					continue;
+				}
+			if (soap_flag_volume && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
+				if (soap_in_string(soap, "volume", &a->volume, ""))
+				{	soap_flag_volume = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__create_USCOREobject *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__create_USCOREobject, 0, sizeof(struct ns1__create_USCOREobject), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__create_USCOREobjectResponse(struct soap *soap, const struct ns1__create_USCOREobjectResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	soap_embedded(soap, &a->result, SOAP_TYPE_PointerTostring);
+	soap_serialize_PointerTostring(soap, &a->result);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__create_USCOREobjectResponse(struct soap *soap, struct ns1__create_USCOREobjectResponse *a)
+{
+	(void)soap; (void)a; /* appease -Wall -Werror */
+	a->result = NULL;
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__create_USCOREobjectResponse(struct soap *soap, const struct ns1__create_USCOREobjectResponse *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_ns1__create_USCOREobjectResponse);
+	if (soap_out_ns1__create_USCOREobjectResponse(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__create_USCOREobjectResponse(struct soap *soap, const char *tag, int id, const struct ns1__create_USCOREobjectResponse *a, const char *type)
+{
+	soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__create_USCOREobjectResponse), type);
+	if (a->result)
+		soap_element_result(soap, "result");
+	soap_out_PointerTostring(soap, "result", -1, &a->result, "");
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ns1__create_USCOREobjectResponse * SOAP_FMAC4 soap_get_ns1__create_USCOREobjectResponse(struct soap *soap, struct ns1__create_USCOREobjectResponse *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ns1__create_USCOREobjectResponse(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__create_USCOREobjectResponse * SOAP_FMAC4 soap_in_ns1__create_USCOREobjectResponse(struct soap *soap, const char *tag, struct ns1__create_USCOREobjectResponse *a, const char *type)
+{
+	short soap_flag_result = 1;
+	if (soap_element_begin_in(soap, tag, 0))
+		return NULL;
+	if (*soap->type && soap_match_tag(soap, soap->type, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ns1__create_USCOREobjectResponse *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__create_USCOREobjectResponse, sizeof(struct ns1__create_USCOREobjectResponse), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ns1__create_USCOREobjectResponse(soap, a);
+	if (soap->body && !*soap->href)
+	{	for (;;)
+		{	soap->error = SOAP_TAG_MISMATCH;
+			if (soap_flag_result && soap->error == SOAP_TAG_MISMATCH)
+				if (soap_in_PointerTostring(soap, "result", &a->result, ""))
+				{	soap_flag_result = 0;
+					continue;
+				}
+			if (soap->error == SOAP_TAG_MISMATCH)
+				soap->error = soap_ignore_element(soap);
+			if (soap->error == SOAP_NO_TAG)
+				break;
+			if (soap->error)
+				return NULL;
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__create_USCOREobjectResponse *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ns1__create_USCOREobjectResponse, 0, sizeof(struct ns1__create_USCOREobjectResponse), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ArrayOfString(struct soap *soap, struct ArrayOfString const*a)
+{
+	int i;
+	if (a->__ptr && !soap_array_reference(soap, a, (struct soap_array*)&a->__ptr, 1, SOAP_TYPE_ArrayOfString))
+		for (i = 0; i < a->__size; i++)
+		{	soap_embedded(soap, a->__ptr + i, SOAP_TYPE_string);
+			soap_serialize_string(soap, a->__ptr + i);
+		}
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ArrayOfString(struct soap *soap, struct ArrayOfString *a)
+{
+	a->__size = 0;
+	a->__ptr = NULL;
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ArrayOfString(struct soap *soap, const struct ArrayOfString *a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, (struct soap_array*)&a->__ptr, 1, tag, SOAP_TYPE_ArrayOfString);
+	if (soap_out_ArrayOfString(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ArrayOfString(struct soap *soap, const char *tag, int id, const struct ArrayOfString *a, const char *type)
+{
+	int i, n = a->__size;
+	char *t = soap_putsize(soap, "xsd:string", n);
+	id = soap_element_id(soap, tag, id, a, (struct soap_array*)&a->__ptr, 1, type, SOAP_TYPE_ArrayOfString);
+	if (id < 0)
+		return soap->error;
+	soap_array_begin_out(soap, tag, id, t, NULL);
+	for (i = 0; i < n; i++)
+	{
+		soap->position = 1;
+		soap->positions[0] = i;
+		soap_out_string(soap, "item", -1, &a->__ptr[i], "");
+	}
+	soap->position = 0;
+	soap_element_end_out(soap, tag);
+	return SOAP_OK;
+}
+
+SOAP_FMAC3 struct ArrayOfString * SOAP_FMAC4 soap_get_ArrayOfString(struct soap *soap, struct ArrayOfString *p, const char *tag, const char *type)
+{
+	if ((p = soap_in_ArrayOfString(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ArrayOfString * SOAP_FMAC4 soap_in_ArrayOfString(struct soap *soap, const char *tag, struct ArrayOfString *a, const char *type)
+{	int i, j;
+	char **p;
+	if (soap_element_begin_in(soap, tag, 1))
+		return NULL;
+	if (soap_match_array(soap, type))
+	{	soap->error = SOAP_TYPE;
+		return NULL;
+	}
+	a = (struct ArrayOfString *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ArrayOfString, sizeof(struct ArrayOfString), 0, NULL, NULL, NULL);
+	if (!a)
+		return NULL;
+	if (soap->alloced)
+		soap_default_ArrayOfString(soap, a);
+	if (soap->body && !*soap->href)
+	{
+		a->__size = soap_getsize(soap->arraySize, soap->arrayOffset, &j);
+		if (a->__size >= 0)
+		{	a->__ptr = (char **)soap_malloc(soap, sizeof(char *) * a->__size);
+			for (i = 0; i < a->__size; i++)
+				a->__ptr[i] = NULL;
+			for (i = 0; i < a->__size; i++)
+			{	soap_peek_element(soap);
+				if (soap->position)
+				{	i = soap->positions[0]-j;
+					if (i < 0 || i >= a->__size)
+					{	soap->error = SOAP_IOB;
+						return NULL;
+					}
+				}
+				if (!soap_in_string(soap, NULL, a->__ptr + i, ""))
+				{	if (soap->error != SOAP_NO_TAG)
+						return NULL;
+					soap->error = SOAP_OK;
+					break;
+				}
+			}
+		}
+		else
+		{	soap_new_block(soap);
+			for (a->__size = 0; ; a->__size++)
+			{	p = (char **)soap_push_block(soap, sizeof(char *));
+				if (!p)
+					return NULL;
+				*p = NULL;
+				if (!soap_in_string(soap, NULL, p, ""))
+				{	if (soap->error != SOAP_NO_TAG)
+						return NULL;
+					soap->error = SOAP_OK;
+					break;
+				}
+			}
+			soap_pop_block(soap);
+			a->__ptr = (char **)soap_malloc(soap, soap->blist->size);
+			soap_save_block(soap, (char*)a->__ptr, 0);
+		}
+		if (soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	else
+	{	a = (struct ArrayOfString *)soap_id_forward(soap, soap->href, (void**)a, SOAP_TYPE_ArrayOfString, 0, sizeof(struct ArrayOfString), 0, NULL);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+#ifndef WITH_NOGLOBAL
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerToSOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail *const*a)
+{
+	if (!soap_reference(soap, *a, SOAP_TYPE_SOAP_ENV__Detail))
+		soap_serialize_SOAP_ENV__Detail(soap, *a);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToSOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail *const*a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_PointerToSOAP_ENV__Detail);
+	if (soap_out_PointerToSOAP_ENV__Detail(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToSOAP_ENV__Detail(struct soap *soap, const char *tag, int id, struct SOAP_ENV__Detail *const*a, const char *type)
+{
+	id = soap_element_id(soap, tag, id, *a, NULL, 0, type, SOAP_TYPE_SOAP_ENV__Detail);
+	if (id < 0)
+		return soap->error;
+	return soap_out_SOAP_ENV__Detail(soap, tag, id, *a, type);
+}
+
+SOAP_FMAC3 struct SOAP_ENV__Detail ** SOAP_FMAC4 soap_get_PointerToSOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail **p, const char *tag, const char *type)
+{
+	if ((p = soap_in_PointerToSOAP_ENV__Detail(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct SOAP_ENV__Detail ** SOAP_FMAC4 soap_in_PointerToSOAP_ENV__Detail(struct soap *soap, const char *tag, struct SOAP_ENV__Detail **a, const char *type)
+{
+	if (soap_element_begin_in(soap, tag, 1))
+		return NULL;
+	if (!a)
+		if (!(a = (struct SOAP_ENV__Detail **)soap_malloc(soap, sizeof(struct SOAP_ENV__Detail *))))
+			return NULL;
+	*a = NULL;
+	if (!soap->null && *soap->href != '#')
+	{	soap_revert(soap);
+		if (!(*a = soap_in_SOAP_ENV__Detail(soap, tag, *a, type)))
+			return NULL;
+	}
+	else
+	{	a = (struct SOAP_ENV__Detail **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE_SOAP_ENV__Detail, sizeof(struct SOAP_ENV__Detail), 0);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+#endif
+
+#ifndef WITH_NOGLOBAL
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerToSOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code *const*a)
+{
+	if (!soap_reference(soap, *a, SOAP_TYPE_SOAP_ENV__Code))
+		soap_serialize_SOAP_ENV__Code(soap, *a);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToSOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code *const*a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_PointerToSOAP_ENV__Code);
+	if (soap_out_PointerToSOAP_ENV__Code(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToSOAP_ENV__Code(struct soap *soap, const char *tag, int id, struct SOAP_ENV__Code *const*a, const char *type)
+{
+	id = soap_element_id(soap, tag, id, *a, NULL, 0, type, SOAP_TYPE_SOAP_ENV__Code);
+	if (id < 0)
+		return soap->error;
+	return soap_out_SOAP_ENV__Code(soap, tag, id, *a, type);
+}
+
+SOAP_FMAC3 struct SOAP_ENV__Code ** SOAP_FMAC4 soap_get_PointerToSOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code **p, const char *tag, const char *type)
+{
+	if ((p = soap_in_PointerToSOAP_ENV__Code(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct SOAP_ENV__Code ** SOAP_FMAC4 soap_in_PointerToSOAP_ENV__Code(struct soap *soap, const char *tag, struct SOAP_ENV__Code **a, const char *type)
+{
+	if (soap_element_begin_in(soap, tag, 1))
+		return NULL;
+	if (!a)
+		if (!(a = (struct SOAP_ENV__Code **)soap_malloc(soap, sizeof(struct SOAP_ENV__Code *))))
+			return NULL;
+	*a = NULL;
+	if (!soap->null && *soap->href != '#')
+	{	soap_revert(soap);
+		if (!(*a = soap_in_SOAP_ENV__Code(soap, tag, *a, type)))
+			return NULL;
+	}
+	else
+	{	a = (struct SOAP_ENV__Code **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE_SOAP_ENV__Code, sizeof(struct SOAP_ENV__Code), 0);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+#endif
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerTons1__stat_USCOREobjectResponse(struct soap *soap, struct ns1__stat_USCOREobjectResponse *const*a)
+{
+	if (!soap_reference(soap, *a, SOAP_TYPE_ns1__stat_USCOREobjectResponse))
+		soap_serialize_ns1__stat_USCOREobjectResponse(soap, *a);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerTons1__stat_USCOREobjectResponse(struct soap *soap, struct ns1__stat_USCOREobjectResponse *const*a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_PointerTons1__stat_USCOREobjectResponse);
+	if (soap_out_PointerTons1__stat_USCOREobjectResponse(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerTons1__stat_USCOREobjectResponse(struct soap *soap, const char *tag, int id, struct ns1__stat_USCOREobjectResponse *const*a, const char *type)
+{
+	id = soap_element_id(soap, tag, id, *a, NULL, 0, type, SOAP_TYPE_ns1__stat_USCOREobjectResponse);
+	if (id < 0)
+		return soap->error;
+	return soap_out_ns1__stat_USCOREobjectResponse(soap, tag, id, *a, type);
+}
+
+SOAP_FMAC3 struct ns1__stat_USCOREobjectResponse ** SOAP_FMAC4 soap_get_PointerTons1__stat_USCOREobjectResponse(struct soap *soap, struct ns1__stat_USCOREobjectResponse **p, const char *tag, const char *type)
+{
+	if ((p = soap_in_PointerTons1__stat_USCOREobjectResponse(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__stat_USCOREobjectResponse ** SOAP_FMAC4 soap_in_PointerTons1__stat_USCOREobjectResponse(struct soap *soap, const char *tag, struct ns1__stat_USCOREobjectResponse **a, const char *type)
+{
+	if (soap_element_begin_in(soap, tag, 1))
+		return NULL;
+	if (!a)
+		if (!(a = (struct ns1__stat_USCOREobjectResponse **)soap_malloc(soap, sizeof(struct ns1__stat_USCOREobjectResponse *))))
+			return NULL;
+	*a = NULL;
+	if (!soap->null && *soap->href != '#')
+	{	soap_revert(soap);
+		if (!(*a = soap_in_ns1__stat_USCOREobjectResponse(soap, tag, *a, type)))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__stat_USCOREobjectResponse **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE_ns1__stat_USCOREobjectResponse, sizeof(struct ns1__stat_USCOREobjectResponse), 0);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerTons1__find_USCOREinstancesResponse(struct soap *soap, struct ns1__find_USCOREinstancesResponse *const*a)
+{
+	if (!soap_reference(soap, *a, SOAP_TYPE_ns1__find_USCOREinstancesResponse))
+		soap_serialize_ns1__find_USCOREinstancesResponse(soap, *a);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerTons1__find_USCOREinstancesResponse(struct soap *soap, struct ns1__find_USCOREinstancesResponse *const*a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_PointerTons1__find_USCOREinstancesResponse);
+	if (soap_out_PointerTons1__find_USCOREinstancesResponse(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerTons1__find_USCOREinstancesResponse(struct soap *soap, const char *tag, int id, struct ns1__find_USCOREinstancesResponse *const*a, const char *type)
+{
+	id = soap_element_id(soap, tag, id, *a, NULL, 0, type, SOAP_TYPE_ns1__find_USCOREinstancesResponse);
+	if (id < 0)
+		return soap->error;
+	return soap_out_ns1__find_USCOREinstancesResponse(soap, tag, id, *a, type);
+}
+
+SOAP_FMAC3 struct ns1__find_USCOREinstancesResponse ** SOAP_FMAC4 soap_get_PointerTons1__find_USCOREinstancesResponse(struct soap *soap, struct ns1__find_USCOREinstancesResponse **p, const char *tag, const char *type)
+{
+	if ((p = soap_in_PointerTons1__find_USCOREinstancesResponse(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__find_USCOREinstancesResponse ** SOAP_FMAC4 soap_in_PointerTons1__find_USCOREinstancesResponse(struct soap *soap, const char *tag, struct ns1__find_USCOREinstancesResponse **a, const char *type)
+{
+	if (soap_element_begin_in(soap, tag, 1))
+		return NULL;
+	if (!a)
+		if (!(a = (struct ns1__find_USCOREinstancesResponse **)soap_malloc(soap, sizeof(struct ns1__find_USCOREinstancesResponse *))))
+			return NULL;
+	*a = NULL;
+	if (!soap->null && *soap->href != '#')
+	{	soap_revert(soap);
+		if (!(*a = soap_in_ns1__find_USCOREinstancesResponse(soap, tag, *a, type)))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__find_USCOREinstancesResponse **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE_ns1__find_USCOREinstancesResponse, sizeof(struct ns1__find_USCOREinstancesResponse), 0);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerTons1__find_USCOREobjectsResponse(struct soap *soap, struct ns1__find_USCOREobjectsResponse *const*a)
+{
+	if (!soap_reference(soap, *a, SOAP_TYPE_ns1__find_USCOREobjectsResponse))
+		soap_serialize_ns1__find_USCOREobjectsResponse(soap, *a);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerTons1__find_USCOREobjectsResponse(struct soap *soap, struct ns1__find_USCOREobjectsResponse *const*a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_PointerTons1__find_USCOREobjectsResponse);
+	if (soap_out_PointerTons1__find_USCOREobjectsResponse(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerTons1__find_USCOREobjectsResponse(struct soap *soap, const char *tag, int id, struct ns1__find_USCOREobjectsResponse *const*a, const char *type)
+{
+	id = soap_element_id(soap, tag, id, *a, NULL, 0, type, SOAP_TYPE_ns1__find_USCOREobjectsResponse);
+	if (id < 0)
+		return soap->error;
+	return soap_out_ns1__find_USCOREobjectsResponse(soap, tag, id, *a, type);
+}
+
+SOAP_FMAC3 struct ns1__find_USCOREobjectsResponse ** SOAP_FMAC4 soap_get_PointerTons1__find_USCOREobjectsResponse(struct soap *soap, struct ns1__find_USCOREobjectsResponse **p, const char *tag, const char *type)
+{
+	if ((p = soap_in_PointerTons1__find_USCOREobjectsResponse(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ns1__find_USCOREobjectsResponse ** SOAP_FMAC4 soap_in_PointerTons1__find_USCOREobjectsResponse(struct soap *soap, const char *tag, struct ns1__find_USCOREobjectsResponse **a, const char *type)
+{
+	if (soap_element_begin_in(soap, tag, 1))
+		return NULL;
+	if (!a)
+		if (!(a = (struct ns1__find_USCOREobjectsResponse **)soap_malloc(soap, sizeof(struct ns1__find_USCOREobjectsResponse *))))
+			return NULL;
+	*a = NULL;
+	if (!soap->null && *soap->href != '#')
+	{	soap_revert(soap);
+		if (!(*a = soap_in_ns1__find_USCOREobjectsResponse(soap, tag, *a, type)))
+			return NULL;
+	}
+	else
+	{	a = (struct ns1__find_USCOREobjectsResponse **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE_ns1__find_USCOREobjectsResponse, sizeof(struct ns1__find_USCOREobjectsResponse), 0);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerToArrayOfString(struct soap *soap, struct ArrayOfString *const*a)
+{
+	if (*a)
+		soap_serialize_ArrayOfString(soap, *a);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToArrayOfString(struct soap *soap, struct ArrayOfString *const*a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_PointerToArrayOfString);
+	if (soap_out_PointerToArrayOfString(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToArrayOfString(struct soap *soap, const char *tag, int id, struct ArrayOfString *const*a, const char *type)
+{
+	id = soap_element_id(soap, tag, id, *a, (struct soap_array*)&(*a)->__ptr, 1, type, SOAP_TYPE_ArrayOfString);
+	if (id < 0)
+		return soap->error;
+	return soap_out_ArrayOfString(soap, tag, id, *a, type);
+}
+
+SOAP_FMAC3 struct ArrayOfString ** SOAP_FMAC4 soap_get_PointerToArrayOfString(struct soap *soap, struct ArrayOfString **p, const char *tag, const char *type)
+{
+	if ((p = soap_in_PointerToArrayOfString(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 struct ArrayOfString ** SOAP_FMAC4 soap_in_PointerToArrayOfString(struct soap *soap, const char *tag, struct ArrayOfString **a, const char *type)
+{
+	if (soap_element_begin_in(soap, tag, 1))
+		return NULL;
+	if (!a)
+		if (!(a = (struct ArrayOfString **)soap_malloc(soap, sizeof(struct ArrayOfString *))))
+			return NULL;
+	*a = NULL;
+	if (!soap->null && *soap->href != '#')
+	{	soap_revert(soap);
+		if (!(*a = soap_in_ArrayOfString(soap, tag, *a, type)))
+			return NULL;
+	}
+	else
+	{	a = (struct ArrayOfString **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE_ArrayOfString, sizeof(struct ArrayOfString), 0);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerToint(struct soap *soap, int *const*a)
+{
+	soap_reference(soap, *a, SOAP_TYPE_int);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToint(struct soap *soap, int *const*a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_PointerToint);
+	if (soap_out_PointerToint(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToint(struct soap *soap, const char *tag, int id, int *const*a, const char *type)
+{
+	id = soap_element_id(soap, tag, id, *a, NULL, 0, type, SOAP_TYPE_int);
+	if (id < 0)
+		return soap->error;
+	return soap_out_int(soap, tag, id, *a, type);
+}
+
+SOAP_FMAC3 int ** SOAP_FMAC4 soap_get_PointerToint(struct soap *soap, int **p, const char *tag, const char *type)
+{
+	if ((p = soap_in_PointerToint(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 int ** SOAP_FMAC4 soap_in_PointerToint(struct soap *soap, const char *tag, int **a, const char *type)
+{
+	if (soap_element_begin_in(soap, tag, 1))
+		return NULL;
+	if (!a)
+		if (!(a = (int **)soap_malloc(soap, sizeof(int *))))
+			return NULL;
+	*a = NULL;
+	if (!soap->null && *soap->href != '#')
+	{	soap_revert(soap);
+		if (!(*a = soap_in_int(soap, tag, *a, type)))
+			return NULL;
+	}
+	else
+	{	a = (int **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE_int, sizeof(int), 0);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerTostring(struct soap *soap, char **const*a)
+{
+	if (!soap_reference(soap, *a, SOAP_TYPE_string))
+		soap_serialize_string(soap, *a);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerTostring(struct soap *soap, char **const*a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_PointerTostring);
+	if (soap_out_PointerTostring(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerTostring(struct soap *soap, const char *tag, int id, char **const*a, const char *type)
+{
+	id = soap_element_id(soap, tag, id, *a, NULL, 0, type, SOAP_TYPE_string);
+	if (id < 0)
+		return soap->error;
+	return soap_out_string(soap, tag, id, *a, type);
+}
+
+SOAP_FMAC3 char *** SOAP_FMAC4 soap_get_PointerTostring(struct soap *soap, char ***p, const char *tag, const char *type)
+{
+	if ((p = soap_in_PointerTostring(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 char *** SOAP_FMAC4 soap_in_PointerTostring(struct soap *soap, const char *tag, char ***a, const char *type)
+{
+	if (soap_element_begin_in(soap, tag, 1))
+		return NULL;
+	if (!a)
+		if (!(a = (char ***)soap_malloc(soap, sizeof(char **))))
+			return NULL;
+	*a = NULL;
+	if (!soap->null && *soap->href != '#')
+	{	soap_revert(soap);
+		if (!(*a = soap_in_string(soap, tag, *a, type)))
+			return NULL;
+	}
+	else
+	{	a = (char ***)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE_string, sizeof(char *), 1);
+		if (soap->body && soap_element_end_in(soap, tag))
+			return NULL;
+	}
+	return a;
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENC__arrayType(struct soap *soap, char **a)
+{	soap_default_string(soap, a);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENC__arrayType(struct soap *soap, char *const*a)
+{	soap_serialize_string(soap, a);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENC__arrayType(struct soap *soap, char *const*a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_SOAP_ENC__arrayType);
+	if (soap_out_SOAP_ENC__arrayType(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENC__arrayType(struct soap *soap, const char *tag, int id, char *const*a, const char *type)
+{
+	return soap_outstring(soap, tag, id, a, type, SOAP_TYPE_SOAP_ENC__arrayType);
+}
+
+SOAP_FMAC3 char ** SOAP_FMAC4 soap_get_SOAP_ENC__arrayType(struct soap *soap, char **p, const char *tag, const char *type)
+{
+	if ((p = soap_in_SOAP_ENC__arrayType(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 char * * SOAP_FMAC4 soap_in_SOAP_ENC__arrayType(struct soap *soap, const char *tag, char **a, const char *type)
+{
+	return soap_instring(soap, tag, a, type, SOAP_TYPE_SOAP_ENC__arrayType, 1, 0, -1);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default__QName(struct soap *soap, char **a)
+{	soap_default_string(soap, a);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize__QName(struct soap *soap, char *const*a)
+{	soap_serialize_string(soap, a);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put__QName(struct soap *soap, char *const*a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE__QName);
+	if (soap_out__QName(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out__QName(struct soap *soap, const char *tag, int id, char *const*a, const char *type)
+{
+	return soap_outstring(soap, tag, id, a, type, SOAP_TYPE__QName);
+}
+
+SOAP_FMAC3 char ** SOAP_FMAC4 soap_get__QName(struct soap *soap, char **p, const char *tag, const char *type)
+{
+	if ((p = soap_in__QName(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 char * * SOAP_FMAC4 soap_in__QName(struct soap *soap, const char *tag, char **a, const char *type)
+{
+	return soap_instring(soap, tag, a, type, SOAP_TYPE__QName, 2, 0, -1);
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_string(struct soap *soap, char **a)
+{
+(void)soap; /* appease -Wall -Werror */
+#ifdef SOAP_DEFAULT_string
+	*a = SOAP_DEFAULT_string;
+#else
+	*a = (char *)0;
+#endif
+}
+
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_string(struct soap *soap, char *const*a)
+{
+	soap_reference(soap, *a, SOAP_TYPE_string);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_string(struct soap *soap, char *const*a, const char *tag, const char *type)
+{
+	register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_string);
+	if (soap_out_string(soap, tag, id, a, type))
+		return soap->error;
+	return soap_putindependent(soap);
+}
+
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_string(struct soap *soap, const char *tag, int id, char *const*a, const char *type)
+{
+	return soap_outstring(soap, tag, id, a, type, SOAP_TYPE_string);
+}
+
+SOAP_FMAC3 char ** SOAP_FMAC4 soap_get_string(struct soap *soap, char **p, const char *tag, const char *type)
+{
+	if ((p = soap_in_string(soap, tag, p, type)))
+		soap_getindependent(soap);
+	return p;
+}
+
+SOAP_FMAC3 char * * SOAP_FMAC4 soap_in_string(struct soap *soap, const char *tag, char **a, const char *type)
+{
+	return soap_instring(soap, tag, a, type, SOAP_TYPE_string, 1, 0, -1);
+}
+
+SOAP_END_NAMESPACE(soap)
+
+#ifdef __cplusplus
+}
+#endif
+
+/* End of soapC.c */
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapClient.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapClient.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapClient.c	(revision 21994)
@@ -0,0 +1,561 @@
+/* soapClient.c
+   Generated by gSOAP 2.7.2 from src/nebulous.h
+   Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc. All Rights Reserved.
+   This part of the software is released under one of the following licenses:
+   GPL, the gSOAP public license, or Genivia's license for commercial use.
+*/
+#include "soapH.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SOAP_BEGIN_NAMESPACE(soap)
+
+SOAP_SOURCE_STAMP("@(#) soapClient.c ver 2.7.2 2007-05-01 02:53:36 GMT")
+
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__create_USCOREobject(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *key, char *volume, char **result)
+{	struct ns1__create_USCOREobject soap_tmp_ns1__create_USCOREobject;
+	struct ns1__create_USCOREobjectResponse *soap_tmp_ns1__create_USCOREobjectResponse;
+	if (!soap_endpoint)
+		soap_endpoint = "http://localhost:80/nebulous";
+	if (!soap_action)
+		soap_action = "urn:Nebulous/Server/SOAP#create_object";
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	soap_tmp_ns1__create_USCOREobject.key = key;
+	soap_tmp_ns1__create_USCOREobject.volume = volume;
+	soap_begin(soap);
+	soap_serializeheader(soap);
+	soap_serialize_ns1__create_USCOREobject(soap, &soap_tmp_ns1__create_USCOREobject);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__create_USCOREobject(soap, &soap_tmp_ns1__create_USCOREobject, "ns1:create_object", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	}
+	if (soap_connect(soap, soap_endpoint, soap_action)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__create_USCOREobject(soap, &soap_tmp_ns1__create_USCOREobject, "ns1:create_object", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap_closesock(soap);
+	*result = NULL;
+	if (soap_begin_recv(soap)
+	 || soap_envelope_begin_in(soap)
+	 || soap_recv_header(soap)
+	 || soap_body_begin_in(soap))
+		return soap_closesock(soap);
+	soap_tmp_ns1__create_USCOREobjectResponse = soap_get_ns1__create_USCOREobjectResponse(soap, NULL, "ns1:create_objectResponse", "");
+	if (soap->error)
+	{	if (soap->error == SOAP_TAG_MISMATCH && soap->level == 2)
+			return soap_recv_fault(soap);
+		return soap_closesock(soap);
+	}
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap_closesock(soap);
+	if (result && soap_tmp_ns1__create_USCOREobjectResponse->result)
+		*result = *soap_tmp_ns1__create_USCOREobjectResponse->result;
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__rename_USCOREobject(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *key, char *newkey, char **result)
+{	struct ns1__rename_USCOREobject soap_tmp_ns1__rename_USCOREobject;
+	struct ns1__rename_USCOREobjectResponse *soap_tmp_ns1__rename_USCOREobjectResponse;
+	if (!soap_endpoint)
+		soap_endpoint = "http://localhost:80/nebulous";
+	if (!soap_action)
+		soap_action = "urn:Nebulous/Server/SOAP#create_object";
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	soap_tmp_ns1__rename_USCOREobject.key = key;
+	soap_tmp_ns1__rename_USCOREobject.newkey = newkey;
+	soap_begin(soap);
+	soap_serializeheader(soap);
+	soap_serialize_ns1__rename_USCOREobject(soap, &soap_tmp_ns1__rename_USCOREobject);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__rename_USCOREobject(soap, &soap_tmp_ns1__rename_USCOREobject, "ns1:rename_object", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	}
+	if (soap_connect(soap, soap_endpoint, soap_action)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__rename_USCOREobject(soap, &soap_tmp_ns1__rename_USCOREobject, "ns1:rename_object", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap_closesock(soap);
+	*result = NULL;
+	if (soap_begin_recv(soap)
+	 || soap_envelope_begin_in(soap)
+	 || soap_recv_header(soap)
+	 || soap_body_begin_in(soap))
+		return soap_closesock(soap);
+	soap_tmp_ns1__rename_USCOREobjectResponse = soap_get_ns1__rename_USCOREobjectResponse(soap, NULL, "ns1:rename_objectResponse", "");
+	if (soap->error)
+	{	if (soap->error == SOAP_TAG_MISMATCH && soap->level == 2)
+			return soap_recv_fault(soap);
+		return soap_closesock(soap);
+	}
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap_closesock(soap);
+	if (result && soap_tmp_ns1__rename_USCOREobjectResponse->result)
+		*result = *soap_tmp_ns1__rename_USCOREobjectResponse->result;
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__rename_USCOREobject_(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *key, char *newkey, char **result)
+{	struct ns1__rename_USCOREobject_ soap_tmp_ns1__rename_USCOREobject_;
+	struct ns1__rename_USCOREobject_Response *soap_tmp_ns1__rename_USCOREobject_Response;
+	if (!soap_endpoint)
+		soap_endpoint = "http://localhost:80/nebulous";
+	if (!soap_action)
+		soap_action = "urn:Nebulous/Server/SOAP#create_object";
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	soap_tmp_ns1__rename_USCOREobject_.key = key;
+	soap_tmp_ns1__rename_USCOREobject_.newkey = newkey;
+	soap_begin(soap);
+	soap_serializeheader(soap);
+	soap_serialize_ns1__rename_USCOREobject_(soap, &soap_tmp_ns1__rename_USCOREobject_);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__rename_USCOREobject_(soap, &soap_tmp_ns1__rename_USCOREobject_, "ns1:rename_object", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	}
+	if (soap_connect(soap, soap_endpoint, soap_action)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__rename_USCOREobject_(soap, &soap_tmp_ns1__rename_USCOREobject_, "ns1:rename_object", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap_closesock(soap);
+	*result = NULL;
+	if (soap_begin_recv(soap)
+	 || soap_envelope_begin_in(soap)
+	 || soap_recv_header(soap)
+	 || soap_body_begin_in(soap))
+		return soap_closesock(soap);
+	soap_tmp_ns1__rename_USCOREobject_Response = soap_get_ns1__rename_USCOREobject_Response(soap, NULL, "ns1:rename_object-Response", "");
+	if (soap->error)
+	{	if (soap->error == SOAP_TAG_MISMATCH && soap->level == 2)
+			return soap_recv_fault(soap);
+		return soap_closesock(soap);
+	}
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap_closesock(soap);
+	if (result && soap_tmp_ns1__rename_USCOREobject_Response->result)
+		*result = *soap_tmp_ns1__rename_USCOREobject_Response->result;
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__replicate_USCOREobject(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *key, char *volume, char **result)
+{	struct ns1__replicate_USCOREobject soap_tmp_ns1__replicate_USCOREobject;
+	struct ns1__replicate_USCOREobjectResponse *soap_tmp_ns1__replicate_USCOREobjectResponse;
+	if (!soap_endpoint)
+		soap_endpoint = "http://localhost:80/nebulous";
+	if (!soap_action)
+		soap_action = "urn:Nebulous/Server/SOAP#replicate_object";
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	soap_tmp_ns1__replicate_USCOREobject.key = key;
+	soap_tmp_ns1__replicate_USCOREobject.volume = volume;
+	soap_begin(soap);
+	soap_serializeheader(soap);
+	soap_serialize_ns1__replicate_USCOREobject(soap, &soap_tmp_ns1__replicate_USCOREobject);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__replicate_USCOREobject(soap, &soap_tmp_ns1__replicate_USCOREobject, "ns1:replicate_object", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	}
+	if (soap_connect(soap, soap_endpoint, soap_action)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__replicate_USCOREobject(soap, &soap_tmp_ns1__replicate_USCOREobject, "ns1:replicate_object", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap_closesock(soap);
+	*result = NULL;
+	if (soap_begin_recv(soap)
+	 || soap_envelope_begin_in(soap)
+	 || soap_recv_header(soap)
+	 || soap_body_begin_in(soap))
+		return soap_closesock(soap);
+	soap_tmp_ns1__replicate_USCOREobjectResponse = soap_get_ns1__replicate_USCOREobjectResponse(soap, NULL, "ns1:replicate_objectResponse", "");
+	if (soap->error)
+	{	if (soap->error == SOAP_TAG_MISMATCH && soap->level == 2)
+			return soap_recv_fault(soap);
+		return soap_closesock(soap);
+	}
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap_closesock(soap);
+	if (result && soap_tmp_ns1__replicate_USCOREobjectResponse->result)
+		*result = *soap_tmp_ns1__replicate_USCOREobjectResponse->result;
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__lock_USCOREobject(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *key, char *type, int *result)
+{	struct ns1__lock_USCOREobject soap_tmp_ns1__lock_USCOREobject;
+	struct ns1__lock_USCOREobjectResponse *soap_tmp_ns1__lock_USCOREobjectResponse;
+	if (!soap_endpoint)
+		soap_endpoint = "http://localhost:80/nebulous";
+	if (!soap_action)
+		soap_action = "urn:Nebulous/Server/SOAP#lock_object";
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	soap_tmp_ns1__lock_USCOREobject.key = key;
+	soap_tmp_ns1__lock_USCOREobject.type = type;
+	soap_begin(soap);
+	soap_serializeheader(soap);
+	soap_serialize_ns1__lock_USCOREobject(soap, &soap_tmp_ns1__lock_USCOREobject);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__lock_USCOREobject(soap, &soap_tmp_ns1__lock_USCOREobject, "ns1:lock_object", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	}
+	if (soap_connect(soap, soap_endpoint, soap_action)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__lock_USCOREobject(soap, &soap_tmp_ns1__lock_USCOREobject, "ns1:lock_object", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap_closesock(soap);
+	soap_default_int(soap, result);
+	if (soap_begin_recv(soap)
+	 || soap_envelope_begin_in(soap)
+	 || soap_recv_header(soap)
+	 || soap_body_begin_in(soap))
+		return soap_closesock(soap);
+	soap_tmp_ns1__lock_USCOREobjectResponse = soap_get_ns1__lock_USCOREobjectResponse(soap, NULL, "ns1:lock_objectResponse", "");
+	if (soap->error)
+	{	if (soap->error == SOAP_TAG_MISMATCH && soap->level == 2)
+			return soap_recv_fault(soap);
+		return soap_closesock(soap);
+	}
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap_closesock(soap);
+	if (result && soap_tmp_ns1__lock_USCOREobjectResponse->result)
+		*result = *soap_tmp_ns1__lock_USCOREobjectResponse->result;
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__unlock_USCOREobject(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *key, char *type, int *result)
+{	struct ns1__unlock_USCOREobject soap_tmp_ns1__unlock_USCOREobject;
+	struct ns1__unlock_USCOREobjectResponse *soap_tmp_ns1__unlock_USCOREobjectResponse;
+	if (!soap_endpoint)
+		soap_endpoint = "http://localhost:80/nebulous";
+	if (!soap_action)
+		soap_action = "urn:Nebulous/Server/SOAP#unlock_object";
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	soap_tmp_ns1__unlock_USCOREobject.key = key;
+	soap_tmp_ns1__unlock_USCOREobject.type = type;
+	soap_begin(soap);
+	soap_serializeheader(soap);
+	soap_serialize_ns1__unlock_USCOREobject(soap, &soap_tmp_ns1__unlock_USCOREobject);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__unlock_USCOREobject(soap, &soap_tmp_ns1__unlock_USCOREobject, "ns1:unlock_object", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	}
+	if (soap_connect(soap, soap_endpoint, soap_action)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__unlock_USCOREobject(soap, &soap_tmp_ns1__unlock_USCOREobject, "ns1:unlock_object", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap_closesock(soap);
+	soap_default_int(soap, result);
+	if (soap_begin_recv(soap)
+	 || soap_envelope_begin_in(soap)
+	 || soap_recv_header(soap)
+	 || soap_body_begin_in(soap))
+		return soap_closesock(soap);
+	soap_tmp_ns1__unlock_USCOREobjectResponse = soap_get_ns1__unlock_USCOREobjectResponse(soap, NULL, "ns1:unlock_objectResponse", "");
+	if (soap->error)
+	{	if (soap->error == SOAP_TAG_MISMATCH && soap->level == 2)
+			return soap_recv_fault(soap);
+		return soap_closesock(soap);
+	}
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap_closesock(soap);
+	if (result && soap_tmp_ns1__unlock_USCOREobjectResponse->result)
+		*result = *soap_tmp_ns1__unlock_USCOREobjectResponse->result;
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__find_USCOREobjects(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *pattern, struct ns1__find_USCOREobjectsResponse *param_1)
+{	struct ns1__find_USCOREobjects soap_tmp_ns1__find_USCOREobjects;
+	if (!soap_endpoint)
+		soap_endpoint = "http://localhost:80/nebulous";
+	if (!soap_action)
+		soap_action = "urn:Nebulous/Server/SOAP#find_objects";
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	soap_tmp_ns1__find_USCOREobjects.pattern = pattern;
+	soap_begin(soap);
+	soap_serializeheader(soap);
+	soap_serialize_ns1__find_USCOREobjects(soap, &soap_tmp_ns1__find_USCOREobjects);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__find_USCOREobjects(soap, &soap_tmp_ns1__find_USCOREobjects, "ns1:find_objects", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	}
+	if (soap_connect(soap, soap_endpoint, soap_action)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__find_USCOREobjects(soap, &soap_tmp_ns1__find_USCOREobjects, "ns1:find_objects", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap_closesock(soap);
+	soap_default_ns1__find_USCOREobjectsResponse(soap, param_1);
+	if (soap_begin_recv(soap)
+	 || soap_envelope_begin_in(soap)
+	 || soap_recv_header(soap)
+	 || soap_body_begin_in(soap))
+		return soap_closesock(soap);
+	soap_get_ns1__find_USCOREobjectsResponse(soap, param_1, "ns1:find_objectsResponse", "");
+	if (soap->error)
+	{	if (soap->error == SOAP_TAG_MISMATCH && soap->level == 2)
+			return soap_recv_fault(soap);
+		return soap_closesock(soap);
+	}
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap_closesock(soap);
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__find_USCOREinstances(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *key, char *volume, struct ns1__find_USCOREinstancesResponse *param_2)
+{	struct ns1__find_USCOREinstances soap_tmp_ns1__find_USCOREinstances;
+	if (!soap_endpoint)
+		soap_endpoint = "http://localhost:80/nebulous";
+	if (!soap_action)
+		soap_action = "urn:Nebulous/Server/SOAP#find_instances";
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	soap_tmp_ns1__find_USCOREinstances.key = key;
+	soap_tmp_ns1__find_USCOREinstances.volume = volume;
+	soap_begin(soap);
+	soap_serializeheader(soap);
+	soap_serialize_ns1__find_USCOREinstances(soap, &soap_tmp_ns1__find_USCOREinstances);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__find_USCOREinstances(soap, &soap_tmp_ns1__find_USCOREinstances, "ns1:find_instances", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	}
+	if (soap_connect(soap, soap_endpoint, soap_action)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__find_USCOREinstances(soap, &soap_tmp_ns1__find_USCOREinstances, "ns1:find_instances", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap_closesock(soap);
+	soap_default_ns1__find_USCOREinstancesResponse(soap, param_2);
+	if (soap_begin_recv(soap)
+	 || soap_envelope_begin_in(soap)
+	 || soap_recv_header(soap)
+	 || soap_body_begin_in(soap))
+		return soap_closesock(soap);
+	soap_get_ns1__find_USCOREinstancesResponse(soap, param_2, "ns1:find_instancesResponse", "");
+	if (soap->error)
+	{	if (soap->error == SOAP_TAG_MISMATCH && soap->level == 2)
+			return soap_recv_fault(soap);
+		return soap_closesock(soap);
+	}
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap_closesock(soap);
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__delete_USCOREinstance(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *uri, int *result)
+{	struct ns1__delete_USCOREinstance soap_tmp_ns1__delete_USCOREinstance;
+	struct ns1__delete_USCOREinstanceResponse *soap_tmp_ns1__delete_USCOREinstanceResponse;
+	if (!soap_endpoint)
+		soap_endpoint = "http://localhost:80/nebulous";
+	if (!soap_action)
+		soap_action = "urn:Nebulous/Server/SOAP#delete_instance";
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	soap_tmp_ns1__delete_USCOREinstance.uri = uri;
+	soap_begin(soap);
+	soap_serializeheader(soap);
+	soap_serialize_ns1__delete_USCOREinstance(soap, &soap_tmp_ns1__delete_USCOREinstance);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__delete_USCOREinstance(soap, &soap_tmp_ns1__delete_USCOREinstance, "ns1:delete_instance", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	}
+	if (soap_connect(soap, soap_endpoint, soap_action)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__delete_USCOREinstance(soap, &soap_tmp_ns1__delete_USCOREinstance, "ns1:delete_instance", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap_closesock(soap);
+	soap_default_int(soap, result);
+	if (soap_begin_recv(soap)
+	 || soap_envelope_begin_in(soap)
+	 || soap_recv_header(soap)
+	 || soap_body_begin_in(soap))
+		return soap_closesock(soap);
+	soap_tmp_ns1__delete_USCOREinstanceResponse = soap_get_ns1__delete_USCOREinstanceResponse(soap, NULL, "ns1:delete_instanceResponse", "");
+	if (soap->error)
+	{	if (soap->error == SOAP_TAG_MISMATCH && soap->level == 2)
+			return soap_recv_fault(soap);
+		return soap_closesock(soap);
+	}
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap_closesock(soap);
+	if (result && soap_tmp_ns1__delete_USCOREinstanceResponse->result)
+		*result = *soap_tmp_ns1__delete_USCOREinstanceResponse->result;
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__stat_USCOREobject(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *key, struct ns1__stat_USCOREobjectResponse *param_3)
+{	struct ns1__stat_USCOREobject soap_tmp_ns1__stat_USCOREobject;
+	if (!soap_endpoint)
+		soap_endpoint = "http://localhost:80/nebulous";
+	if (!soap_action)
+		soap_action = "urn:Nebulous/Server/SOAP#stat_object";
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	soap_tmp_ns1__stat_USCOREobject.key = key;
+	soap_begin(soap);
+	soap_serializeheader(soap);
+	soap_serialize_ns1__stat_USCOREobject(soap, &soap_tmp_ns1__stat_USCOREobject);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__stat_USCOREobject(soap, &soap_tmp_ns1__stat_USCOREobject, "ns1:stat_object", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	}
+	if (soap_connect(soap, soap_endpoint, soap_action)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__stat_USCOREobject(soap, &soap_tmp_ns1__stat_USCOREobject, "ns1:stat_object", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap_closesock(soap);
+	soap_default_ns1__stat_USCOREobjectResponse(soap, param_3);
+	if (soap_begin_recv(soap)
+	 || soap_envelope_begin_in(soap)
+	 || soap_recv_header(soap)
+	 || soap_body_begin_in(soap))
+		return soap_closesock(soap);
+	soap_get_ns1__stat_USCOREobjectResponse(soap, param_3, "ns1:stat_objectResponse", "");
+	if (soap->error)
+	{	if (soap->error == SOAP_TAG_MISMATCH && soap->level == 2)
+			return soap_recv_fault(soap);
+		return soap_closesock(soap);
+	}
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap_closesock(soap);
+	return soap_closesock(soap);
+}
+
+SOAP_END_NAMESPACE(soap)
+
+#ifdef __cplusplus
+}
+#endif
+
+/* End of soapClient.c */
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapClientLib.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapClientLib.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapClientLib.c	(revision 21994)
@@ -0,0 +1,14 @@
+/* soapClientLib.c
+   Generated by gSOAP 2.7.2 from src/nebulous.h
+   Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc. All Rights Reserved.
+   This part of the software is released under one of the following licenses:
+   GPL, the gSOAP public license, or Genivia's license for commercial use.
+*/
+#ifndef WITH_NOGLOBAL
+#define WITH_NOGLOBAL
+#endif
+#define SOAP_FMAC3 static
+#include "soapC.c"
+#include "soapClient.c"
+
+/* End of soapClientLib.c */
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapH.h
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapH.h	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapH.h	(revision 21994)
@@ -0,0 +1,427 @@
+/* soapH.h
+   Generated by gSOAP 2.7.2 from src/nebulous.h
+   Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc. All Rights Reserved.
+   This part of the software is released under one of the following licenses:
+   GPL, the gSOAP public license, or Genivia's license for commercial use.
+*/
+#ifndef soapH_H
+#define soapH_H
+#include "soapStub.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SOAP_BEGIN_NAMESPACE(soap)
+SOAP_FMAC3 int SOAP_FMAC4 soap_ignore_element(struct soap*);
+#ifndef WITH_NOIDREF
+SOAP_FMAC3 int SOAP_FMAC4 soap_putindependent(struct soap*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_getindependent(struct soap*);
+SOAP_FMAC3 void SOAP_FMAC4 soap_markelement(struct soap*, const void*, int);
+SOAP_FMAC3 int SOAP_FMAC4 soap_putelement(struct soap*, const void*, const char*, int, int);
+SOAP_FMAC3 void * SOAP_FMAC4 soap_getelement(struct soap*, int*);
+#endif
+SOAP_FMAC3 int SOAP_FMAC4 soap_resolve_attachments(struct soap*);
+
+#ifndef SOAP_TYPE_byte
+#define SOAP_TYPE_byte (2)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_byte(struct soap*, char *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_byte(struct soap*, const char *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_byte(struct soap*, const char*, int, const char *, const char*);
+SOAP_FMAC3 char * SOAP_FMAC4 soap_get_byte(struct soap*, char *, const char*, const char*);
+SOAP_FMAC3 char * SOAP_FMAC4 soap_in_byte(struct soap*, const char*, char *, const char*);
+
+#ifndef SOAP_TYPE_int
+#define SOAP_TYPE_int (1)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_int(struct soap*, int *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_int(struct soap*, const int *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_int(struct soap*, const char*, int, const int *, const char*);
+SOAP_FMAC3 int * SOAP_FMAC4 soap_get_int(struct soap*, int *, const char*, const char*);
+SOAP_FMAC3 int * SOAP_FMAC4 soap_in_int(struct soap*, const char*, int *, const char*);
+
+#ifndef WITH_NOGLOBAL
+
+#ifndef SOAP_TYPE_SOAP_ENV__Fault
+#define SOAP_TYPE_SOAP_ENV__Fault (50)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Fault(struct soap*, const struct SOAP_ENV__Fault *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Fault(struct soap*, struct SOAP_ENV__Fault *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Fault(struct soap*, const struct SOAP_ENV__Fault *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Fault(struct soap*, const char*, int, const struct SOAP_ENV__Fault *, const char*);
+SOAP_FMAC3 struct SOAP_ENV__Fault * SOAP_FMAC4 soap_get_SOAP_ENV__Fault(struct soap*, struct SOAP_ENV__Fault *, const char*, const char*);
+SOAP_FMAC3 struct SOAP_ENV__Fault * SOAP_FMAC4 soap_in_SOAP_ENV__Fault(struct soap*, const char*, struct SOAP_ENV__Fault *, const char*);
+
+#endif
+
+#ifndef WITH_NOGLOBAL
+
+#ifndef SOAP_TYPE_SOAP_ENV__Detail
+#define SOAP_TYPE_SOAP_ENV__Detail (49)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Detail(struct soap*, const struct SOAP_ENV__Detail *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Detail(struct soap*, struct SOAP_ENV__Detail *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Detail(struct soap*, const struct SOAP_ENV__Detail *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Detail(struct soap*, const char*, int, const struct SOAP_ENV__Detail *, const char*);
+SOAP_FMAC3 struct SOAP_ENV__Detail * SOAP_FMAC4 soap_get_SOAP_ENV__Detail(struct soap*, struct SOAP_ENV__Detail *, const char*, const char*);
+SOAP_FMAC3 struct SOAP_ENV__Detail * SOAP_FMAC4 soap_in_SOAP_ENV__Detail(struct soap*, const char*, struct SOAP_ENV__Detail *, const char*);
+
+#endif
+
+#ifndef WITH_NOGLOBAL
+
+#ifndef SOAP_TYPE_SOAP_ENV__Code
+#define SOAP_TYPE_SOAP_ENV__Code (47)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Code(struct soap*, const struct SOAP_ENV__Code *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Code(struct soap*, struct SOAP_ENV__Code *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Code(struct soap*, const struct SOAP_ENV__Code *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Code(struct soap*, const char*, int, const struct SOAP_ENV__Code *, const char*);
+SOAP_FMAC3 struct SOAP_ENV__Code * SOAP_FMAC4 soap_get_SOAP_ENV__Code(struct soap*, struct SOAP_ENV__Code *, const char*, const char*);
+SOAP_FMAC3 struct SOAP_ENV__Code * SOAP_FMAC4 soap_in_SOAP_ENV__Code(struct soap*, const char*, struct SOAP_ENV__Code *, const char*);
+
+#endif
+
+#ifndef WITH_NOGLOBAL
+
+#ifndef SOAP_TYPE_SOAP_ENV__Header
+#define SOAP_TYPE_SOAP_ENV__Header (46)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Header(struct soap*, const struct SOAP_ENV__Header *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Header(struct soap*, struct SOAP_ENV__Header *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Header(struct soap*, const struct SOAP_ENV__Header *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Header(struct soap*, const char*, int, const struct SOAP_ENV__Header *, const char*);
+SOAP_FMAC3 struct SOAP_ENV__Header * SOAP_FMAC4 soap_get_SOAP_ENV__Header(struct soap*, struct SOAP_ENV__Header *, const char*, const char*);
+SOAP_FMAC3 struct SOAP_ENV__Header * SOAP_FMAC4 soap_in_SOAP_ENV__Header(struct soap*, const char*, struct SOAP_ENV__Header *, const char*);
+
+#endif
+
+#ifndef SOAP_TYPE_ns1__stat_USCOREobject
+#define SOAP_TYPE_ns1__stat_USCOREobject (43)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__stat_USCOREobject(struct soap*, const struct ns1__stat_USCOREobject *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__stat_USCOREobject(struct soap*, struct ns1__stat_USCOREobject *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__stat_USCOREobject(struct soap*, const struct ns1__stat_USCOREobject *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__stat_USCOREobject(struct soap*, const char*, int, const struct ns1__stat_USCOREobject *, const char*);
+SOAP_FMAC3 struct ns1__stat_USCOREobject * SOAP_FMAC4 soap_get_ns1__stat_USCOREobject(struct soap*, struct ns1__stat_USCOREobject *, const char*, const char*);
+SOAP_FMAC3 struct ns1__stat_USCOREobject * SOAP_FMAC4 soap_in_ns1__stat_USCOREobject(struct soap*, const char*, struct ns1__stat_USCOREobject *, const char*);
+
+#ifndef SOAP_TYPE_ns1__stat_USCOREobjectResponse
+#define SOAP_TYPE_ns1__stat_USCOREobjectResponse (40)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__stat_USCOREobjectResponse(struct soap*, const struct ns1__stat_USCOREobjectResponse *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__stat_USCOREobjectResponse(struct soap*, struct ns1__stat_USCOREobjectResponse *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__stat_USCOREobjectResponse(struct soap*, const struct ns1__stat_USCOREobjectResponse *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__stat_USCOREobjectResponse(struct soap*, const char*, int, const struct ns1__stat_USCOREobjectResponse *, const char*);
+SOAP_FMAC3 struct ns1__stat_USCOREobjectResponse * SOAP_FMAC4 soap_get_ns1__stat_USCOREobjectResponse(struct soap*, struct ns1__stat_USCOREobjectResponse *, const char*, const char*);
+SOAP_FMAC3 struct ns1__stat_USCOREobjectResponse * SOAP_FMAC4 soap_in_ns1__stat_USCOREobjectResponse(struct soap*, const char*, struct ns1__stat_USCOREobjectResponse *, const char*);
+
+#ifndef SOAP_TYPE_ns1__delete_USCOREinstance
+#define SOAP_TYPE_ns1__delete_USCOREinstance (39)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__delete_USCOREinstance(struct soap*, const struct ns1__delete_USCOREinstance *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__delete_USCOREinstance(struct soap*, struct ns1__delete_USCOREinstance *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__delete_USCOREinstance(struct soap*, const struct ns1__delete_USCOREinstance *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__delete_USCOREinstance(struct soap*, const char*, int, const struct ns1__delete_USCOREinstance *, const char*);
+SOAP_FMAC3 struct ns1__delete_USCOREinstance * SOAP_FMAC4 soap_get_ns1__delete_USCOREinstance(struct soap*, struct ns1__delete_USCOREinstance *, const char*, const char*);
+SOAP_FMAC3 struct ns1__delete_USCOREinstance * SOAP_FMAC4 soap_in_ns1__delete_USCOREinstance(struct soap*, const char*, struct ns1__delete_USCOREinstance *, const char*);
+
+#ifndef SOAP_TYPE_ns1__delete_USCOREinstanceResponse
+#define SOAP_TYPE_ns1__delete_USCOREinstanceResponse (38)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__delete_USCOREinstanceResponse(struct soap*, const struct ns1__delete_USCOREinstanceResponse *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__delete_USCOREinstanceResponse(struct soap*, struct ns1__delete_USCOREinstanceResponse *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__delete_USCOREinstanceResponse(struct soap*, const struct ns1__delete_USCOREinstanceResponse *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__delete_USCOREinstanceResponse(struct soap*, const char*, int, const struct ns1__delete_USCOREinstanceResponse *, const char*);
+SOAP_FMAC3 struct ns1__delete_USCOREinstanceResponse * SOAP_FMAC4 soap_get_ns1__delete_USCOREinstanceResponse(struct soap*, struct ns1__delete_USCOREinstanceResponse *, const char*, const char*);
+SOAP_FMAC3 struct ns1__delete_USCOREinstanceResponse * SOAP_FMAC4 soap_in_ns1__delete_USCOREinstanceResponse(struct soap*, const char*, struct ns1__delete_USCOREinstanceResponse *, const char*);
+
+#ifndef SOAP_TYPE_ns1__find_USCOREinstances
+#define SOAP_TYPE_ns1__find_USCOREinstances (36)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__find_USCOREinstances(struct soap*, const struct ns1__find_USCOREinstances *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__find_USCOREinstances(struct soap*, struct ns1__find_USCOREinstances *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__find_USCOREinstances(struct soap*, const struct ns1__find_USCOREinstances *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__find_USCOREinstances(struct soap*, const char*, int, const struct ns1__find_USCOREinstances *, const char*);
+SOAP_FMAC3 struct ns1__find_USCOREinstances * SOAP_FMAC4 soap_get_ns1__find_USCOREinstances(struct soap*, struct ns1__find_USCOREinstances *, const char*, const char*);
+SOAP_FMAC3 struct ns1__find_USCOREinstances * SOAP_FMAC4 soap_in_ns1__find_USCOREinstances(struct soap*, const char*, struct ns1__find_USCOREinstances *, const char*);
+
+#ifndef SOAP_TYPE_ns1__find_USCOREinstancesResponse
+#define SOAP_TYPE_ns1__find_USCOREinstancesResponse (33)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__find_USCOREinstancesResponse(struct soap*, const struct ns1__find_USCOREinstancesResponse *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__find_USCOREinstancesResponse(struct soap*, struct ns1__find_USCOREinstancesResponse *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__find_USCOREinstancesResponse(struct soap*, const struct ns1__find_USCOREinstancesResponse *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__find_USCOREinstancesResponse(struct soap*, const char*, int, const struct ns1__find_USCOREinstancesResponse *, const char*);
+SOAP_FMAC3 struct ns1__find_USCOREinstancesResponse * SOAP_FMAC4 soap_get_ns1__find_USCOREinstancesResponse(struct soap*, struct ns1__find_USCOREinstancesResponse *, const char*, const char*);
+SOAP_FMAC3 struct ns1__find_USCOREinstancesResponse * SOAP_FMAC4 soap_in_ns1__find_USCOREinstancesResponse(struct soap*, const char*, struct ns1__find_USCOREinstancesResponse *, const char*);
+
+#ifndef SOAP_TYPE_ns1__find_USCOREobjects
+#define SOAP_TYPE_ns1__find_USCOREobjects (32)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__find_USCOREobjects(struct soap*, const struct ns1__find_USCOREobjects *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__find_USCOREobjects(struct soap*, struct ns1__find_USCOREobjects *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__find_USCOREobjects(struct soap*, const struct ns1__find_USCOREobjects *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__find_USCOREobjects(struct soap*, const char*, int, const struct ns1__find_USCOREobjects *, const char*);
+SOAP_FMAC3 struct ns1__find_USCOREobjects * SOAP_FMAC4 soap_get_ns1__find_USCOREobjects(struct soap*, struct ns1__find_USCOREobjects *, const char*, const char*);
+SOAP_FMAC3 struct ns1__find_USCOREobjects * SOAP_FMAC4 soap_in_ns1__find_USCOREobjects(struct soap*, const char*, struct ns1__find_USCOREobjects *, const char*);
+
+#ifndef SOAP_TYPE_ns1__find_USCOREobjectsResponse
+#define SOAP_TYPE_ns1__find_USCOREobjectsResponse (28)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__find_USCOREobjectsResponse(struct soap*, const struct ns1__find_USCOREobjectsResponse *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__find_USCOREobjectsResponse(struct soap*, struct ns1__find_USCOREobjectsResponse *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__find_USCOREobjectsResponse(struct soap*, const struct ns1__find_USCOREobjectsResponse *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__find_USCOREobjectsResponse(struct soap*, const char*, int, const struct ns1__find_USCOREobjectsResponse *, const char*);
+SOAP_FMAC3 struct ns1__find_USCOREobjectsResponse * SOAP_FMAC4 soap_get_ns1__find_USCOREobjectsResponse(struct soap*, struct ns1__find_USCOREobjectsResponse *, const char*, const char*);
+SOAP_FMAC3 struct ns1__find_USCOREobjectsResponse * SOAP_FMAC4 soap_in_ns1__find_USCOREobjectsResponse(struct soap*, const char*, struct ns1__find_USCOREobjectsResponse *, const char*);
+
+#ifndef SOAP_TYPE_ns1__unlock_USCOREobject
+#define SOAP_TYPE_ns1__unlock_USCOREobject (27)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__unlock_USCOREobject(struct soap*, const struct ns1__unlock_USCOREobject *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__unlock_USCOREobject(struct soap*, struct ns1__unlock_USCOREobject *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__unlock_USCOREobject(struct soap*, const struct ns1__unlock_USCOREobject *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__unlock_USCOREobject(struct soap*, const char*, int, const struct ns1__unlock_USCOREobject *, const char*);
+SOAP_FMAC3 struct ns1__unlock_USCOREobject * SOAP_FMAC4 soap_get_ns1__unlock_USCOREobject(struct soap*, struct ns1__unlock_USCOREobject *, const char*, const char*);
+SOAP_FMAC3 struct ns1__unlock_USCOREobject * SOAP_FMAC4 soap_in_ns1__unlock_USCOREobject(struct soap*, const char*, struct ns1__unlock_USCOREobject *, const char*);
+
+#ifndef SOAP_TYPE_ns1__unlock_USCOREobjectResponse
+#define SOAP_TYPE_ns1__unlock_USCOREobjectResponse (26)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__unlock_USCOREobjectResponse(struct soap*, const struct ns1__unlock_USCOREobjectResponse *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__unlock_USCOREobjectResponse(struct soap*, struct ns1__unlock_USCOREobjectResponse *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__unlock_USCOREobjectResponse(struct soap*, const struct ns1__unlock_USCOREobjectResponse *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__unlock_USCOREobjectResponse(struct soap*, const char*, int, const struct ns1__unlock_USCOREobjectResponse *, const char*);
+SOAP_FMAC3 struct ns1__unlock_USCOREobjectResponse * SOAP_FMAC4 soap_get_ns1__unlock_USCOREobjectResponse(struct soap*, struct ns1__unlock_USCOREobjectResponse *, const char*, const char*);
+SOAP_FMAC3 struct ns1__unlock_USCOREobjectResponse * SOAP_FMAC4 soap_in_ns1__unlock_USCOREobjectResponse(struct soap*, const char*, struct ns1__unlock_USCOREobjectResponse *, const char*);
+
+#ifndef SOAP_TYPE_ns1__lock_USCOREobject
+#define SOAP_TYPE_ns1__lock_USCOREobject (24)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__lock_USCOREobject(struct soap*, const struct ns1__lock_USCOREobject *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__lock_USCOREobject(struct soap*, struct ns1__lock_USCOREobject *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__lock_USCOREobject(struct soap*, const struct ns1__lock_USCOREobject *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__lock_USCOREobject(struct soap*, const char*, int, const struct ns1__lock_USCOREobject *, const char*);
+SOAP_FMAC3 struct ns1__lock_USCOREobject * SOAP_FMAC4 soap_get_ns1__lock_USCOREobject(struct soap*, struct ns1__lock_USCOREobject *, const char*, const char*);
+SOAP_FMAC3 struct ns1__lock_USCOREobject * SOAP_FMAC4 soap_in_ns1__lock_USCOREobject(struct soap*, const char*, struct ns1__lock_USCOREobject *, const char*);
+
+#ifndef SOAP_TYPE_ns1__lock_USCOREobjectResponse
+#define SOAP_TYPE_ns1__lock_USCOREobjectResponse (23)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__lock_USCOREobjectResponse(struct soap*, const struct ns1__lock_USCOREobjectResponse *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__lock_USCOREobjectResponse(struct soap*, struct ns1__lock_USCOREobjectResponse *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__lock_USCOREobjectResponse(struct soap*, const struct ns1__lock_USCOREobjectResponse *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__lock_USCOREobjectResponse(struct soap*, const char*, int, const struct ns1__lock_USCOREobjectResponse *, const char*);
+SOAP_FMAC3 struct ns1__lock_USCOREobjectResponse * SOAP_FMAC4 soap_get_ns1__lock_USCOREobjectResponse(struct soap*, struct ns1__lock_USCOREobjectResponse *, const char*, const char*);
+SOAP_FMAC3 struct ns1__lock_USCOREobjectResponse * SOAP_FMAC4 soap_in_ns1__lock_USCOREobjectResponse(struct soap*, const char*, struct ns1__lock_USCOREobjectResponse *, const char*);
+
+#ifndef SOAP_TYPE_ns1__replicate_USCOREobject
+#define SOAP_TYPE_ns1__replicate_USCOREobject (20)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__replicate_USCOREobject(struct soap*, const struct ns1__replicate_USCOREobject *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__replicate_USCOREobject(struct soap*, struct ns1__replicate_USCOREobject *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__replicate_USCOREobject(struct soap*, const struct ns1__replicate_USCOREobject *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__replicate_USCOREobject(struct soap*, const char*, int, const struct ns1__replicate_USCOREobject *, const char*);
+SOAP_FMAC3 struct ns1__replicate_USCOREobject * SOAP_FMAC4 soap_get_ns1__replicate_USCOREobject(struct soap*, struct ns1__replicate_USCOREobject *, const char*, const char*);
+SOAP_FMAC3 struct ns1__replicate_USCOREobject * SOAP_FMAC4 soap_in_ns1__replicate_USCOREobject(struct soap*, const char*, struct ns1__replicate_USCOREobject *, const char*);
+
+#ifndef SOAP_TYPE_ns1__replicate_USCOREobjectResponse
+#define SOAP_TYPE_ns1__replicate_USCOREobjectResponse (19)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__replicate_USCOREobjectResponse(struct soap*, const struct ns1__replicate_USCOREobjectResponse *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__replicate_USCOREobjectResponse(struct soap*, struct ns1__replicate_USCOREobjectResponse *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__replicate_USCOREobjectResponse(struct soap*, const struct ns1__replicate_USCOREobjectResponse *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__replicate_USCOREobjectResponse(struct soap*, const char*, int, const struct ns1__replicate_USCOREobjectResponse *, const char*);
+SOAP_FMAC3 struct ns1__replicate_USCOREobjectResponse * SOAP_FMAC4 soap_get_ns1__replicate_USCOREobjectResponse(struct soap*, struct ns1__replicate_USCOREobjectResponse *, const char*, const char*);
+SOAP_FMAC3 struct ns1__replicate_USCOREobjectResponse * SOAP_FMAC4 soap_in_ns1__replicate_USCOREobjectResponse(struct soap*, const char*, struct ns1__replicate_USCOREobjectResponse *, const char*);
+
+#ifndef SOAP_TYPE_ns1__rename_USCOREobject_
+#define SOAP_TYPE_ns1__rename_USCOREobject_ (17)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__rename_USCOREobject_(struct soap*, const struct ns1__rename_USCOREobject_ *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__rename_USCOREobject_(struct soap*, struct ns1__rename_USCOREobject_ *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__rename_USCOREobject_(struct soap*, const struct ns1__rename_USCOREobject_ *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__rename_USCOREobject_(struct soap*, const char*, int, const struct ns1__rename_USCOREobject_ *, const char*);
+SOAP_FMAC3 struct ns1__rename_USCOREobject_ * SOAP_FMAC4 soap_get_ns1__rename_USCOREobject_(struct soap*, struct ns1__rename_USCOREobject_ *, const char*, const char*);
+SOAP_FMAC3 struct ns1__rename_USCOREobject_ * SOAP_FMAC4 soap_in_ns1__rename_USCOREobject_(struct soap*, const char*, struct ns1__rename_USCOREobject_ *, const char*);
+
+#ifndef SOAP_TYPE_ns1__rename_USCOREobject_Response
+#define SOAP_TYPE_ns1__rename_USCOREobject_Response (16)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__rename_USCOREobject_Response(struct soap*, const struct ns1__rename_USCOREobject_Response *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__rename_USCOREobject_Response(struct soap*, struct ns1__rename_USCOREobject_Response *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__rename_USCOREobject_Response(struct soap*, const struct ns1__rename_USCOREobject_Response *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__rename_USCOREobject_Response(struct soap*, const char*, int, const struct ns1__rename_USCOREobject_Response *, const char*);
+SOAP_FMAC3 struct ns1__rename_USCOREobject_Response * SOAP_FMAC4 soap_get_ns1__rename_USCOREobject_Response(struct soap*, struct ns1__rename_USCOREobject_Response *, const char*, const char*);
+SOAP_FMAC3 struct ns1__rename_USCOREobject_Response * SOAP_FMAC4 soap_in_ns1__rename_USCOREobject_Response(struct soap*, const char*, struct ns1__rename_USCOREobject_Response *, const char*);
+
+#ifndef SOAP_TYPE_ns1__rename_USCOREobject
+#define SOAP_TYPE_ns1__rename_USCOREobject (14)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__rename_USCOREobject(struct soap*, const struct ns1__rename_USCOREobject *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__rename_USCOREobject(struct soap*, struct ns1__rename_USCOREobject *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__rename_USCOREobject(struct soap*, const struct ns1__rename_USCOREobject *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__rename_USCOREobject(struct soap*, const char*, int, const struct ns1__rename_USCOREobject *, const char*);
+SOAP_FMAC3 struct ns1__rename_USCOREobject * SOAP_FMAC4 soap_get_ns1__rename_USCOREobject(struct soap*, struct ns1__rename_USCOREobject *, const char*, const char*);
+SOAP_FMAC3 struct ns1__rename_USCOREobject * SOAP_FMAC4 soap_in_ns1__rename_USCOREobject(struct soap*, const char*, struct ns1__rename_USCOREobject *, const char*);
+
+#ifndef SOAP_TYPE_ns1__rename_USCOREobjectResponse
+#define SOAP_TYPE_ns1__rename_USCOREobjectResponse (13)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__rename_USCOREobjectResponse(struct soap*, const struct ns1__rename_USCOREobjectResponse *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__rename_USCOREobjectResponse(struct soap*, struct ns1__rename_USCOREobjectResponse *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__rename_USCOREobjectResponse(struct soap*, const struct ns1__rename_USCOREobjectResponse *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__rename_USCOREobjectResponse(struct soap*, const char*, int, const struct ns1__rename_USCOREobjectResponse *, const char*);
+SOAP_FMAC3 struct ns1__rename_USCOREobjectResponse * SOAP_FMAC4 soap_get_ns1__rename_USCOREobjectResponse(struct soap*, struct ns1__rename_USCOREobjectResponse *, const char*, const char*);
+SOAP_FMAC3 struct ns1__rename_USCOREobjectResponse * SOAP_FMAC4 soap_in_ns1__rename_USCOREobjectResponse(struct soap*, const char*, struct ns1__rename_USCOREobjectResponse *, const char*);
+
+#ifndef SOAP_TYPE_ns1__create_USCOREobject
+#define SOAP_TYPE_ns1__create_USCOREobject (11)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__create_USCOREobject(struct soap*, const struct ns1__create_USCOREobject *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__create_USCOREobject(struct soap*, struct ns1__create_USCOREobject *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__create_USCOREobject(struct soap*, const struct ns1__create_USCOREobject *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__create_USCOREobject(struct soap*, const char*, int, const struct ns1__create_USCOREobject *, const char*);
+SOAP_FMAC3 struct ns1__create_USCOREobject * SOAP_FMAC4 soap_get_ns1__create_USCOREobject(struct soap*, struct ns1__create_USCOREobject *, const char*, const char*);
+SOAP_FMAC3 struct ns1__create_USCOREobject * SOAP_FMAC4 soap_in_ns1__create_USCOREobject(struct soap*, const char*, struct ns1__create_USCOREobject *, const char*);
+
+#ifndef SOAP_TYPE_ns1__create_USCOREobjectResponse
+#define SOAP_TYPE_ns1__create_USCOREobjectResponse (10)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__create_USCOREobjectResponse(struct soap*, const struct ns1__create_USCOREobjectResponse *);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__create_USCOREobjectResponse(struct soap*, struct ns1__create_USCOREobjectResponse *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__create_USCOREobjectResponse(struct soap*, const struct ns1__create_USCOREobjectResponse *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__create_USCOREobjectResponse(struct soap*, const char*, int, const struct ns1__create_USCOREobjectResponse *, const char*);
+SOAP_FMAC3 struct ns1__create_USCOREobjectResponse * SOAP_FMAC4 soap_get_ns1__create_USCOREobjectResponse(struct soap*, struct ns1__create_USCOREobjectResponse *, const char*, const char*);
+SOAP_FMAC3 struct ns1__create_USCOREobjectResponse * SOAP_FMAC4 soap_in_ns1__create_USCOREobjectResponse(struct soap*, const char*, struct ns1__create_USCOREobjectResponse *, const char*);
+
+#ifndef SOAP_TYPE_ArrayOfString
+#define SOAP_TYPE_ArrayOfString (7)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ArrayOfString(struct soap*, struct ArrayOfString const*);
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_ArrayOfString(struct soap*, struct ArrayOfString *);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_ArrayOfString(struct soap*, const struct ArrayOfString *, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_ArrayOfString(struct soap*, const char*, int, const struct ArrayOfString *, const char*);
+SOAP_FMAC3 struct ArrayOfString * SOAP_FMAC4 soap_get_ArrayOfString(struct soap*, struct ArrayOfString *, const char*, const char*);
+SOAP_FMAC3 struct ArrayOfString * SOAP_FMAC4 soap_in_ArrayOfString(struct soap*, const char*, struct ArrayOfString *, const char*);
+
+#ifndef WITH_NOGLOBAL
+
+#ifndef SOAP_TYPE_PointerToSOAP_ENV__Detail
+#define SOAP_TYPE_PointerToSOAP_ENV__Detail (51)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerToSOAP_ENV__Detail(struct soap*, struct SOAP_ENV__Detail *const*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToSOAP_ENV__Detail(struct soap*, struct SOAP_ENV__Detail *const*, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToSOAP_ENV__Detail(struct soap*, const char *, int, struct SOAP_ENV__Detail *const*, const char *);
+SOAP_FMAC3 struct SOAP_ENV__Detail ** SOAP_FMAC4 soap_get_PointerToSOAP_ENV__Detail(struct soap*, struct SOAP_ENV__Detail **, const char*, const char*);
+SOAP_FMAC3 struct SOAP_ENV__Detail ** SOAP_FMAC4 soap_in_PointerToSOAP_ENV__Detail(struct soap*, const char*, struct SOAP_ENV__Detail **, const char*);
+
+#endif
+
+#ifndef WITH_NOGLOBAL
+
+#ifndef SOAP_TYPE_PointerToSOAP_ENV__Code
+#define SOAP_TYPE_PointerToSOAP_ENV__Code (48)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerToSOAP_ENV__Code(struct soap*, struct SOAP_ENV__Code *const*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToSOAP_ENV__Code(struct soap*, struct SOAP_ENV__Code *const*, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToSOAP_ENV__Code(struct soap*, const char *, int, struct SOAP_ENV__Code *const*, const char *);
+SOAP_FMAC3 struct SOAP_ENV__Code ** SOAP_FMAC4 soap_get_PointerToSOAP_ENV__Code(struct soap*, struct SOAP_ENV__Code **, const char*, const char*);
+SOAP_FMAC3 struct SOAP_ENV__Code ** SOAP_FMAC4 soap_in_PointerToSOAP_ENV__Code(struct soap*, const char*, struct SOAP_ENV__Code **, const char*);
+
+#endif
+
+#ifndef SOAP_TYPE_PointerTons1__stat_USCOREobjectResponse
+#define SOAP_TYPE_PointerTons1__stat_USCOREobjectResponse (41)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerTons1__stat_USCOREobjectResponse(struct soap*, struct ns1__stat_USCOREobjectResponse *const*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerTons1__stat_USCOREobjectResponse(struct soap*, struct ns1__stat_USCOREobjectResponse *const*, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerTons1__stat_USCOREobjectResponse(struct soap*, const char *, int, struct ns1__stat_USCOREobjectResponse *const*, const char *);
+SOAP_FMAC3 struct ns1__stat_USCOREobjectResponse ** SOAP_FMAC4 soap_get_PointerTons1__stat_USCOREobjectResponse(struct soap*, struct ns1__stat_USCOREobjectResponse **, const char*, const char*);
+SOAP_FMAC3 struct ns1__stat_USCOREobjectResponse ** SOAP_FMAC4 soap_in_PointerTons1__stat_USCOREobjectResponse(struct soap*, const char*, struct ns1__stat_USCOREobjectResponse **, const char*);
+
+#ifndef SOAP_TYPE_PointerTons1__find_USCOREinstancesResponse
+#define SOAP_TYPE_PointerTons1__find_USCOREinstancesResponse (34)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerTons1__find_USCOREinstancesResponse(struct soap*, struct ns1__find_USCOREinstancesResponse *const*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerTons1__find_USCOREinstancesResponse(struct soap*, struct ns1__find_USCOREinstancesResponse *const*, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerTons1__find_USCOREinstancesResponse(struct soap*, const char *, int, struct ns1__find_USCOREinstancesResponse *const*, const char *);
+SOAP_FMAC3 struct ns1__find_USCOREinstancesResponse ** SOAP_FMAC4 soap_get_PointerTons1__find_USCOREinstancesResponse(struct soap*, struct ns1__find_USCOREinstancesResponse **, const char*, const char*);
+SOAP_FMAC3 struct ns1__find_USCOREinstancesResponse ** SOAP_FMAC4 soap_in_PointerTons1__find_USCOREinstancesResponse(struct soap*, const char*, struct ns1__find_USCOREinstancesResponse **, const char*);
+
+#ifndef SOAP_TYPE_PointerTons1__find_USCOREobjectsResponse
+#define SOAP_TYPE_PointerTons1__find_USCOREobjectsResponse (30)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerTons1__find_USCOREobjectsResponse(struct soap*, struct ns1__find_USCOREobjectsResponse *const*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerTons1__find_USCOREobjectsResponse(struct soap*, struct ns1__find_USCOREobjectsResponse *const*, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerTons1__find_USCOREobjectsResponse(struct soap*, const char *, int, struct ns1__find_USCOREobjectsResponse *const*, const char *);
+SOAP_FMAC3 struct ns1__find_USCOREobjectsResponse ** SOAP_FMAC4 soap_get_PointerTons1__find_USCOREobjectsResponse(struct soap*, struct ns1__find_USCOREobjectsResponse **, const char*, const char*);
+SOAP_FMAC3 struct ns1__find_USCOREobjectsResponse ** SOAP_FMAC4 soap_in_PointerTons1__find_USCOREobjectsResponse(struct soap*, const char*, struct ns1__find_USCOREobjectsResponse **, const char*);
+
+#ifndef SOAP_TYPE_PointerToArrayOfString
+#define SOAP_TYPE_PointerToArrayOfString (29)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerToArrayOfString(struct soap*, struct ArrayOfString *const*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToArrayOfString(struct soap*, struct ArrayOfString *const*, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToArrayOfString(struct soap*, const char *, int, struct ArrayOfString *const*, const char *);
+SOAP_FMAC3 struct ArrayOfString ** SOAP_FMAC4 soap_get_PointerToArrayOfString(struct soap*, struct ArrayOfString **, const char*, const char*);
+SOAP_FMAC3 struct ArrayOfString ** SOAP_FMAC4 soap_in_PointerToArrayOfString(struct soap*, const char*, struct ArrayOfString **, const char*);
+
+#ifndef SOAP_TYPE_PointerToint
+#define SOAP_TYPE_PointerToint (21)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerToint(struct soap*, int *const*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToint(struct soap*, int *const*, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToint(struct soap*, const char *, int, int *const*, const char *);
+SOAP_FMAC3 int ** SOAP_FMAC4 soap_get_PointerToint(struct soap*, int **, const char*, const char*);
+SOAP_FMAC3 int ** SOAP_FMAC4 soap_in_PointerToint(struct soap*, const char*, int **, const char*);
+
+#ifndef SOAP_TYPE_PointerTostring
+#define SOAP_TYPE_PointerTostring (8)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerTostring(struct soap*, char **const*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerTostring(struct soap*, char **const*, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerTostring(struct soap*, const char *, int, char **const*, const char *);
+SOAP_FMAC3 char *** SOAP_FMAC4 soap_get_PointerTostring(struct soap*, char ***, const char*, const char*);
+SOAP_FMAC3 char *** SOAP_FMAC4 soap_in_PointerTostring(struct soap*, const char*, char ***, const char*);
+
+#ifndef SOAP_TYPE_SOAP_ENC__arrayType
+#define SOAP_TYPE_SOAP_ENC__arrayType (6)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENC__arrayType(struct soap*, char **);
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENC__arrayType(struct soap*, char *const*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENC__arrayType(struct soap*, char *const*, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENC__arrayType(struct soap*, const char*, int, char*const*, const char*);
+SOAP_FMAC3 char ** SOAP_FMAC4 soap_get_SOAP_ENC__arrayType(struct soap*, char **, const char*, const char*);
+SOAP_FMAC3 char * * SOAP_FMAC4 soap_in_SOAP_ENC__arrayType(struct soap*, const char*, char **, const char*);
+
+#ifndef SOAP_TYPE__QName
+#define SOAP_TYPE__QName (5)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_default__QName(struct soap*, char **);
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize__QName(struct soap*, char *const*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put__QName(struct soap*, char *const*, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out__QName(struct soap*, const char*, int, char*const*, const char*);
+SOAP_FMAC3 char ** SOAP_FMAC4 soap_get__QName(struct soap*, char **, const char*, const char*);
+SOAP_FMAC3 char * * SOAP_FMAC4 soap_in__QName(struct soap*, const char*, char **, const char*);
+
+#ifndef SOAP_TYPE_string
+#define SOAP_TYPE_string (3)
+#endif
+SOAP_FMAC3 void SOAP_FMAC4 soap_default_string(struct soap*, char **);
+SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_string(struct soap*, char *const*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_put_string(struct soap*, char *const*, const char*, const char*);
+SOAP_FMAC3 int SOAP_FMAC4 soap_out_string(struct soap*, const char*, int, char*const*, const char*);
+SOAP_FMAC3 char ** SOAP_FMAC4 soap_get_string(struct soap*, char **, const char*, const char*);
+SOAP_FMAC3 char * * SOAP_FMAC4 soap_in_string(struct soap*, const char*, char **, const char*);
+
+SOAP_END_NAMESPACE(soap)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/* End of soapH.h */
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapServer.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapServer.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapServer.c	(revision 21994)
@@ -0,0 +1,505 @@
+/* soapServer.c
+   Generated by gSOAP 2.7.2 from src/nebulous.h
+   Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc. All Rights Reserved.
+   This part of the software is released under one of the following licenses:
+   GPL, the gSOAP public license, or Genivia's license for commercial use.
+*/
+#include "soapH.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SOAP_BEGIN_NAMESPACE(soap)
+
+SOAP_SOURCE_STAMP("@(#) soapServer.c ver 2.7.2 2007-05-01 02:53:36 GMT")
+
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve(struct soap *soap)
+{
+	unsigned int n = soap->max_keep_alive;
+	do
+	{	soap_begin(soap);
+		if (!--n)
+			soap->keep_alive = 0;
+		if (soap_begin_recv(soap))
+		{	if (soap->error < SOAP_STOP)
+				return soap_send_fault(soap);
+			soap_closesock(soap);
+			continue;
+		}
+		if (soap_envelope_begin_in(soap)
+		 || soap_recv_header(soap)
+		 || soap_body_begin_in(soap)
+		 || soap_serve_request(soap) || (soap->fserveloop && soap->fserveloop(soap)))
+			return soap_send_fault(soap);
+		
+	} while (soap->keep_alive);
+	return SOAP_OK;
+}
+
+#ifndef WITH_NOSERVEREQUEST
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_request(struct soap *soap)
+{
+	soap_peek_element(soap);
+	if (!soap_match_tag(soap, soap->tag, "ns1:create_object"))
+		return soap_serve_ns1__create_USCOREobject(soap);
+	if (!soap_match_tag(soap, soap->tag, "ns1:rename_object"))
+		return soap_serve_ns1__rename_USCOREobject(soap);
+	if (!soap_match_tag(soap, soap->tag, "ns1:rename_object"))
+		return soap_serve_ns1__rename_USCOREobject_(soap);
+	if (!soap_match_tag(soap, soap->tag, "ns1:replicate_object"))
+		return soap_serve_ns1__replicate_USCOREobject(soap);
+	if (!soap_match_tag(soap, soap->tag, "ns1:lock_object"))
+		return soap_serve_ns1__lock_USCOREobject(soap);
+	if (!soap_match_tag(soap, soap->tag, "ns1:unlock_object"))
+		return soap_serve_ns1__unlock_USCOREobject(soap);
+	if (!soap_match_tag(soap, soap->tag, "ns1:find_objects"))
+		return soap_serve_ns1__find_USCOREobjects(soap);
+	if (!soap_match_tag(soap, soap->tag, "ns1:find_instances"))
+		return soap_serve_ns1__find_USCOREinstances(soap);
+	if (!soap_match_tag(soap, soap->tag, "ns1:delete_instance"))
+		return soap_serve_ns1__delete_USCOREinstance(soap);
+	if (!soap_match_tag(soap, soap->tag, "ns1:stat_object"))
+		return soap_serve_ns1__stat_USCOREobject(soap);
+	return soap->error = SOAP_NO_METHOD;
+}
+#endif
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__create_USCOREobject(struct soap *soap)
+{	struct ns1__create_USCOREobject soap_tmp_ns1__create_USCOREobject;
+	struct ns1__create_USCOREobjectResponse soap_tmp_ns1__create_USCOREobjectResponse;
+	char * soap_tmp_string;
+	soap_default_ns1__create_USCOREobjectResponse(soap, &soap_tmp_ns1__create_USCOREobjectResponse);
+	soap_tmp_string = NULL;
+	soap_tmp_ns1__create_USCOREobjectResponse.result = &soap_tmp_string;
+	soap_default_ns1__create_USCOREobject(soap, &soap_tmp_ns1__create_USCOREobject);
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	if (!soap_get_ns1__create_USCOREobject(soap, &soap_tmp_ns1__create_USCOREobject, "ns1:create_object", NULL))
+		return soap->error;
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap->error;
+	soap->error = ns1__create_USCOREobject(soap, soap_tmp_ns1__create_USCOREobject.key, soap_tmp_ns1__create_USCOREobject.volume, &soap_tmp_string);
+	if (soap->error)
+		return soap->error;
+	soap_serializeheader(soap);
+	soap_serialize_ns1__create_USCOREobjectResponse(soap, &soap_tmp_ns1__create_USCOREobjectResponse);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__create_USCOREobjectResponse(soap, &soap_tmp_ns1__create_USCOREobjectResponse, "ns1:create_objectResponse", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	};
+	if (soap_response(soap, SOAP_OK)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__create_USCOREobjectResponse(soap, &soap_tmp_ns1__create_USCOREobjectResponse, "ns1:create_objectResponse", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap->error;
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__rename_USCOREobject(struct soap *soap)
+{	struct ns1__rename_USCOREobject soap_tmp_ns1__rename_USCOREobject;
+	struct ns1__rename_USCOREobjectResponse soap_tmp_ns1__rename_USCOREobjectResponse;
+	char * soap_tmp_string;
+	soap_default_ns1__rename_USCOREobjectResponse(soap, &soap_tmp_ns1__rename_USCOREobjectResponse);
+	soap_tmp_string = NULL;
+	soap_tmp_ns1__rename_USCOREobjectResponse.result = &soap_tmp_string;
+	soap_default_ns1__rename_USCOREobject(soap, &soap_tmp_ns1__rename_USCOREobject);
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	if (!soap_get_ns1__rename_USCOREobject(soap, &soap_tmp_ns1__rename_USCOREobject, "ns1:rename_object", NULL))
+		return soap->error;
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap->error;
+	soap->error = ns1__rename_USCOREobject(soap, soap_tmp_ns1__rename_USCOREobject.key, soap_tmp_ns1__rename_USCOREobject.newkey, &soap_tmp_string);
+	if (soap->error)
+		return soap->error;
+	soap_serializeheader(soap);
+	soap_serialize_ns1__rename_USCOREobjectResponse(soap, &soap_tmp_ns1__rename_USCOREobjectResponse);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__rename_USCOREobjectResponse(soap, &soap_tmp_ns1__rename_USCOREobjectResponse, "ns1:rename_objectResponse", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	};
+	if (soap_response(soap, SOAP_OK)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__rename_USCOREobjectResponse(soap, &soap_tmp_ns1__rename_USCOREobjectResponse, "ns1:rename_objectResponse", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap->error;
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__rename_USCOREobject_(struct soap *soap)
+{	struct ns1__rename_USCOREobject_ soap_tmp_ns1__rename_USCOREobject_;
+	struct ns1__rename_USCOREobject_Response soap_tmp_ns1__rename_USCOREobject_Response;
+	char * soap_tmp_string;
+	soap_default_ns1__rename_USCOREobject_Response(soap, &soap_tmp_ns1__rename_USCOREobject_Response);
+	soap_tmp_string = NULL;
+	soap_tmp_ns1__rename_USCOREobject_Response.result = &soap_tmp_string;
+	soap_default_ns1__rename_USCOREobject_(soap, &soap_tmp_ns1__rename_USCOREobject_);
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	if (!soap_get_ns1__rename_USCOREobject_(soap, &soap_tmp_ns1__rename_USCOREobject_, "ns1:rename_object", NULL))
+		return soap->error;
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap->error;
+	soap->error = ns1__rename_USCOREobject_(soap, soap_tmp_ns1__rename_USCOREobject_.key, soap_tmp_ns1__rename_USCOREobject_.newkey, &soap_tmp_string);
+	if (soap->error)
+		return soap->error;
+	soap_serializeheader(soap);
+	soap_serialize_ns1__rename_USCOREobject_Response(soap, &soap_tmp_ns1__rename_USCOREobject_Response);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__rename_USCOREobject_Response(soap, &soap_tmp_ns1__rename_USCOREobject_Response, "ns1:rename_object-Response", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	};
+	if (soap_response(soap, SOAP_OK)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__rename_USCOREobject_Response(soap, &soap_tmp_ns1__rename_USCOREobject_Response, "ns1:rename_object-Response", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap->error;
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__replicate_USCOREobject(struct soap *soap)
+{	struct ns1__replicate_USCOREobject soap_tmp_ns1__replicate_USCOREobject;
+	struct ns1__replicate_USCOREobjectResponse soap_tmp_ns1__replicate_USCOREobjectResponse;
+	char * soap_tmp_string;
+	soap_default_ns1__replicate_USCOREobjectResponse(soap, &soap_tmp_ns1__replicate_USCOREobjectResponse);
+	soap_tmp_string = NULL;
+	soap_tmp_ns1__replicate_USCOREobjectResponse.result = &soap_tmp_string;
+	soap_default_ns1__replicate_USCOREobject(soap, &soap_tmp_ns1__replicate_USCOREobject);
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	if (!soap_get_ns1__replicate_USCOREobject(soap, &soap_tmp_ns1__replicate_USCOREobject, "ns1:replicate_object", NULL))
+		return soap->error;
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap->error;
+	soap->error = ns1__replicate_USCOREobject(soap, soap_tmp_ns1__replicate_USCOREobject.key, soap_tmp_ns1__replicate_USCOREobject.volume, &soap_tmp_string);
+	if (soap->error)
+		return soap->error;
+	soap_serializeheader(soap);
+	soap_serialize_ns1__replicate_USCOREobjectResponse(soap, &soap_tmp_ns1__replicate_USCOREobjectResponse);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__replicate_USCOREobjectResponse(soap, &soap_tmp_ns1__replicate_USCOREobjectResponse, "ns1:replicate_objectResponse", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	};
+	if (soap_response(soap, SOAP_OK)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__replicate_USCOREobjectResponse(soap, &soap_tmp_ns1__replicate_USCOREobjectResponse, "ns1:replicate_objectResponse", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap->error;
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__lock_USCOREobject(struct soap *soap)
+{	struct ns1__lock_USCOREobject soap_tmp_ns1__lock_USCOREobject;
+	struct ns1__lock_USCOREobjectResponse soap_tmp_ns1__lock_USCOREobjectResponse;
+	int soap_tmp_int;
+	soap_default_ns1__lock_USCOREobjectResponse(soap, &soap_tmp_ns1__lock_USCOREobjectResponse);
+	soap_default_int(soap, &soap_tmp_int);
+	soap_tmp_ns1__lock_USCOREobjectResponse.result = &soap_tmp_int;
+	soap_default_ns1__lock_USCOREobject(soap, &soap_tmp_ns1__lock_USCOREobject);
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	if (!soap_get_ns1__lock_USCOREobject(soap, &soap_tmp_ns1__lock_USCOREobject, "ns1:lock_object", NULL))
+		return soap->error;
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap->error;
+	soap->error = ns1__lock_USCOREobject(soap, soap_tmp_ns1__lock_USCOREobject.key, soap_tmp_ns1__lock_USCOREobject.type, &soap_tmp_int);
+	if (soap->error)
+		return soap->error;
+	soap_serializeheader(soap);
+	soap_serialize_ns1__lock_USCOREobjectResponse(soap, &soap_tmp_ns1__lock_USCOREobjectResponse);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__lock_USCOREobjectResponse(soap, &soap_tmp_ns1__lock_USCOREobjectResponse, "ns1:lock_objectResponse", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	};
+	if (soap_response(soap, SOAP_OK)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__lock_USCOREobjectResponse(soap, &soap_tmp_ns1__lock_USCOREobjectResponse, "ns1:lock_objectResponse", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap->error;
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__unlock_USCOREobject(struct soap *soap)
+{	struct ns1__unlock_USCOREobject soap_tmp_ns1__unlock_USCOREobject;
+	struct ns1__unlock_USCOREobjectResponse soap_tmp_ns1__unlock_USCOREobjectResponse;
+	int soap_tmp_int;
+	soap_default_ns1__unlock_USCOREobjectResponse(soap, &soap_tmp_ns1__unlock_USCOREobjectResponse);
+	soap_default_int(soap, &soap_tmp_int);
+	soap_tmp_ns1__unlock_USCOREobjectResponse.result = &soap_tmp_int;
+	soap_default_ns1__unlock_USCOREobject(soap, &soap_tmp_ns1__unlock_USCOREobject);
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	if (!soap_get_ns1__unlock_USCOREobject(soap, &soap_tmp_ns1__unlock_USCOREobject, "ns1:unlock_object", NULL))
+		return soap->error;
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap->error;
+	soap->error = ns1__unlock_USCOREobject(soap, soap_tmp_ns1__unlock_USCOREobject.key, soap_tmp_ns1__unlock_USCOREobject.type, &soap_tmp_int);
+	if (soap->error)
+		return soap->error;
+	soap_serializeheader(soap);
+	soap_serialize_ns1__unlock_USCOREobjectResponse(soap, &soap_tmp_ns1__unlock_USCOREobjectResponse);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__unlock_USCOREobjectResponse(soap, &soap_tmp_ns1__unlock_USCOREobjectResponse, "ns1:unlock_objectResponse", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	};
+	if (soap_response(soap, SOAP_OK)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__unlock_USCOREobjectResponse(soap, &soap_tmp_ns1__unlock_USCOREobjectResponse, "ns1:unlock_objectResponse", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap->error;
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__find_USCOREobjects(struct soap *soap)
+{	struct ns1__find_USCOREobjects soap_tmp_ns1__find_USCOREobjects;
+	struct ns1__find_USCOREobjectsResponse param_1;
+	soap_default_ns1__find_USCOREobjectsResponse(soap, &param_1);
+	soap_default_ns1__find_USCOREobjects(soap, &soap_tmp_ns1__find_USCOREobjects);
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	if (!soap_get_ns1__find_USCOREobjects(soap, &soap_tmp_ns1__find_USCOREobjects, "ns1:find_objects", NULL))
+		return soap->error;
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap->error;
+	soap->error = ns1__find_USCOREobjects(soap, soap_tmp_ns1__find_USCOREobjects.pattern, &param_1);
+	if (soap->error)
+		return soap->error;
+	soap_serializeheader(soap);
+	soap_serialize_ns1__find_USCOREobjectsResponse(soap, &param_1);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__find_USCOREobjectsResponse(soap, &param_1, "ns1:find_objectsResponse", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	};
+	if (soap_response(soap, SOAP_OK)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__find_USCOREobjectsResponse(soap, &param_1, "ns1:find_objectsResponse", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap->error;
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__find_USCOREinstances(struct soap *soap)
+{	struct ns1__find_USCOREinstances soap_tmp_ns1__find_USCOREinstances;
+	struct ns1__find_USCOREinstancesResponse param_2;
+	soap_default_ns1__find_USCOREinstancesResponse(soap, &param_2);
+	soap_default_ns1__find_USCOREinstances(soap, &soap_tmp_ns1__find_USCOREinstances);
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	if (!soap_get_ns1__find_USCOREinstances(soap, &soap_tmp_ns1__find_USCOREinstances, "ns1:find_instances", NULL))
+		return soap->error;
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap->error;
+	soap->error = ns1__find_USCOREinstances(soap, soap_tmp_ns1__find_USCOREinstances.key, soap_tmp_ns1__find_USCOREinstances.volume, &param_2);
+	if (soap->error)
+		return soap->error;
+	soap_serializeheader(soap);
+	soap_serialize_ns1__find_USCOREinstancesResponse(soap, &param_2);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__find_USCOREinstancesResponse(soap, &param_2, "ns1:find_instancesResponse", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	};
+	if (soap_response(soap, SOAP_OK)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__find_USCOREinstancesResponse(soap, &param_2, "ns1:find_instancesResponse", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap->error;
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__delete_USCOREinstance(struct soap *soap)
+{	struct ns1__delete_USCOREinstance soap_tmp_ns1__delete_USCOREinstance;
+	struct ns1__delete_USCOREinstanceResponse soap_tmp_ns1__delete_USCOREinstanceResponse;
+	int soap_tmp_int;
+	soap_default_ns1__delete_USCOREinstanceResponse(soap, &soap_tmp_ns1__delete_USCOREinstanceResponse);
+	soap_default_int(soap, &soap_tmp_int);
+	soap_tmp_ns1__delete_USCOREinstanceResponse.result = &soap_tmp_int;
+	soap_default_ns1__delete_USCOREinstance(soap, &soap_tmp_ns1__delete_USCOREinstance);
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	if (!soap_get_ns1__delete_USCOREinstance(soap, &soap_tmp_ns1__delete_USCOREinstance, "ns1:delete_instance", NULL))
+		return soap->error;
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap->error;
+	soap->error = ns1__delete_USCOREinstance(soap, soap_tmp_ns1__delete_USCOREinstance.uri, &soap_tmp_int);
+	if (soap->error)
+		return soap->error;
+	soap_serializeheader(soap);
+	soap_serialize_ns1__delete_USCOREinstanceResponse(soap, &soap_tmp_ns1__delete_USCOREinstanceResponse);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__delete_USCOREinstanceResponse(soap, &soap_tmp_ns1__delete_USCOREinstanceResponse, "ns1:delete_instanceResponse", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	};
+	if (soap_response(soap, SOAP_OK)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__delete_USCOREinstanceResponse(soap, &soap_tmp_ns1__delete_USCOREinstanceResponse, "ns1:delete_instanceResponse", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap->error;
+	return soap_closesock(soap);
+}
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__stat_USCOREobject(struct soap *soap)
+{	struct ns1__stat_USCOREobject soap_tmp_ns1__stat_USCOREobject;
+	struct ns1__stat_USCOREobjectResponse param_3;
+	soap_default_ns1__stat_USCOREobjectResponse(soap, &param_3);
+	soap_default_ns1__stat_USCOREobject(soap, &soap_tmp_ns1__stat_USCOREobject);
+	soap->encodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
+	if (!soap_get_ns1__stat_USCOREobject(soap, &soap_tmp_ns1__stat_USCOREobject, "ns1:stat_object", NULL))
+		return soap->error;
+	if (soap_body_end_in(soap)
+	 || soap_envelope_end_in(soap)
+#ifndef WITH_LEANER
+	 || soap_resolve_attachments(soap)
+#endif
+	 || soap_end_recv(soap))
+		return soap->error;
+	soap->error = ns1__stat_USCOREobject(soap, soap_tmp_ns1__stat_USCOREobject.key, &param_3);
+	if (soap->error)
+		return soap->error;
+	soap_serializeheader(soap);
+	soap_serialize_ns1__stat_USCOREobjectResponse(soap, &param_3);
+	soap_begin_count(soap);
+	if (soap->mode & SOAP_IO_LENGTH)
+	{	soap_envelope_begin_out(soap);
+		soap_putheader(soap);
+		soap_body_begin_out(soap);
+		soap_put_ns1__stat_USCOREobjectResponse(soap, &param_3, "ns1:stat_objectResponse", "");
+		soap_body_end_out(soap);
+		soap_envelope_end_out(soap);
+	};
+	if (soap_response(soap, SOAP_OK)
+	 || soap_envelope_begin_out(soap)
+	 || soap_putheader(soap)
+	 || soap_body_begin_out(soap)
+	 || soap_put_ns1__stat_USCOREobjectResponse(soap, &param_3, "ns1:stat_objectResponse", "")
+	 || soap_body_end_out(soap)
+	 || soap_envelope_end_out(soap)
+	 || soap_end_send(soap))
+		return soap->error;
+	return soap_closesock(soap);
+}
+
+SOAP_END_NAMESPACE(soap)
+
+#ifdef __cplusplus
+}
+#endif
+
+/* End of soapServer.c */
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapServerLib.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapServerLib.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapServerLib.c	(revision 21994)
@@ -0,0 +1,14 @@
+/* soapServerLib.c
+   Generated by gSOAP 2.7.2 from src/nebulous.h
+   Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc. All Rights Reserved.
+   This part of the software is released under one of the following licenses:
+   GPL, the gSOAP public license, or Genivia's license for commercial use.
+*/
+#ifndef WITH_NOGLOBAL
+#define WITH_NOGLOBAL
+#endif
+#define SOAP_FMAC3 static
+#include "soapC.c"
+#include "soapServer.c"
+
+/* End of soapServerLib.c */
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapStub.h
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapStub.h	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/soapStub.h	(revision 21994)
@@ -0,0 +1,315 @@
+/* soapStub.h
+   Generated by gSOAP 2.7.2 from src/nebulous.h
+   Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc. All Rights Reserved.
+   This part of the software is released under one of the following licenses:
+   GPL, the gSOAP public license, or Genivia's license for commercial use.
+*/
+#ifndef soapStub_H
+#define soapStub_H
+#include "stdsoap2.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SOAP_BEGIN_NAMESPACE(soap)
+
+/******************************************************************************\
+ *                                                                            *
+ * Enumerations                                                               *
+ *                                                                            *
+\******************************************************************************/
+
+
+/******************************************************************************\
+ *                                                                            *
+ * Classes and Structs                                                        *
+ *                                                                            *
+\******************************************************************************/
+
+
+/* SOAP encoded array of xsd:string schema type: */
+struct ArrayOfString
+{
+	char **__ptr;
+	int __size;
+};
+
+/* ns1:create_objectResponse: */
+struct ns1__create_USCOREobjectResponse
+{
+	char **result;	/* RPC return element */	/* optional element of type xsd:string */
+};
+
+/* ns1:create_object: */
+struct ns1__create_USCOREobject
+{
+	char *key;	/* optional element of type xsd:string */
+	char *volume;	/* optional element of type xsd:string */
+};
+
+/* ns1:rename_objectResponse: */
+struct ns1__rename_USCOREobjectResponse
+{
+	char **result;	/* RPC return element */	/* optional element of type xsd:string */
+};
+
+/* ns1:rename_object: */
+struct ns1__rename_USCOREobject
+{
+	char *key;	/* optional element of type xsd:string */
+	char *newkey;	/* optional element of type xsd:string */
+};
+
+/* ns1:rename_object-Response: */
+struct ns1__rename_USCOREobject_Response
+{
+	char **result;	/* RPC return element */	/* optional element of type xsd:string */
+};
+
+/* ns1:rename_object: */
+struct ns1__rename_USCOREobject_
+{
+	char *key;	/* optional element of type xsd:string */
+	char *newkey;	/* optional element of type xsd:string */
+};
+
+/* ns1:replicate_objectResponse: */
+struct ns1__replicate_USCOREobjectResponse
+{
+	char **result;	/* RPC return element */	/* optional element of type xsd:string */
+};
+
+/* ns1:replicate_object: */
+struct ns1__replicate_USCOREobject
+{
+	char *key;	/* optional element of type xsd:string */
+	char *volume;	/* optional element of type xsd:string */
+};
+
+/* ns1:lock_objectResponse: */
+struct ns1__lock_USCOREobjectResponse
+{
+	int *result;	/* RPC return element */	/* optional element of type xsd:int */
+};
+
+/* ns1:lock_object: */
+struct ns1__lock_USCOREobject
+{
+	char *key;	/* optional element of type xsd:string */
+	char *type;	/* optional element of type xsd:string */
+};
+
+/* ns1:unlock_objectResponse: */
+struct ns1__unlock_USCOREobjectResponse
+{
+	int *result;	/* RPC return element */	/* optional element of type xsd:int */
+};
+
+/* ns1:unlock_object: */
+struct ns1__unlock_USCOREobject
+{
+	char *key;	/* optional element of type xsd:string */
+	char *type;	/* optional element of type xsd:string */
+};
+
+/* ns1:find_objectsResponse: */
+struct ns1__find_USCOREobjectsResponse
+{
+	struct ArrayOfString *result;	/* RPC return element */	/* optional element of type ArrayOfstring */
+};
+
+/* ns1:find_objects: */
+struct ns1__find_USCOREobjects
+{
+	char *pattern;	/* optional element of type xsd:string */
+};
+
+/* ns1:find_instancesResponse: */
+struct ns1__find_USCOREinstancesResponse
+{
+	struct ArrayOfString *result;	/* RPC return element */	/* optional element of type ArrayOfstring */
+};
+
+/* ns1:find_instances: */
+struct ns1__find_USCOREinstances
+{
+	char *key;	/* optional element of type xsd:string */
+	char *volume;	/* optional element of type xsd:string */
+};
+
+/* ns1:delete_instanceResponse: */
+struct ns1__delete_USCOREinstanceResponse
+{
+	int *result;	/* RPC return element */	/* optional element of type xsd:int */
+};
+
+/* ns1:delete_instance: */
+struct ns1__delete_USCOREinstance
+{
+	char *uri;	/* optional element of type xsd:string */
+};
+
+/* ns1:stat_objectResponse: */
+struct ns1__stat_USCOREobjectResponse
+{
+	struct ArrayOfString *result;	/* RPC return element */	/* optional element of type ArrayOfstring */
+};
+
+/* ns1:stat_object: */
+struct ns1__stat_USCOREobject
+{
+	char *key;	/* optional element of type xsd:string */
+};
+
+/* SOAP Header: */
+struct SOAP_ENV__Header
+{
+	void *dummy;	/* transient */
+};
+
+/* SOAP Fault Code: */
+struct SOAP_ENV__Code
+{
+	char *SOAP_ENV__Value;	/* optional element of type QName */
+	struct SOAP_ENV__Code *SOAP_ENV__Subcode;	/* optional element of type SOAP-ENV:Code */
+};
+
+/* SOAP-ENV:Detail: */
+struct SOAP_ENV__Detail
+{
+	int __type;	/* any type of element <fault> (defined below) */
+	void *fault;	/* transient */
+	char *__any;
+};
+
+/* SOAP Fault: */
+struct SOAP_ENV__Fault
+{
+	char *faultcode;	/* optional element of type QName */
+	char *faultstring;	/* optional element of type xsd:string */
+	char *faultactor;	/* optional element of type xsd:string */
+	struct SOAP_ENV__Detail *detail;	/* optional element of type SOAP-ENV:Detail */
+	struct SOAP_ENV__Code *SOAP_ENV__Code;	/* optional element of type SOAP-ENV:Code */
+	char *SOAP_ENV__Reason;	/* optional element of type xsd:string */
+	char *SOAP_ENV__Node;	/* optional element of type xsd:string */
+	char *SOAP_ENV__Role;	/* optional element of type xsd:string */
+	struct SOAP_ENV__Detail *SOAP_ENV__Detail;	/* optional element of type SOAP-ENV:Detail */
+};
+
+/******************************************************************************\
+ *                                                                            *
+ * Types with Custom Serializers                                              *
+ *                                                                            *
+\******************************************************************************/
+
+
+/******************************************************************************\
+ *                                                                            *
+ * Typedefs                                                                   *
+ *                                                                            *
+\******************************************************************************/
+
+typedef char *_XML;
+typedef char *_QName;
+typedef char *SOAP_ENC__arrayType;
+
+/******************************************************************************\
+ *                                                                            *
+ * Externals                                                                  *
+ *                                                                            *
+\******************************************************************************/
+
+
+/******************************************************************************\
+ *                                                                            *
+ * Service Operations                                                         *
+ *                                                                            *
+\******************************************************************************/
+
+
+SOAP_FMAC5 int SOAP_FMAC6 ns1__create_USCOREobject(struct soap*, char *key, char *volume, char **result);
+
+SOAP_FMAC5 int SOAP_FMAC6 ns1__rename_USCOREobject(struct soap*, char *key, char *newkey, char **result);
+
+SOAP_FMAC5 int SOAP_FMAC6 ns1__rename_USCOREobject_(struct soap*, char *key, char *newkey, char **result);
+
+SOAP_FMAC5 int SOAP_FMAC6 ns1__replicate_USCOREobject(struct soap*, char *key, char *volume, char **result);
+
+SOAP_FMAC5 int SOAP_FMAC6 ns1__lock_USCOREobject(struct soap*, char *key, char *type, int *result);
+
+SOAP_FMAC5 int SOAP_FMAC6 ns1__unlock_USCOREobject(struct soap*, char *key, char *type, int *result);
+
+SOAP_FMAC5 int SOAP_FMAC6 ns1__find_USCOREobjects(struct soap*, char *pattern, struct ns1__find_USCOREobjectsResponse *param_1);
+
+SOAP_FMAC5 int SOAP_FMAC6 ns1__find_USCOREinstances(struct soap*, char *key, char *volume, struct ns1__find_USCOREinstancesResponse *param_2);
+
+SOAP_FMAC5 int SOAP_FMAC6 ns1__delete_USCOREinstance(struct soap*, char *uri, int *result);
+
+SOAP_FMAC5 int SOAP_FMAC6 ns1__stat_USCOREobject(struct soap*, char *key, struct ns1__stat_USCOREobjectResponse *param_3);
+
+/******************************************************************************\
+ *                                                                            *
+ * Stubs                                                                      *
+ *                                                                            *
+\******************************************************************************/
+
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__create_USCOREobject(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *key, char *volume, char **result);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__rename_USCOREobject(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *key, char *newkey, char **result);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__rename_USCOREobject_(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *key, char *newkey, char **result);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__replicate_USCOREobject(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *key, char *volume, char **result);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__lock_USCOREobject(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *key, char *type, int *result);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__unlock_USCOREobject(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *key, char *type, int *result);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__find_USCOREobjects(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *pattern, struct ns1__find_USCOREobjectsResponse *param_1);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__find_USCOREinstances(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *key, char *volume, struct ns1__find_USCOREinstancesResponse *param_2);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__delete_USCOREinstance(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *uri, int *result);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__stat_USCOREobject(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *key, struct ns1__stat_USCOREobjectResponse *param_3);
+
+/******************************************************************************\
+ *                                                                            *
+ * Skeletons                                                                  *
+ *                                                                            *
+\******************************************************************************/
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve(struct soap*);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_request(struct soap*);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__create_USCOREobject(struct soap*);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__rename_USCOREobject(struct soap*);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__rename_USCOREobject_(struct soap*);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__replicate_USCOREobject(struct soap*);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__lock_USCOREobject(struct soap*);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__unlock_USCOREobject(struct soap*);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__find_USCOREobjects(struct soap*);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__find_USCOREinstances(struct soap*);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__delete_USCOREinstance(struct soap*);
+
+SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__stat_USCOREobject(struct soap*);
+
+SOAP_END_NAMESPACE(soap)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/* End of soapStub.h */
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/stdsoap2.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/stdsoap2.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/stdsoap2.c	(revision 21994)
@@ -0,0 +1,11690 @@
+/*
+
+stdsoap2.c[pp] 2.7.0d
+
+Runtime environment.
+
+gSOAP XML Web services tools
+Copyright (C) 2000-2004, Robert van Engelen, Genivia, Inc., All Rights Reserved.
+
+Contributors:
+
+Wind River Systems, Inc., for the following additions (marked WR[...]):
+  - vxWorks compatible
+  - Support for IPv6.
+
+--------------------------------------------------------------------------------
+gSOAP public license.
+
+The contents of this file are subject to the gSOAP Public License Version 1.3
+(the "License"); you may not use this file except in compliance with the
+License. You may obtain a copy of the License at
+http://www.cs.fsu.edu/~engelen/soaplicense.html
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+for the specific language governing rights and limitations under the License.
+
+The Initial Developer of the Original Code is Robert A. van Engelen.
+Copyright (C) 2000-2004, Robert van Engelen, Genivia, Inc., All Rights Reserved.
+--------------------------------------------------------------------------------
+GPL license.
+
+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.
+
+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
+
+Author contact information:
+engelen@genivia.com / engelen@acm.org
+--------------------------------------------------------------------------------
+
+Installation note:
+
+Win32 build needs winsock.dll (Visual C++ "wsock32.lib")
+To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link"
+tab (the project file needs to be selected in the file view) and add
+"wsock32.lib" to the "Object/library modules" entry
+
+On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with
+-fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack
+when locally allocated data exceeds 64K.
+
+*/
+
+#include "stdsoap2.h"
+
+#ifdef __cplusplus
+SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.0c 2004-09-27 12:00:00 GMT")
+extern "C" {
+#else
+SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.0c 2004-09-27 12:00:00 GMT")
+#endif
+
+/* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale) */
+#ifndef SOAP_UNKNOWN_CHAR
+#define SOAP_UNKNOWN_CHAR (127)
+#endif
+
+/*      EOF=-1 */
+#define SOAP_LT (soap_wchar)(-2) /* XML character '<' */
+#define SOAP_TT (soap_wchar)(-3) /* XML character '</' */
+#define SOAP_GT (soap_wchar)(-4) /* XML character '>' */
+#define SOAP_QT (soap_wchar)(-5) /* XML character '"' */
+#define SOAP_AP (soap_wchar)(-6) /* XML character ''' */
+
+#define soap_blank(c)		((c) >= 0 && (c) <= 32)
+#define soap_notblank(c)	((c) > 32)
+#define soap_hash_ptr(p)	(((unsigned long)(p) >> 3) & (SOAP_PTRHASH - 1))
+
+static int soap_isxdigit(int);
+static soap_wchar soap_char(struct soap*);
+static soap_wchar soap_getchunkchar(struct soap*);
+static void soap_update_ptrs(struct soap*, char*, char*, long);
+static int soap_has_copies(struct soap*, const char*, const char*);
+static struct soap_ilist *soap_hlookup(struct soap*, const char*);
+static void soap_init_iht(struct soap*);
+static void soap_free_iht(struct soap*);
+static void soap_init_pht(struct soap*);
+static void soap_free_pht(struct soap*);
+static int soap_set_error(struct soap*, const char*, const char*, const char*, int);
+static const char *soap_set_validation_fault(struct soap*, const char*, const char*);
+static int soap_copy_fault(struct soap*, const char*, const char*, const char*);
+static int soap_getattrval(struct soap*, char*, size_t, soap_wchar);
+static void soap_set_local_namespaces(struct soap*);
+static int soap_isnumeric(struct soap*, const char*);
+static void *fplugin(struct soap*, const char*);
+static const char *soap_decode(char*, size_t, const char*, const char*);
+
+#ifndef WITH_LEAN
+static time_t soap_timegm(struct tm*);
+#endif
+
+#ifdef SOAP_DEBUG
+static void soap_init_logs(struct soap*);
+static void soap_close_logfile(struct soap*, int);
+static void soap_set_logfile(struct soap*, int, const char*);
+#endif
+
+#ifdef WITH_FAST
+static int soap_append_lab(struct soap*, const char*, size_t);
+#endif
+
+#ifndef WITH_LEANER
+static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t);
+static int soap_putdimefield(struct soap*, const char*, size_t);
+static char *soap_getdimefield(struct soap*, size_t);
+static void soap_select_mime_boundary(struct soap*);
+static int soap_valid_mime_boundary(struct soap*);
+#endif
+
+#ifdef WITH_GZIP
+static int soap_getgziphdr(struct soap*);
+#endif
+
+#ifdef WITH_OPENSSL
+static int ssl_auth_init(struct soap*);
+static int ssl_verify_callback(int, X509_STORE_CTX*);
+static int ssl_password(char*, int, int, void *);
+static const char *ssl_error(struct soap*, int);
+/* This callback is included for future references. It should not be deleted
+static DH *ssl_tmp_dh(SSL*, int, int);
+*/
+#endif
+
+static const char *soap_strerror(struct soap*);
+static const char *tcp_error(struct soap*);
+static const char *http_error(struct soap*, int);
+static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t);
+static int http_get(struct soap*);
+static int http_send_header(struct soap*, const char*);
+static int http_post_header(struct soap*, const char*, const char*);
+static int http_response(struct soap*, int, size_t);
+static int http_parse(struct soap*);
+static int http_parse_header(struct soap*, const char*, const char*);
+#ifndef MAC_CARBON
+static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr);
+static int tcp_connect(struct soap*, const char *endpoint, const char *host, int port);
+static int tcp_accept(struct soap*, int, struct sockaddr*, int*);
+static int tcp_disconnect(struct soap*);
+static int tcp_closesocket(struct soap*, SOAP_SOCKET);
+static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int);
+static int fsend(struct soap*, const char*, size_t);
+static size_t frecv(struct soap*, char*, size_t);
+#endif
+
+/* WR[ */
+#ifdef VXWORKS
+static int vx_nonblocking = TRUE; /* ioctl argument */
+#endif
+/* ]WR */
+
+#if defined(PALM) && !defined(PALM_2)
+unsigned short errno;
+#endif
+
+#ifndef PALM_1
+static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/";
+static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/";
+static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope";
+static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding";
+static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc";
+#endif
+
+#ifndef PALM_1
+const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF};
+static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63";
+#endif
+
+static const char soap_padding[3] = "\0\0";
+#define SOAP_STR_PADDING (soap_padding)
+#define SOAP_STR_EOS (soap_padding)
+
+#ifndef WITH_LEAN
+static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */
+{ { 160, "nbsp" },
+  { 161, "iexcl" },
+  { 162, "cent" },
+  { 163, "pound" },
+  { 164, "curren" },
+  { 165, "yen" },
+  { 166, "brvbar" },
+  { 167, "sect" },
+  { 168, "uml" },
+  { 169, "copy" },
+  { 170, "ordf" },
+  { 171, "laquo" },
+  { 172, "not" },
+  { 173, "shy" },
+  { 174, "reg" },
+  { 175, "macr" },
+  { 176, "deg" },
+  { 177, "plusmn" },
+  { 178, "sup2" },
+  { 179, "sup3" },
+  { 180, "acute" },
+  { 181, "micro" },
+  { 182, "para" },
+  { 183, "middot" },
+  { 184, "cedil" },
+  { 185, "sup1" },
+  { 186, "ordm" },
+  { 187, "raquo" },
+  { 188, "frac14" },
+  { 189, "frac12" },
+  { 190, "frac34" },
+  { 191, "iquest" },
+  { 192, "Agrave" },
+  { 193, "Aacute" },
+  { 194, "Acirc" },
+  { 195, "Atilde" },
+  { 196, "Auml" },
+  { 197, "Aring" },
+  { 198, "AElig" },
+  { 199, "Ccedil" },
+  { 200, "Egrave" },
+  { 201, "Eacute" },
+  { 202, "Ecirc" },
+  { 203, "Euml" },
+  { 204, "Igrave" },
+  { 205, "Iacute" },
+  { 206, "Icirc" },
+  { 207, "Iuml" },
+  { 208, "ETH" },
+  { 209, "Ntilde" },
+  { 210, "Ograve" },
+  { 211, "Oacute" },
+  { 212, "Ocirc" },
+  { 213, "Otilde" },
+  { 214, "Ouml" },
+  { 215, "times" },
+  { 216, "Oslash" },
+  { 217, "Ugrave" },
+  { 218, "Uacute" },
+  { 219, "Ucirc" },
+  { 220, "Uuml" },
+  { 221, "Yacute" },
+  { 222, "THORN" },
+  { 223, "szlig" },
+  { 224, "agrave" },
+  { 225, "aacute" },
+  { 226, "acirc" },
+  { 227, "atilde" },
+  { 228, "auml" },
+  { 229, "aring" },
+  { 230, "aelig" },
+  { 231, "ccedil" },
+  { 232, "egrave" },
+  { 233, "eacute" },
+  { 234, "ecirc" },
+  { 235, "euml" },
+  { 236, "igrave" },
+  { 237, "iacute" },
+  { 238, "icirc" },
+  { 239, "iuml" },
+  { 240, "eth" },
+  { 241, "ntilde" },
+  { 242, "ograve" },
+  { 243, "oacute" },
+  { 244, "ocirc" },
+  { 245, "otilde" },
+  { 246, "ouml" },
+  { 247, "divide" },
+  { 248, "oslash" },
+  { 249, "ugrave" },
+  { 250, "uacute" },
+  { 251, "ucirc" },
+  { 252, "uuml" },
+  { 253, "yacute" },
+  { 254, "thorn" },
+  { 255, "yuml" },
+  {   0, NULL }
+};
+#endif
+
+#ifndef WITH_LEAN
+static const struct soap_code_map h_error_codes[] =
+{
+#ifdef HOST_NOT_FOUND   
+  { HOST_NOT_FOUND, "Host not found" },
+#endif
+#ifdef TRY_AGAIN
+  { TRY_AGAIN, "Try Again" },
+#endif
+#ifdef NO_RECOVERY  
+  { NO_RECOVERY, "No Recovery" },
+#endif
+#ifdef NO_DATA
+  { NO_DATA, "No Data" },
+#endif
+#ifdef NO_ADDRESS
+  { NO_ADDRESS, "No Address" },
+#endif
+  { 0, NULL }
+};
+#endif
+
+#ifndef WITH_LEAN
+static const struct soap_code_map h_http_error_codes[] =
+{ { 201, "Created" },
+  { 202, "Accepted" },
+  { 203, "Non-Authoritative Information" },
+  { 204, "No Content" },
+  { 205, "Reset Content" },
+  { 206, "Partial Content" },
+  { 300, "Multiple Choices" },
+  { 301, "Moved Permanently" },
+  { 302, "Found" },
+  { 303, "See Other" },
+  { 304, "Not Modified" },
+  { 305, "Use Proxy" },
+  { 307, "Temporary Redirect" },
+  { 400, "Bad Request" },
+  { 401, "Unauthorized" },
+  { 402, "Payment Required" },
+  { 403, "Forbidden" },
+  { 404, "Not Found" },
+  { 405, "Method Not Allowed" },
+  { 406, "Not Acceptable" },
+  { 407, "Proxy Authentication Required" },
+  { 408, "Request Time-out" },
+  { 409, "Conflict" },
+  { 410, "Gone" },
+  { 411, "Length Required" },
+  { 412, "Precondition Failed" },
+  { 413, "Request Entity Too Large" },
+  { 414, "Request-URI Too Large" },
+  { 415, "Unsupported Media Type" },
+  { 416, "Requested range not satisfiable" },
+  { 417, "Expectation Failed" },
+  { 500, "Internal Server Error" },
+  { 501, "Not Implemented" },
+  { 502, "Bad Gateway" },
+  { 503, "Service Unavailable" },
+  { 504, "Gateway Time-out" },
+  { 505, "HTTP Version not supported" },
+  {   0, NULL }
+};
+#endif
+
+#ifdef WITH_OPENSSL
+static const struct soap_code_map h_ssl_error_codes[] =
+{
+#define _SSL_ERROR(e) { e, #e }
+  _SSL_ERROR(SSL_ERROR_SSL),
+  _SSL_ERROR(SSL_ERROR_ZERO_RETURN),
+  _SSL_ERROR(SSL_ERROR_WANT_READ),
+  _SSL_ERROR(SSL_ERROR_WANT_WRITE),
+  _SSL_ERROR(SSL_ERROR_WANT_CONNECT),
+  _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP),
+  _SSL_ERROR(SSL_ERROR_SYSCALL),
+  { 0, NULL }
+};
+#endif
+
+#ifndef WITH_LEANER
+static const struct soap_code_map mime_codes[] =
+{ { SOAP_MIME_7BIT,		"7bit" },
+  { SOAP_MIME_8BIT,		"8bit" },
+  { SOAP_MIME_BINARY,		"binary" },
+  { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" },
+  { SOAP_MIME_BASE64,		"base64" },
+  { SOAP_MIME_IETF_TOKEN,	"ietf-token" },
+  { SOAP_MIME_X_TOKEN,		"x-token" },
+  { 0,				NULL }
+};
+#endif
+
+#ifdef WIN32
+static int tcp_done = 0;
+#endif
+
+/******************************************************************************/
+#ifndef MAC_CARBON
+#ifndef PALM_1
+static int
+fsend(struct soap *soap, const char *s, size_t n)
+{ register int nwritten;
+#if defined(__cplusplus) && !defined(WITH_LEAN)
+  if (soap->os)
+  { soap->os->write(s, n);
+    if (soap->os->good())
+      return SOAP_OK;
+    return SOAP_EOF;
+  }
+#endif
+  while (n)
+  { if (soap_valid_socket(soap->socket))
+    { 
+#ifndef WITH_LEAN
+      if (soap->send_timeout)
+      { struct timeval timeout;
+        fd_set fd;
+        if (soap->send_timeout > 0)
+        { timeout.tv_sec = soap->send_timeout;
+          timeout.tv_usec = 0;
+        }
+        else
+        { timeout.tv_sec = -soap->send_timeout/1000000;
+          timeout.tv_usec = -soap->send_timeout%1000000;
+        }
+        FD_ZERO(&fd);
+        FD_SET((SOAP_SOCKET)soap->socket, &fd);
+        for (;;)
+        { register int r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout);
+          if (r > 0)
+            break;
+          if (!r)
+          { soap->errnum = 0;
+            return SOAP_EOF;
+          }
+          if (soap_socket_errno != SOAP_EINTR)
+          { soap->errnum = soap_socket_errno;
+            return SOAP_EOF;
+          }
+        }
+      }
+#endif
+#ifdef WITH_OPENSSL
+      if (soap->ssl)
+        nwritten = SSL_write(soap->ssl, s, n);
+      else
+#endif
+#ifndef PALM
+        nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags);
+#else
+        nwritten = send((SOAP_SOCKET)soap->socket, (void*)s, n, soap->socket_flags);
+#endif
+      if (nwritten <= 0)
+      {
+#ifdef WITH_OPENSSL
+	int err;
+        if (soap->ssl && (err = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
+          return SOAP_EOF;
+#endif
+        if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EWOULDBLOCK && soap_socket_errno != SOAP_EAGAIN)
+        { soap->errnum = soap_socket_errno;
+          return SOAP_EOF;
+        }
+        nwritten = 0; /* and call write() again */
+      }
+    }
+    else
+    {
+#ifdef WITH_FASTCGI
+      nwritten = fwrite((void*)s, 1, n, stdout);
+      fflush(stdout);
+#else
+#ifdef UNDER_CE
+      nwritten = fwrite(s, 1, n, soap->sendfd);
+#else
+/* WR[ */
+#ifdef VXWORKS
+#ifdef WMW_RPM_IO
+      if (soap->rpmreqid)
+          {
+          httpBlockPut(soap->rpmreqid, s, n); 
+          nwritten = n;
+          }
+      else
+          {
+          nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w"));
+          }
+#else
+      nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w"));
+#endif /* WMW_RPM_IO */
+#else
+/* ]WR */
+      nwritten = write((SOAP_SOCKET)soap->sendfd, s, n);
+/* WR[ */
+#endif
+/* ]WR */
+#endif
+#endif
+      if (nwritten <= 0)
+      { if (soap_errno != SOAP_EINTR && soap_errno != SOAP_EWOULDBLOCK && soap_errno != SOAP_EAGAIN)
+        { soap->errnum = soap_errno;
+          return SOAP_EOF;
+        }
+        nwritten = 0; /* and call write() again */
+      }
+    }
+    n -= nwritten;
+    s += nwritten;
+  }
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_flush_raw(struct soap *soap, const char *s, size_t n)
+{ if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
+  { register char *t;
+    if (!(t = (char*)soap_push_block(soap, n)))
+      return soap->error = SOAP_EOM;
+    memcpy(t, s, n);
+    if (soap->fpreparesend)
+      return soap->fpreparesend(soap, s, n);
+    return SOAP_OK;
+  }
+  if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
+  { char t[16];
+    sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n);
+    DBGMSG(SENT, t, strlen(t));
+    if ((soap->error = soap->fsend(soap, t, strlen(t))))
+      return soap->error;
+    soap->chunksize += n;
+  }
+  DBGMSG(SENT, s, n);
+  return soap->error = soap->fsend(soap, s, n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_flush(struct soap *soap)
+{ if (soap->bufidx)
+  {
+#ifdef WITH_ZLIB
+    if (soap->mode & SOAP_ENC_ZLIB)
+    { soap->d_stream.next_in = (Byte*)soap->buf;
+      soap->d_stream.avail_in = (unsigned int)soap->bufidx;
+#ifdef WITH_GZIP
+      soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->bufidx);
+#endif
+      do
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream.avail_in));
+        if (deflate(&soap->d_stream, Z_NO_FLUSH) != Z_OK)
+        { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:""));
+          return soap->error = SOAP_ZLIB_ERROR;
+        }
+        if (!soap->d_stream.avail_out)
+        { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN))
+            return soap->error;
+          soap->d_stream.next_out = (Byte*)soap->z_buf;
+          soap->d_stream.avail_out = SOAP_BUFLEN;
+        }
+      } while (soap->d_stream.avail_in);
+    }
+    else
+#endif
+    if (soap_flush_raw(soap, soap->buf, soap->bufidx))
+      return soap->error;
+    soap->bufidx = 0;
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_send_raw(struct soap *soap, const char *s, size_t n)
+{ if (!n)
+    return SOAP_OK;
+  if (soap->mode & SOAP_IO_LENGTH)
+  { soap->count += n;
+    if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE)
+      return soap->fpreparesend(soap, s, n);
+    return SOAP_OK;
+  }
+  if (soap->mode & SOAP_IO)
+  { register size_t i = SOAP_BUFLEN - soap->bufidx;
+    while (n >= i)
+    { memcpy(soap->buf + soap->bufidx, s, i);
+      soap->bufidx = SOAP_BUFLEN;
+      if (soap_flush(soap))
+        return soap->error;
+      s += i;
+      n -= i;
+      i = SOAP_BUFLEN;
+    }
+    memcpy(soap->buf + soap->bufidx, s, n);
+    soap->bufidx += n;
+    return SOAP_OK;
+  }
+  return soap_flush_raw(soap, s, n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_send(struct soap *soap, const char *s)
+{ if (s)
+    return soap_send_raw(soap, s, strlen(s));
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_send2(struct soap *soap, const char *s1, const char *s2)
+{ if (soap_send(soap, s1))
+    return soap->error;
+  return soap_send(soap, s2);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3)
+{ if (soap_send(soap, s1)
+   || soap_send(soap, s2))
+    return soap->error;
+  return soap_send(soap, s3);
+}
+#endif
+
+/******************************************************************************/
+#ifndef MAC_CARBON
+#ifndef PALM_1
+static size_t
+frecv(struct soap *soap, char *s, size_t n)
+{ register int r;
+  soap->errnum = 0;
+#if defined(__cplusplus) && !defined(WITH_LEAN)
+  if (soap->is)
+  { if (soap->is->good())
+      return soap->is->read(s, n).gcount();
+    return 0;
+  }
+#endif
+  if (soap_valid_socket(soap->socket))
+  { for (;;)
+    { 
+#ifndef WITH_LEAN
+      struct timeval timeout;
+      fd_set fd;
+      if (soap->recv_timeout)
+      { if (soap->recv_timeout > 0)
+        { timeout.tv_sec = soap->recv_timeout;
+          timeout.tv_usec = 0;
+        }
+        else
+        { timeout.tv_sec = -soap->recv_timeout/1000000;
+          timeout.tv_usec = -soap->recv_timeout%1000000;
+        }
+        FD_ZERO(&fd);
+        FD_SET((SOAP_SOCKET)soap->socket, &fd);
+        for (;;)
+        { r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout);
+          if (r > 0)
+            break;
+          if (r == 0)
+            return 0;
+          if (soap_socket_errno != SOAP_EINTR)
+          { soap->errnum = soap_socket_errno;
+            return 0;
+          }
+        }
+      }
+#endif
+#ifdef WITH_OPENSSL
+      if (soap->ssl)
+      { int err;
+	r = SSL_read(soap->ssl, s, n);
+        if ((err = SSL_get_error(soap->ssl, r)) == SSL_ERROR_NONE)
+          return (size_t)r;
+	if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
+          return 0;
+      }
+      else
+#endif
+      { r = recv((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags);
+        if (r >= 0)
+          return (size_t)r;
+        if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN)
+        { soap->errnum = soap_socket_errno;
+          return 0;
+        }
+      }
+#ifndef WITH_LEAN
+      { struct timeval timeout;
+        fd_set fd;
+        timeout.tv_sec = 0;
+        timeout.tv_usec = 10000;
+        FD_ZERO(&fd);
+        FD_SET((SOAP_SOCKET)soap->socket, &fd);
+        r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout);
+        if (r < 0 && soap_socket_errno != SOAP_EINTR)
+        { soap->errnum = soap_socket_errno;
+          return 0;
+        }
+      }
+#endif
+    }
+  }
+#ifdef WITH_FASTCGI
+  return fread(s, 1, n, stdin);
+#else
+#ifdef UNDER_CE
+  return fread(s, 1, n, soap->recvfd);
+#else
+/* WR[ */
+#ifdef WMW_RPM_IO
+  if (soap->rpmreqid)
+    r = httpBlockRead(soap->rpmreqid, s, n);
+  else
+    r = read(soap->recvfd, s, n);
+  if (r >= 0)
+    return r;
+  return 0;
+#else
+/* ]WR */
+  r = read((SOAP_SOCKET)soap->recvfd, s, n);
+  if (r >= 0)
+    return (size_t)r;
+  soap->errnum = soap_errno;
+  return 0;
+/* WR[ */
+#endif
+/* ]WR */
+#endif
+#endif
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static soap_wchar
+soap_getchunkchar(struct soap *soap)
+{ if (soap->bufidx < soap->buflen)
+    return soap->buf[soap->bufidx++];
+  soap->bufidx = 0;
+  soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes\n", (unsigned int)soap->buflen));
+  DBGMSG(RECV, soap->buf, soap->buflen);
+  if (soap->buflen)
+    return soap->buf[soap->bufidx++];
+  return EOF;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static int
+soap_isxdigit(int c)
+{ switch (c)
+  { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+      return 1;
+  }
+  return 0;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_recv_raw(struct soap *soap)
+{ register size_t ret;
+#ifdef WITH_ZLIB
+  if (soap->mode & SOAP_ENC_ZLIB)
+  { if (soap->d_stream.next_out == Z_NULL)
+      return EOF;
+    if (soap->d_stream.avail_in || !soap->d_stream.avail_out)
+    { register int r;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n"));
+      soap->d_stream.next_out = (Byte*)soap->buf;
+      soap->d_stream.avail_out = SOAP_BUFLEN;
+      r = inflate(&soap->d_stream, Z_NO_FLUSH);
+      if (r == Z_OK || r == Z_STREAM_END)
+      { soap->bufidx = 0;
+        soap->buflen = SOAP_BUFLEN - soap->d_stream.avail_out;
+        if (soap->zlib_in == SOAP_ZLIB_GZIP)
+          soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
+        if (r == Z_STREAM_END)
+        { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out));
+          soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out;
+          soap->d_stream.next_out = Z_NULL;
+        }
+        if (soap->buflen)
+        { soap->count += soap->buflen;
+          return SOAP_OK;
+        }
+      }
+      else if (r != Z_BUF_ERROR)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream.msg?soap->d_stream.msg:""));
+        soap->d_stream.next_out = Z_NULL;
+        return EOF;
+      }
+    }
+zlib_again:
+    if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize)
+    { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
+      soap->buflen = soap->z_buflen;
+    }
+  }
+#endif
+  if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */
+  { 
+chunk_again:
+    if (soap->chunksize)
+    { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize);
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret));
+      DBGMSG(RECV, soap->buf, ret);
+      soap->bufidx = 0;
+      soap->chunksize -= ret;
+    }
+    else
+    { register soap_wchar c;
+      char *t, tmp[8];
+      t = tmp;
+      if (!soap->chunkbuflen)
+      { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes\n", (unsigned int)ret));
+        DBGMSG(RECV, soap->buf, ret);
+        soap->bufidx = 0;
+        if (!ret)
+          return EOF;
+      }
+      else
+        soap->bufidx = soap->buflen;
+      soap->buflen = soap->chunkbuflen;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (%u %u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen));
+      while (!soap_isxdigit((int)(c = soap_getchunkchar(soap))))
+        if ((int)c == EOF)
+	  return EOF;
+      do
+        *t++ = (char)c;
+      while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7);
+      while ((int)c != EOF && c != '\n')
+        c = soap_getchunkchar(soap);
+      if ((int)c == EOF)
+        return EOF;
+      *t = '\0';
+      soap->chunksize = soap_strtoul(tmp, &t, 16);
+      if (!soap->chunksize)
+      { soap->chunkbuflen = 0;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n"));
+	while ((int)c != EOF && c != '\n')
+          c = soap_getchunkchar(soap);
+        return EOF;
+      }
+      soap->buflen = soap->bufidx + soap->chunksize;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to %u (%u %s)\n", (unsigned int)soap->buflen, (unsigned int)soap->bufidx, tmp));
+      if (soap->buflen > soap->chunkbuflen)
+      { soap->buflen = soap->chunkbuflen;
+        soap->chunksize -= soap->buflen - soap->bufidx;
+        soap->chunkbuflen = 0;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%lu bytes left)\n", (unsigned long)(soap->buflen - soap->bufidx)));
+      }
+      else if (soap->chunkbuflen)
+        soap->chunksize = 0;
+      ret = soap->buflen - soap->bufidx;
+      if (!ret)
+        goto chunk_again;
+    }
+  }
+  else
+  { soap->bufidx = 0;
+    soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes\n", (unsigned int)ret));
+    DBGMSG(RECV, soap->buf, ret);
+  }
+  if (soap->fpreparerecv && (soap->error = soap->fpreparerecv(soap, soap->buf, ret)))
+    return soap->error;
+#ifdef WITH_ZLIB
+  if (soap->mode & SOAP_ENC_ZLIB)
+  { register int r;
+    memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
+    soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx);
+    soap->d_stream.avail_in = (unsigned int)ret;
+    soap->d_stream.next_out = (Byte*)soap->buf;
+    soap->d_stream.avail_out = SOAP_BUFLEN;
+    r = inflate(&soap->d_stream, Z_NO_FLUSH);
+    if (r == Z_OK || r == Z_STREAM_END)
+    { soap->bufidx = 0;
+      soap->z_buflen = soap->buflen;
+      soap->buflen = ret = SOAP_BUFLEN - soap->d_stream.avail_out;
+      if (soap->zlib_in == SOAP_ZLIB_GZIP)
+        soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)ret));
+      if (!ret)
+        goto zlib_again;
+      if (r == Z_STREAM_END)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out));
+        soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out;
+        soap->d_stream.next_out = Z_NULL;
+      }
+    }
+    else
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream.msg?soap->d_stream.msg:""));
+      soap->d_stream.next_out = Z_NULL;
+      return EOF;
+    }
+  }
+#endif
+  soap->count += ret;
+  return !ret;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_recv(struct soap *soap)
+{ 
+#ifndef WITH_LEANER
+  if (soap->mode & SOAP_ENC_DIME)
+  { if (soap->dime.buflen)
+    { char *s;
+      int i;
+      unsigned char tmp[12];
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n"));
+      soap->count += soap->dime.buflen - soap->buflen;
+      soap->buflen = soap->dime.buflen;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3));
+      for (i = -(long)soap->dime.size&3; i > 0; i--)
+      { soap->bufidx++;
+        if (soap->bufidx >= soap->buflen)
+          if (soap_recv_raw(soap))
+            return EOF;
+      }
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n"));
+      s = (char*)tmp;
+      for (i = 12; i > 0; i--)
+      { *s++ = soap->buf[soap->bufidx++];
+        if (soap->bufidx >= soap->buflen)
+          if (soap_recv_raw(soap))
+            return EOF;
+      }
+      soap->dime.flags = tmp[0] & 0x7;
+      soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size));
+      if (soap->dime.flags & SOAP_DIME_CF)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n"));
+        soap->dime.chunksize = soap->dime.size;
+        if (soap->buflen - soap->bufidx >= soap->dime.size)
+        { soap->dime.buflen = soap->buflen;
+          soap->buflen = soap->bufidx + soap->dime.chunksize;
+        }
+        else
+          soap->dime.chunksize -= soap->buflen - soap->bufidx;
+      }
+      else
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n"));
+        soap->dime.buflen = 0;
+        soap->dime.chunksize = 0;
+      }
+      soap->count = soap->buflen - soap->bufidx;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count));
+      return SOAP_OK;
+    }
+    if (soap->dime.chunksize)
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize));
+      if (soap_recv_raw(soap))
+        return EOF;
+      if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
+      { soap->dime.buflen = soap->buflen;
+        soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize;
+        soap->buflen = soap->bufidx + soap->dime.chunksize;
+      }
+      else
+        soap->dime.chunksize -= soap->buflen - soap->bufidx;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count));
+      return SOAP_OK;
+    }
+  }
+#endif
+  return soap_recv_raw(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+soap_wchar
+SOAP_FMAC2
+soap_getchar(struct soap *soap)
+{ register soap_wchar c;
+  if (soap->ahead)
+  { c = soap->ahead;
+    soap->ahead = 0;
+    return c;
+  }
+  return soap_get1(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+const struct soap_code_map*
+SOAP_FMAC2
+soap_code(const struct soap_code_map *map, const char *str)
+{ while (map->string)
+  { if (!strcmp(str, map->string)) /* case sensitive */
+      return map;
+    map++;
+  }
+  return NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+long
+SOAP_FMAC2
+soap_int_code(const struct soap_code_map *map, const char *str, long other)
+{ while (map->string)
+  { if (!soap_tag_cmp(str, map->string)) /* case insensitive */
+      return map->code;
+    map++;
+  }
+  return other;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_str_code(const struct soap_code_map *map, long code)
+{ while (map->code != code && map->string)
+    map++;
+  return map->string;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static soap_wchar
+soap_char(struct soap *soap)
+{ char tmp[8];
+  register int i;
+  register soap_wchar c;
+  register char *s = tmp;
+  for (i = 0; i < 7; i++)
+  { c = soap_get1(soap);
+    if (c == ';' || (int)c == EOF)
+      break;
+    *s++ = (char)c;
+  }
+  *s = '\0';
+  if (*tmp == '#')
+  { if (tmp[1] == 'x' || tmp[1] == 'X')
+      return soap_strtol(tmp + 2, NULL, 16);
+    return atol(tmp + 1);
+  }
+  if (!strcmp(tmp, "lt"))
+    return '<';
+  if (!strcmp(tmp, "gt"))
+    return '>';
+  if (!strcmp(tmp, "amp"))
+    return '&';
+  if (!strcmp(tmp, "quot"))
+    return '"';
+  if (!strcmp(tmp, "apos"))
+    return '\'';
+#ifndef WITH_LEAN
+  return (soap_wchar)soap_int_code(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR);
+#else
+  return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+soap_wchar
+SOAP_FMAC2
+soap_get(struct soap *soap)
+{ register soap_wchar c;
+  c = soap->ahead;
+  if (c)
+    soap->ahead = 0;
+  else
+    c = soap_get1(soap);
+  for (;;)
+  { if (soap->cdata)
+    { if (c == ']')
+      { c = soap_get1(soap);
+        if (c == ']')
+        { soap->cdata = 0;
+          soap_get1(soap); /* skip > */
+          c = soap_get1(soap);
+        }
+	else
+        { soap_revget1(soap);
+          return ']';
+        }
+      }
+      else
+        return c;
+    }
+    switch (c)
+    { case '<':
+        do c = soap_get1(soap);
+        while (soap_blank(c));
+        if (c == '!' || c == '?' || c == '%')
+        { if (c == '!')
+          { c = soap_get1(soap);
+            if (c == '[')
+            { do c = soap_get1(soap);
+              while ((int)c != EOF && c != '[');
+              if ((int)c == EOF)
+                break;
+              soap->cdata = 1;
+              c = soap_get1(soap);
+	      continue;
+            }
+            if (c == '-' && (c = soap_get1(soap)) == '-')
+            { do
+              { c = soap_get1(soap);
+                if (c == '-' && (c = soap_get1(soap)) == '-')
+                  break;
+              } while ((int)c != EOF);
+            }
+          }
+          while ((int)c != EOF && c != '>')
+            c = soap_get1(soap);
+	  if ((int)c == EOF)
+	    break;
+          c = soap_get1(soap);
+          continue;
+        }
+        if (c == '/')
+          return SOAP_TT;
+        soap_revget1(soap);
+        return SOAP_LT;
+      case '>':
+        return SOAP_GT;
+      case '"':
+        return SOAP_QT;
+      case '\'':
+        return SOAP_AP;
+      case '&':
+        return soap_char(soap) | 0x80000000;
+    }
+    break;
+  }
+  return c;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+soap_wchar
+SOAP_FMAC2
+soap_advance(struct soap *soap)
+{ register soap_wchar c;
+  while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
+    ;
+  return c;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+soap_wchar
+SOAP_FMAC2
+soap_skip(struct soap *soap)
+{ register soap_wchar c;
+  do c = soap_get(soap);
+  while (soap_blank(c));
+  return c;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_move(struct soap *soap, long n)
+{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n));
+  for (; n > 0; n--)
+    if ((int)soap_getchar(soap) == EOF)
+      return SOAP_EOF;
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+size_t
+SOAP_FMAC2
+soap_tell(struct soap *soap)
+{ return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_pututf8(struct soap *soap, register unsigned long c)
+{ char tmp[16];
+  if (c > 0 && c < 0x80)
+  { *tmp = (char)c;
+    return soap_send_raw(soap, tmp, 1);
+  }
+#ifndef WITH_LEAN
+  if (soap->mode & SOAP_XML_CANONICAL)
+  { register char *t = tmp;
+    if (c < 0x0800)
+      *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
+    else
+    { if (c < 0x010000)
+        *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
+      else
+      { if (c < 0x200000)
+          *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
+        else
+        { if (c < 0x04000000)
+            *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
+          else
+          { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
+            *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
+          }
+          *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
+        }     
+        *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
+      }
+      *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
+    }
+    *t++ = (char)(0x80 | (c & 0x3F));
+    *t = '\0';
+  }
+  else
+#endif
+    sprintf(tmp, "&#%lu;", c);
+  return soap_send(soap, tmp);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+soap_wchar
+SOAP_FMAC2
+soap_getutf8(struct soap *soap)
+{ register soap_wchar c, c1, c2, c3, c4;
+  c = soap_get(soap);
+  if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN))
+    return c;
+  c1 = soap_get(soap);
+  if (c1 < 0x80)
+  { soap_unget(soap, c1);
+    return c;
+  }
+  c1 &= 0x3F;
+  if (c < 0xE0)
+    return ((soap_wchar)(c & 0x1F) << 6) | c1;
+  c2 = (soap_wchar)soap_get1(soap) & 0x3F;
+  if (c < 0xF0)
+    return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2;
+  c3 = (soap_wchar)soap_get1(soap) & 0x3F;
+  if (c < 0xF8)
+    return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
+  c4 = (soap_wchar)soap_get1(soap) & 0x3F;
+  if (c < 0xFC)
+    return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
+  return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_puthex(struct soap *soap, const unsigned char *s, int n)
+{ /* TODO: serialize to DOM (as an option) using new soap_s2hex() */
+  char d[2];
+  register int i;
+  for (i = 0; i < n; i++)
+  { register int m = *s++;
+    d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0'));
+    m &= 0x0F;
+    d[1] = (char)(m + (m > 9 ? '7' : '0'));
+    if (soap_send_raw(soap, d, 2))
+      return soap->error;
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+unsigned char*
+SOAP_FMAC2
+soap_gethex(struct soap *soap, int *n)
+{
+#ifdef WITH_FAST
+  soap->labidx = 0;
+  for (;;)
+  { register char *s;
+    register int i, k;
+    if (soap_append_lab(soap, NULL, 0))
+      return NULL;
+    s = soap->labbuf + soap->labidx;
+    k = soap->lablen - soap->labidx;
+    soap->labidx = soap->lablen;
+    for (i = 0; i < k; i++)
+    { register char d1, d2;
+      register soap_wchar c;
+      c = soap_get(soap);
+      if (soap_isxdigit(c))
+      { d1 = (char)c;
+        c = soap_get(soap); 
+	if (soap_isxdigit(c))
+          d2 = (char)c;
+        else 
+        { soap->error = SOAP_TYPE;
+          return NULL;
+        }
+      }
+      else
+      { unsigned char *p;
+        soap_unget(soap, c);
+        if (n)
+          *n = (int)(soap->lablen - k + i);
+        p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i);
+	if (p)
+	  memcpy(p, soap->labbuf, soap->lablen - k + i);
+        return p;
+      }
+      *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
+    }
+  }
+#else
+  if (soap_new_block(soap))
+    return NULL;
+  for (;;)
+  { register int i;
+    register char *s = (char*)soap_push_block(soap, SOAP_BLKLEN);
+    if (!s)
+    { soap_end_block(soap);
+      return NULL;
+    }
+    for (i = 0; i < SOAP_BLKLEN; i++)
+    { register char d1, d2;
+      register soap_wchar c = soap_get(soap);
+      if (soap_isxdigit(c))
+      { d1 = (char)c;
+        c = soap_get(soap); 
+	if (soap_isxdigit(c))
+          d2 = (char)c;
+        else 
+        { soap_end_block(soap);
+	  soap->error = SOAP_TYPE;
+          return NULL;
+        }
+      }
+      else
+      { unsigned char *p;
+        soap_unget(soap, c);
+        if (n)
+          *n = soap_size_block(soap, i);
+        p = (unsigned char*)soap_save_block(soap, NULL, 0);
+        return p;
+      }
+      *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
+    }
+  }
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_putbase64(struct soap *soap, const unsigned char *s, int n)
+{ register int i;
+  register unsigned long m;
+  char d[4];
+  if (!s)
+    return SOAP_OK;
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+  { if (!(soap->dom->data = soap_s2base64(soap, s, soap->dom->data, n)))
+      return soap->error;
+    return SOAP_OK;
+  }
+#endif
+  for (; n > 2; n -= 3, s += 3)
+  { m = s[0];
+    m = (m << 8) | s[1];
+    m = (m << 8) | s[2];
+    for (i = 4; i > 0; m >>= 6)
+      d[--i] = soap_base64o[m & 0x3F];
+    if (soap_send_raw(soap, d, 4))
+      return soap->error;
+  }
+  if (n > 0)
+  { m = 0;
+    for (i = 0; i < n; i++)
+      m = (m << 8) | *s++;
+    for (; i < 3; i++)
+      m <<= 8;
+    for (i++; i > 0; m >>= 6)
+      d[--i] = soap_base64o[m & 0x3F];
+    for (i = 3; i > n; i--)
+      d[i] = '=';
+    if (soap_send_raw(soap, d, 4))
+      return soap->error;
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+unsigned char*
+SOAP_FMAC2
+soap_getbase64(struct soap *soap, int *n, int malloc_flag)
+{ 
+#ifdef WITH_FAST
+  soap->labidx = 0;
+  for (;;)
+  { register int i, k;
+    register char *s;
+    if (soap_append_lab(soap, NULL, 2))
+      return NULL;
+    s = soap->labbuf + soap->labidx;
+    k = 3 * ((soap->lablen - soap->labidx) / 3);
+    soap->labidx = 3 * (soap->lablen / 3);
+    if (!s)
+      return NULL;
+    for (i = 0; i < k; i += 3)
+    { register unsigned long m = 0;
+      register int j = 0;
+      do
+      { register soap_wchar c = soap_get(soap);
+        if (c == '=' || c < 0)
+        { unsigned char *p;
+          switch (j)
+          { case 2:
+              *s++ = (char)((m >> 4) & 0xFF);
+              i++;
+              break;
+            case 3:
+              *s++ = (char)((m >> 10) & 0xFF);
+              *s++ = (char)((m >> 2) & 0xFF);
+              i += 2;
+          }
+          if (n)
+            *n = (int)(soap->lablen - k + i);
+          p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i);
+	  if (p)
+	    memcpy(p, soap->labbuf, soap->lablen - k + i);
+          if (c >= 0)
+          { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
+              ;
+	  }
+          soap_unget(soap, c);
+          return p;
+        }
+        c -= '+';
+        if (c >= 0 && c <= 79)
+        { m = (m << 6) + soap_base64i[c];
+          j++;
+        }
+      } while (j < 4);
+      *s++ = (char)((m >> 16) & 0xFF);
+      *s++ = (char)((m >> 8) & 0xFF);
+      *s++ = (char)(m & 0xFF);
+    }
+  }
+#else
+  if (soap_new_block(soap))
+    return NULL;
+  for (;;)
+  { register int i;
+    register char *s = (char*)soap_push_block(soap, 3 * SOAP_BLKLEN); /* must be multiple of 3 */
+    if (!s)
+    { soap_end_block(soap);
+      return NULL;
+    }
+    for (i = 0; i < SOAP_BLKLEN; i++)
+    { register unsigned long m = 0;
+      register int j = 0;
+      do
+      { register soap_wchar c = soap_get(soap);
+        if (c == '=' || c < 0)
+        { unsigned char *p;
+          i *= 3;
+          switch (j)
+          { case 2:
+              *s++ = (char)((m >> 4) & 0xFF);
+              i++;
+              break;
+            case 3:
+              *s++ = (char)((m >> 10) & 0xFF);
+              *s++ = (char)((m >> 2) & 0xFF);
+              i += 2;
+          }
+          if (n)
+	    *n = (int)soap_size_block(soap, i);
+          p = (unsigned char*)soap_save_block(soap, NULL, 0);
+          if (c >= 0)
+          { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
+              ;
+	  }
+          soap_unget(soap, c);
+          return p;
+        }
+        c -= '+';
+        if (c >= 0 && c <= 79)
+        { m = (m << 6) + soap_base64i[c];
+          j++;
+        }
+      } while (j < 4);
+      *s++ = (char)((m >> 16) & 0xFF);
+      *s++ = (char)((m >> 8) & 0xFF);
+      *s++ = (char)(m & 0xFF);
+    }
+  }
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_strdup(struct soap *soap, const char *s)
+{ char *t = NULL;
+  if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1)))
+    strcpy(t, s);
+  return t;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_new_block(struct soap *soap)
+{ struct soap_blist *p;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist));
+  if (!(p = (struct soap_blist*)SOAP_MALLOC(sizeof(struct soap_blist))))
+    return SOAP_EOM;   
+  p->next = soap->blist; 
+  p->ptr = NULL;
+  p->size = 0;
+  soap->blist = p;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void*
+SOAP_FMAC2
+soap_push_block(struct soap *soap, size_t n)
+{ char *p;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)soap->blist->size + (unsigned int)n));
+  if (!(p = (char*)SOAP_MALLOC(n + sizeof(char*) + sizeof(size_t))))
+  { soap->error = SOAP_EOM;
+    return NULL;
+  }
+  *(char**)p = soap->blist->ptr;
+  *(size_t*)(p + sizeof(char*)) = n;
+  soap->blist->ptr = p;
+  soap->blist->size += n;
+  return p + sizeof(char*) + sizeof(size_t);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_pop_block(struct soap *soap)
+{ char *p;
+  if (!soap->blist->ptr)
+    return;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n"));
+  p = soap->blist->ptr;
+  soap->blist->size -= *(size_t*)(p + sizeof(char*));
+  soap->blist->ptr = *(char**)p;
+  SOAP_FREE(p);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static void
+soap_update_ptrs(struct soap *soap, char *start, char *end, long offset)
+{ int i;
+  register struct soap_ilist *ip;
+  register struct soap_flist *fp;
+  register void *p, **q;
+  for (i = 0; i < SOAP_IDHASH; i++)
+    for (ip = soap->iht[i]; ip; ip = ip->next)
+    { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + offset));
+        ip->ptr = (char*)ip->ptr + offset;
+      }
+      for (q = &ip->link; q; q = (void**)p)
+      { p = *q;
+        if (p && (char*)p >= start && (char*)p < end)
+        { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p));
+          *q = (char*)p + offset;
+        }
+      }
+      for (q = &ip->copy; q; q = (void**)p)
+      { p = *q;
+        if (p && (char*)p >= start && (char*)p < end)
+        { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p));
+          *q = (char*)p + offset;
+        }
+      }
+      for (fp = ip->flist; fp; fp = fp->next)
+      { if ((char*)fp->ptr >= start && (char*)fp->ptr < end)
+        { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp));
+          fp->ptr = (char*)fp->ptr + offset;
+        }
+      }
+    }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static int
+soap_has_copies(struct soap *soap, register const char *start, register const char *end)
+{ register int i;
+  register struct soap_ilist *ip;
+  register struct soap_flist *fp;
+  register const char *p;
+  for (i = 0; i < SOAP_IDHASH; i++)
+  { for (ip = soap->iht[i]; ip; ip = ip->next)
+    { for (p = (const char*)ip->copy; p; p = *(const char**)p)
+        if (p >= start && p < end)
+          return SOAP_ERR;
+      for (fp = ip->flist; fp; fp = fp->next)
+        if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end)
+	  return SOAP_ERR;
+    }
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_resolve(struct soap *soap)
+{ register int i;
+  register struct soap_ilist *ip;
+  register struct soap_flist *fp;
+  short flag;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n"));
+  for (i = 0; i < SOAP_IDHASH; i++)
+  { for (ip = soap->iht[i]; ip; ip = ip->next)
+    { if (ip->ptr)
+      { register void *p, **q, *r;
+        q = (void**)ip->link;
+        ip->link = NULL;
+        r = ip->ptr;
+        DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id));
+        while (q)
+        { p = *q;
+          *q = r;
+          DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r));
+          q = (void**)p;
+        }
+      }
+      else if (*ip->id == '#')
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id));
+        strcpy(soap->id, ip->id + 1);
+        return soap->error = SOAP_MISSING_ID;
+      }
+    }
+  }
+  do
+  { flag = 0;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n"));
+    for (i = 0; i < SOAP_IDHASH; i++)
+    { for (ip = soap->iht[i]; ip; ip = ip->next)
+      { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size))
+        { if (ip->copy)
+          { register void *p, **q = (void**)ip->copy;
+            DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id));
+            ip->copy = NULL;
+            do
+            { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size));
+	      p = *q;
+              memcpy(q, ip->ptr, ip->size);
+              q = (void**)p;
+            } while (q);
+	    flag = 1;
+	  }
+          for (fp = ip->flist; fp; fp = ip->flist)
+          { register unsigned int k = fp->level;
+	    register void *p = ip->ptr;
+            DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data type=%d location=%p level=%u,%u id='%s'\n", ip->type, p, ip->level, fp->level, ip->id));
+	    while (ip->level < k)
+            { register void **q = (void**)soap_malloc(soap, sizeof(void*));  
+	      if (!q)
+	        return soap->error;
+	      *q = p;
+              DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q));
+              p = (void*)q;
+              k--;
+            }
+	    if (fp->fcopy)
+	      fp->fcopy(soap, ip->type, fp->type, fp->ptr, p, ip->size);
+	    else
+	      soap_fcopy(soap, ip->type, fp->type, fp->ptr, p, ip->size);
+	    ip->flist = fp->next;
+	    SOAP_FREE(fp);
+	    flag = 1;
+	  }
+        }
+      }
+    }
+  } while (flag);
+#ifdef SOAP_DEBUG
+  for (i = 0; i < SOAP_IDHASH; i++)
+  { for (ip = soap->iht[i]; ip; ip = ip->next)
+    { if (ip->copy || ip->flist)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the developers\n", ip->id));
+      }
+    }
+  }
+#endif
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n"));
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+size_t
+SOAP_FMAC2
+soap_size_block(struct soap *soap, size_t n)
+{ if (soap->blist->ptr)
+  { soap->blist->size -= *(size_t*)(soap->blist->ptr + sizeof(char*)) - n;
+    *(size_t*)(soap->blist->ptr + sizeof(char*)) = n;
+  }
+  return soap->blist->size;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+char*
+SOAP_FMAC2
+soap_first_block(struct soap *soap)
+{ char *p, *q, *r;
+  p = soap->blist->ptr;
+  if (!p)
+    return NULL;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n"));
+  r = NULL;
+  do
+  { q = *(char**)p;
+    *(char**)p = r;
+    r = p;
+    p = q;
+  } while (p);
+  soap->blist->ptr = r;
+  return r + sizeof(char*) + sizeof(size_t);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+char*
+SOAP_FMAC2
+soap_next_block(struct soap *soap)
+{ char *p;
+  p = soap->blist->ptr;
+  if (p)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n"));
+    soap->blist->ptr = *(char**)p;
+    SOAP_FREE(p);
+    if (soap->blist->ptr)
+      return soap->blist->ptr + sizeof(char*) + sizeof(size_t);
+  }
+  return NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+size_t
+SOAP_FMAC2
+soap_block_size(struct soap *soap)
+{ return *(size_t*)(soap->blist->ptr + sizeof(char*));
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_end_block(struct soap *soap)
+{ struct soap_blist *bp;
+  char *p, *q;
+  bp = soap->blist;
+  if (bp)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n"));
+    for (p = bp->ptr; p; p = q)
+    { q = *(char**)p;
+      SOAP_FREE(p);
+    }
+    soap->blist = bp->next;
+    SOAP_FREE(bp);
+  }
+  DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n"));
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+char*
+SOAP_FMAC2
+soap_save_block(struct soap *soap, char *p, int flag)
+{ register size_t n;
+  register char *q, *s;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)soap->blist->size, soap->blist->ptr, p));
+  if (soap->blist->size)
+  { if (!p)
+      p = (char*)soap_malloc(soap, soap->blist->size);
+    if (p)
+    { for (s = p, q = soap_first_block(soap); q; q = soap_next_block(soap))
+      { n = soap_block_size(soap);
+        if (flag)
+	  soap_update_ptrs(soap, q, q + n, (long)s - (long)q); /* pointers s and q may or may not be related */
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s));
+        memcpy(s, q, n);
+        s += n;
+      }
+    }
+    else
+      soap->error = SOAP_EOM;
+  }
+  soap_end_block(soap);
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_putsize(struct soap *soap, const char *type, int size)
+{ return soap_putsizes(soap, type, &size, 1);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_putsizes(struct soap *soap, const char *type, const int *size, int dim)
+{ return soap_putsizesoffsets(soap, type, size, NULL, dim);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim)
+{ int i;
+  if (!type)
+    return NULL;
+  if (soap->version == 2)
+  { sprintf(soap->type, "%s[%d", type, size[0]);
+    for (i = 1; i < dim; i++)
+      sprintf(soap->type + strlen(soap->type), " %d", size[i]);
+  }
+  else
+  { if (offset)
+    { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]);
+      for (i = 1; i < dim; i++)
+        sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]);
+    }
+    else
+    { sprintf(soap->type, "%s[%d", type, size[0]);
+      for (i = 1; i < dim; i++)
+        sprintf(soap->type + strlen(soap->type), ",%d", size[i]);
+    }
+    strcat(soap->type, "]");
+  }
+  return soap->type;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_putoffset(struct soap *soap, int offset)
+{ return soap_putoffsets(soap, &offset, 1);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_putoffsets(struct soap *soap, const int *offset, int dim)
+{ register int i;
+  sprintf(soap->arrayOffset, "[%d", offset[0]);
+  for (i = 1; i < dim; i++)
+    sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]);
+  strcat(soap->arrayOffset, "]");
+  return soap->arrayOffset;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_size(const int *size, int dim)
+{ register int i, n = size[0];
+  for (i = 1; i < dim; i++)
+    n *= size[i];
+  return n;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getoffsets(const char *attr, const int *size, int *offset, int dim)
+{ register int i, j = 0;
+  if (offset)
+    for (i = 0; i < dim && attr && *attr; i++)
+    { attr++;
+      j *= size[i];
+      j += offset[i] = (int)atol(attr);
+      attr = strchr(attr, ',');
+    }
+  else
+    for (i = 0; i < dim && attr && *attr; i++)
+    { attr++;
+      j *= size[i];
+      j += (int)atol(attr);
+      attr = strchr(attr, ',');
+    }
+  return j;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getsize(const char *attr1, const char *attr2, int *j)
+{ register int n, k;
+  char *s;
+  *j = 0;
+  if (!*attr1)
+    return -1;
+  n = 1;
+  do
+  { attr1++;
+    k = (int)soap_strtol(attr1, &s, 10);
+    n *= k;
+    if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1)
+      return -1;
+    attr1 = strchr(s, ',');
+    if (!attr1)
+      attr1 = strchr(s, ' ');
+    if (attr2 && *attr2)
+    { attr2++;
+      *j *= k;
+      k = (int)soap_strtol(attr2, &s, 10);
+      *j += k;
+      if (k < 0)
+        return -1;
+      attr2 = s;
+    }
+  } while (attr1 && *attr1 != ']');
+  return n - *j;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getsizes(const char *attr, int *size, int dim)
+{ register int i, k, n;
+  if (!*attr)
+    return -1;
+  i = strlen(attr);
+  n = 1;
+  do
+  { for (i = i-1; i >= 0; i--)
+      if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ')
+        break;
+    k = (int)atol(attr + i + 1);
+    n *= size[--dim] = k;
+    if (k < 0 || n > SOAP_MAXARRAYSIZE)
+      return -1;
+  } while (i >= 0 && attr[i] != '[');
+  return n;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getposition(const char *attr, int *pos)
+{ register int i, n;
+  if (!*attr)
+    return -1;
+  n = 0;
+  i = 1;
+  do
+  { pos[n++] = (int)atol(attr + i);
+    while (attr[i] && attr[i] != ',' && attr[i] != ']')
+      i++;
+    if (attr[i] == ',')
+      i++;
+  } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']');
+  return n;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_push_namespace(struct soap *soap, const char *id, const char *ns)
+{ register struct soap_nlist *np;
+  register struct Namespace *p;
+  np = (struct soap_nlist*)SOAP_MALLOC(sizeof(struct soap_nlist) + strlen(id));
+  if (!np)
+    return soap->error = SOAP_EOM;
+  np->next = soap->nlist;
+  soap->nlist = np;
+  strcpy(np->id, id);
+  np->level = soap->level;
+  np->index = -1;
+  np->ns = NULL;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns));
+  p = soap->local_namespaces;
+  if (p)
+  { register short i = 0;
+    for (; p->id; p++, i++)
+    { if (p->ns && !strcmp(ns, p->ns))
+      { if (p->out)
+        { SOAP_FREE(p->out);
+          p->out = NULL;
+        }
+        break;
+      }
+      if (p->out)
+      { if (!SOAP_STRCMP(ns, p->out))
+          break;
+      }
+      else if (p->in)
+      { if (!soap_tag_cmp(ns, p->in))
+        { if ((p->out = (char*)SOAP_MALLOC(strlen(ns) + 1)))
+            strcpy(p->out, ns);
+          break;
+        }
+      }
+    }
+    if (p && p->id)
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id));
+      np->index = i;
+    }
+  }
+  if (!p || !p->id)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns));
+    np->ns = (char*)SOAP_MALLOC(strlen(ns) + 1);
+    if (!np->ns)
+      return soap->error = SOAP_EOM;
+    strcpy(np->ns, ns);
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_pop_namespace(struct soap *soap)
+{ register struct soap_nlist *np;
+  while (soap->nlist && soap->nlist->level >= soap->level)
+  { np = soap->nlist->next;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Popped namespace binding (level=%u) '%s'\n", soap->level, soap->nlist->id));
+    if (soap->nlist->ns)
+      SOAP_FREE(soap->nlist->ns);
+    SOAP_FREE(soap->nlist);
+    soap->nlist = np;
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_match_namespace(struct soap *soap, const char *id1, const char *id2, int n1, int n2) 
+{ register struct soap_nlist *np = soap->nlist;
+  while (np && (strncmp(np->id, id1, n1) || np->id[n1]))
+    np = np->next;
+  if (np)
+  { if (np->index < 0 || (np->index >= 0 && soap->local_namespaces[np->index].id && (strncmp(soap->local_namespaces[np->index].id, id2, n2) || soap->local_namespaces[np->index].id[n2])))
+      return SOAP_NAMESPACE;
+    return SOAP_OK;
+  }
+  if (n1 == 3 && n1 == n2 && !strcmp(id1, "xml") && !strcmp(id1, id2))
+    return SOAP_OK;
+  return SOAP_SYNTAX_ERROR; 
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_tag_cmp(const char *s, const char *t)
+{ for (;;)
+  { register int c1 = *s;
+    register int c2 = *t;
+    if (!c1 || c1 == '"')
+      break;
+    if (c2 != '-')
+    { if (c1 != c2)
+      { if (c1 >= 'A' && c1 <= 'Z')
+          c1 += 'a' - 'A';
+        if (c2 >= 'A' && c2 <= 'Z')
+          c2 += 'a' - 'A';
+      }
+      if (c1 != c2)
+      { if (c2 != '*')
+          return 1;
+	c2 = *++t;
+        if (!c2)
+	  return 0;
+        if (c2 >= 'A' && c2 <= 'Z')
+          c2 += 'a' - 'A';
+        for (;;)
+        { c1 = *s;
+	  if (!c1 || c1 == '"')
+	    break;
+	  if (c1 >= 'A' && c1 <= 'Z')
+            c1 += 'a' - 'A';
+          if (c1 == c2)
+            if (!soap_tag_cmp(s + 1, t + 1))
+              return 0;
+	  s++;
+        }
+        break;
+      }
+    }
+    s++;
+    t++;
+  }
+  if (*t == '*' && !t[1])
+    return 0;
+  return *t;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_match_tag(struct soap *soap, const char *tag1, const char *tag2)
+{ register const char *s, *t;
+  if (!tag1 || !tag2 || !*tag2)
+    return SOAP_OK;
+  s = strchr(tag1, ':');
+  t = strchr(tag2, ':');
+  if (t)
+  { if (s)
+    { if (t[1] && SOAP_STRCMP(s + 1, t + 1))
+        return SOAP_TAG_MISMATCH;
+      if (t != tag2 && soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2))
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
+        return SOAP_TAG_MISMATCH;
+      }
+    } 
+    else if (SOAP_STRCMP(tag1, t + 1))
+      return SOAP_TAG_MISMATCH;
+    else if (t != tag2 && soap_match_namespace(soap, tag1, tag2, 0, t - tag2))
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
+      return SOAP_TAG_MISMATCH;
+    }
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
+    return SOAP_OK;
+  }
+  if (s)
+  { if (SOAP_STRCMP(s + 1, tag2))
+      return SOAP_TAG_MISMATCH;
+  }
+  else if (SOAP_STRCMP(tag1, tag2))
+    return SOAP_TAG_MISMATCH;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2));
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_match_array(struct soap *soap, const char *type)
+{ if (*soap->arrayType)
+    if (soap_match_tag(soap, soap->arrayType, type)
+     && soap_match_tag(soap, soap->arrayType, "xsd:anyType")
+     && soap_match_tag(soap, soap->arrayType, "xsd:ur-type")
+    )
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type));
+      return SOAP_TAG_MISMATCH;
+    }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+
+#ifdef WITH_OPENSSL
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid)
+{ int err;
+  soap->keyfile = keyfile;
+  soap->password = password;
+  soap->cafile = cafile;
+  soap->capath = capath;
+  if (dhfile)
+  { soap->dhfile = dhfile;
+    soap->rsa = 0;
+  }
+  else
+  { soap->dhfile = NULL;
+    soap->rsa = 1;
+  }
+  soap->randfile = randfile;
+  soap->require_client_auth = (flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION);
+  if (!(err = soap->fsslauth(soap)))
+    if (sid)
+      SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, strlen(sid));
+  return err; 
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *randfile)
+{ soap->keyfile = keyfile;
+  soap->password = password;
+  soap->cafile = cafile;
+  soap->capath = capath;
+  soap->dhfile = NULL;
+  soap->rsa = 0;
+  soap->randfile = randfile;
+  soap->require_server_auth = (flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION);
+  return soap->fsslauth(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+static void
+ssl_init()
+{ static int done = 0;
+  if (!done)
+  { done = 1;
+    SSL_library_init();
+#ifndef WITH_LEAN
+    SSL_load_error_strings();
+#endif
+    if (!RAND_load_file("/dev/urandom", 1024))
+    { int r;
+#ifdef HAVE_RAND_R
+      unsigned int s = (unsigned int)time(NULL);
+#endif
+      char buf[SOAP_BUFLEN];
+      RAND_seed(buf, sizeof(buf));
+      while (!RAND_status())
+      {
+#ifdef HAVE_RAND_R
+        r = rand_r(&s);
+#else
+        r = rand();
+#endif
+        RAND_seed(&r, sizeof(int));
+      }
+    }
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static const char *
+ssl_error(struct soap *soap, int ret)
+{ int err = SSL_get_error(soap->ssl, ret);
+  const char *msg = soap_str_code(h_ssl_error_codes, err);
+  if (msg)
+    strcpy(soap->msgbuf, msg);
+  else
+    return ERR_error_string(err, soap->msgbuf);
+  if (ERR_peek_error())
+  { unsigned long r;
+    strcat(soap->msgbuf, "\n");
+    while ((r = ERR_get_error()))
+      ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf));
+  } 
+  else
+  { switch (ret)
+    { case 0:
+        strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information.");
+        break;
+      case -1:
+        sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno));  
+        break;
+    }
+  }
+  return soap->msgbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static int
+ssl_password(char *buf, int num, int rwflag, void *userdata)
+{ if (num < (int)strlen((char*)userdata) + 1)
+    return 0;
+  return strlen(strcpy(buf, (char*)userdata));
+}
+#endif
+
+/******************************************************************************/
+/* This callback is included for future references. It should not be deleted
+#ifndef PALM_2
+static DH *
+ssl_tmp_dh(SSL *ssl, int is_export, int keylength)
+{ static DH *dh512 = NULL;
+  static DH *dh1024 = NULL;
+  DH *dh;
+  switch (keylength)
+  { case 512:
+      if (!dh512)
+      { BIO *bio = BIO_new_file("dh512.pem", "r");
+        if (bio)
+        { dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
+          BIO_free(bio);
+          return dh512;
+        }
+      }
+      else
+        return dh512;
+    default:
+      if (!dh1024)
+      { BIO *bio = BIO_new_file("dh1024.pem", "r");
+        if (bio)
+        { dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
+          BIO_free(bio);
+        }
+      }
+      dh = dh1024;
+  }
+  return dh;
+}
+#endif
+*/
+/******************************************************************************/
+#ifndef PALM_1
+static int
+ssl_auth_init(struct soap *soap)
+{ ssl_init();
+  if (!soap->ctx)
+    if (!(soap->ctx = SSL_CTX_new(SSLv23_method())))
+      return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR);
+  if (soap->randfile)
+  { if (!RAND_load_file(soap->randfile, -1))
+      return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR);
+  }
+  if (soap->cafile || soap->capath)
+    if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath))
+      return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and/or directory", SOAP_SSL_ERROR);
+  if (!SSL_CTX_set_default_verify_paths(soap->ctx))
+    return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR);
+  if (soap->keyfile)
+  { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
+      return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR);
+    if (soap->password)
+    { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
+      SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
+      if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
+        return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR);
+    }
+  }
+  if (soap->rsa)
+  { RSA *rsa = RSA_generate_key(512, RSA_F4, NULL, NULL);
+    if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
+    { if (rsa)
+        RSA_free(rsa);
+      return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR);
+    }
+    RSA_free(rsa);
+  }
+  else if (soap->dhfile)
+  { DH *dh = 0;
+    BIO *bio;
+    bio = BIO_new_file(soap->dhfile, "r");
+    if (!bio)
+      return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR);
+    dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
+    BIO_free(bio);
+    if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0)
+    { if (dh)
+        DH_free(dh);
+      return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR);
+    }
+    DH_free(dh);
+  }
+  SSL_CTX_set_options(soap->ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
+  SSL_CTX_set_verify(soap->ctx, soap->require_client_auth ? (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT) : soap->require_server_auth ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, soap->fsslverify);
+#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
+  SSL_CTX_set_verify_depth(soap->ctx, 1); 
+#else
+  SSL_CTX_set_verify_depth(soap->ctx, 9); 
+#endif  
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static int
+ssl_verify_callback(int ok, X509_STORE_CTX *store)
+{
+#ifdef SOAP_DEBUG
+  if (!ok) 
+  { char data[256];
+    X509 *cert = X509_STORE_CTX_get_current_cert(store);
+    fprintf(stderr, "SSL Verify error with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(X509_STORE_CTX_get_error(store)));
+    X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
+    fprintf(stderr, "certificate issuer %s\n", data);
+    X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
+    fprintf(stderr, "certificate subject %s\n", data);
+  }
+#endif
+  /* return 1 to always continue, but unsafe progress will be terminated by SSL */
+  return ok;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_ssl_accept(struct soap *soap)
+{ int i, r;
+  if (!soap_valid_socket(soap->socket))
+    return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
+  if (!soap->ssl)
+  { soap->ssl = SSL_new(soap->ctx);
+    if (!soap->ssl)
+      return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
+  }
+  else
+    SSL_clear(soap->ssl);
+  soap->imode |= SOAP_ENC_SSL;
+  soap->omode |= SOAP_ENC_SSL;
+#ifdef WIN32
+  { u_long nonblocking = 1;
+    ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &nonblocking);
+  }
+#else
+  fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)|O_NONBLOCK);
+#endif
+  soap->bio = BIO_new_socket((SOAP_SOCKET)soap->socket, BIO_NOCLOSE);
+  SSL_set_bio(soap->ssl, soap->bio, soap->bio);
+  i = 100; /* 100 * 0.1 ms retries */
+  while ((r = SSL_accept(soap->ssl)) <= 0)
+  { int err = SSL_get_error(soap->ssl, r);
+    if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
+    { struct timeval timeout;
+      fd_set fd;
+      if (i-- <= 0)
+        break;
+      timeout.tv_sec = 0;
+      timeout.tv_usec = 100000;
+      FD_ZERO(&fd);
+      FD_SET((SOAP_SOCKET)soap->socket, &fd);
+      r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout);
+      if (r < 0 && soap_socket_errno != SOAP_EINTR)
+      { soap->errnum = soap_socket_errno;
+        return SOAP_EOF;
+      }
+    }
+    else
+    { soap->errnum = err;
+      break;
+    }
+  }
+#ifdef WIN32
+  { u_long blocking = 0;
+    ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking);
+  }
+#else
+  fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK);
+#endif
+  if (r <= 0)
+  { soap_set_receiver_error(soap, ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
+    soap_closesock(soap);
+    return SOAP_SSL_ERROR;
+  }
+  if (soap->require_client_auth)
+  { X509 *peer;
+    int err;
+    if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
+    { soap_closesock(soap);
+      return soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in soap_ssl_accept()", SOAP_SSL_ERROR);
+    }
+    peer = SSL_get_peer_certificate(soap->ssl);
+    if (!peer)
+    { soap_closesock(soap);
+      return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR);
+    }
+    X509_free(peer);
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#endif /* WITH_OPENSSL */
+
+/******************************************************************************/
+#ifndef PALM_1
+static int
+tcp_init(struct soap *soap)
+{ soap->errmode = 1;
+#ifdef WIN32
+  if (tcp_done)
+    return 0;
+  else
+  { WSADATA w;
+    if (WSAStartup(MAKEWORD(1, 1), &w))
+      return -1;
+    tcp_done = 1;
+  }
+#endif
+  return 0;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_done(struct soap *soap)
+{ 
+#ifdef SOAP_DEBUG
+  int i;
+#endif
+  soap_free(soap);
+  while (soap->clist)
+  { struct soap_clist *p = soap->clist->next;
+    SOAP_FREE(soap->clist);
+    soap->clist = p;
+  }
+  soap->keep_alive = 0; /* to force close the socket */
+  soap_closesock(soap);
+#ifdef WITH_COOKIES
+  soap_free_cookies(soap);
+#endif
+  while (soap->plugins)
+  { register struct soap_plugin *p = soap->plugins->next;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id));
+    if (soap->plugins->fcopy || !soap->copy)
+      soap->plugins->fdelete(soap, soap->plugins);
+    SOAP_FREE(soap->plugins);
+    soap->plugins = p;
+  }
+  soap->fplugin = fplugin;
+  soap->fpost = http_post;
+  soap->fget = http_get;
+  soap->fposthdr = http_post_header;
+  soap->fresponse = http_response;
+  soap->fparse = http_parse;
+  soap->fparsehdr = http_parse_header;
+#ifndef MAC_CARBON
+#ifndef WITH_IPV6
+  soap->fresolve = tcp_gethost;
+#else
+  soap->fresolve = NULL;
+#endif
+  soap->faccept = tcp_accept;
+  soap->fopen = tcp_connect;
+  soap->fclose = tcp_disconnect;
+  soap->fclosesocket = tcp_closesocket;
+  soap->fshutdownsocket = tcp_shutdownsocket;
+  soap->fsend = fsend;
+  soap->frecv = frecv;
+  soap->fpoll = soap_poll;
+#else
+  soap->fpoll = NULL;
+#endif
+  soap->fprepareinit = NULL;
+  soap->fpreparesend = NULL;
+  soap->fpreparerecv = NULL;
+  soap->fignore = NULL;
+  soap->fserveloop = NULL;
+#ifdef WITH_OPENSSL
+  if (soap->session)
+  { SSL_SESSION_free(soap->session);
+    soap->session = NULL;
+  }
+#endif
+  if (!soap->copy)
+  { if (soap_valid_socket(soap->master))
+    { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master);
+      soap->master = SOAP_INVALID_SOCKET;
+    }
+#ifdef WITH_OPENSSL
+    if (soap->ctx)
+    { SSL_CTX_free(soap->ctx);
+      soap->ctx = NULL;
+    }
+#endif
+  }
+#ifdef SOAP_DEBUG
+  for (i = 0; i < SOAP_MAXLOGS; i++)
+  { soap_close_logfile(soap, i);
+    if (soap->logfile[i])
+    { SOAP_FREE((void*)soap->logfile[i]);
+      soap->logfile[i] = NULL;
+    }
+  }
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_cleanup(struct soap *soap)
+{ soap_done(soap);
+#ifdef WIN32
+  if (!tcp_done)
+    return;
+  tcp_done = 0;
+  WSACleanup();
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static const char*
+tcp_error(struct soap *soap)
+{ register const char *msg = NULL;
+  switch (soap->errmode)
+  { case 0:
+      msg = soap_strerror(soap);
+      break;
+    case 1:
+      msg = "WSAStartup failed";
+      break;
+    case 2:
+    {
+#ifndef WITH_LEAN
+      msg = soap_str_code(h_error_codes, soap->errnum);
+      if (!msg)
+#endif
+      { sprintf(soap->msgbuf, "TCP error %d", soap->errnum);
+        msg = soap->msgbuf;
+      }
+    }
+  }
+  return msg;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static const char*
+http_error(struct soap *soap, int status)
+{ register const char *msg = NULL;
+#ifndef WITH_LEAN
+  msg = soap_str_code(h_http_error_codes, status);
+  if (!msg)
+#endif
+  { sprintf(soap->msgbuf, "HTTP error %d", status);
+    msg = soap->msgbuf;
+  }
+  return msg;
+}
+#endif
+
+/******************************************************************************/
+/* WR[ */
+#ifndef WITH_IPV6
+/* ]WR */
+#ifndef MAC_CARBON
+#ifndef PALM_1
+static int
+tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr)
+{ unsigned long iadd;
+  struct hostent hostent, *host = &hostent;
+/* WR[ */
+#ifdef VXWORKS
+  int hostint;
+  char *addrcopy = (char*)malloc(strlen(addr) + 1); /*copy of addr. */
+  /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */
+  strncpy(addrcopy, addr, strlen(addr)+1);
+  iadd = inet_addr(addrcopy);
+#else
+/* ]WR */
+#if defined(_AIXVERSION_431) || defined(TRU64)
+  struct hostent_data ht_data;
+#endif
+  iadd = inet_addr(addr);
+/* WR[ */
+#endif
+/* ]WR */
+  if ((int)iadd != -1)
+  { memcpy(inaddr, &iadd, sizeof(iadd));
+/* WR[ */
+#ifdef VXWORKS
+    free(addrcopy);
+#endif
+/* ]WR */
+    return SOAP_OK;
+  }
+#if defined(__GLIBC__)
+  if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0)
+    host = NULL;
+#elif defined(_AIXVERSION_431) || defined(TRU64)
+  memset((void*)&ht_data, 0, sizeof(ht_data));
+  if (gethostbyname_r(addr, &hostent, &ht_data) < 0)
+  { host = NULL;
+    soap->errnum = h_errno;
+  }
+#elif defined(HAVE_GETHOSTBYNAME_R)
+  host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum);
+/* WR[ */
+#elif defined(VXWORKS)
+  /* If the DNS resolver library resolvLib has been configured in the vxWorks
+   * image, a query for the host IP address is sent to the DNS server, if the
+   * name was not found in the local host table. */
+  hostint = hostGetByName(addrcopy);
+  if (hostint == ERROR)
+  { host = NULL;
+    soap->errnum = soap_errno; 
+  }
+  free(addrcopy);  /*free() is placed after the error checking to assure that
+		    * errno captured is that from hostGetByName() */
+/* ]WR */
+#else
+  if (!(host = gethostbyname(addr)))
+    soap->errnum = h_errno;
+#endif
+  if (!host)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n"));
+    return SOAP_ERR;
+  }
+/* WR[ */
+#ifdef VXWORKS
+  inaddr->s_addr = hostint;
+#else
+/* ]WR */
+  memcpy(inaddr, host->h_addr, host->h_length);
+/* WR[ */
+#endif
+/* ]WR */
+  return SOAP_OK;
+}
+#endif
+#endif
+/* WR[ */
+#endif /* WITH_IPV6 */
+/* ]WR */
+
+/******************************************************************************/
+#ifndef MAC_CARBON
+#ifndef PALM_1
+static int
+tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port)
+{ struct sockaddr_in sockaddr;
+/* WR[ */
+#ifdef WITH_IPV6
+  struct addrinfo *addrinfo;
+  struct addrinfo hints;
+  struct addrinfo resaddr;
+  struct sockaddr_storage addrstorage;
+  int err;
+#endif /* WITH_IPV6 */
+/* ]WR */
+  register int fd;
+#ifndef WITH_LEAN
+  int len = SOAP_BUFLEN;
+  int set = 1;
+#endif
+  if (soap_valid_socket(soap->socket))
+    soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket);
+  soap->socket = SOAP_INVALID_SOCKET;
+  if (tcp_init(soap))
+  { soap_set_sender_error(soap, tcp_error(soap), "TCP initialization failed in tcp_connect()", SOAP_TCP_ERROR);
+    return -1;
+  }
+  soap->errmode = 0;
+/* WR[ */
+#ifdef WITH_IPV6
+  memset((void*)&hints, 0, sizeof(hints));
+  hints.ai_family = PF_UNSPEC;
+  hints.ai_socktype = SOCK_STREAM;
+  soap->errmode = 2;
+  if (soap->proxy_host)
+    err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &addrinfo);
+  else
+    err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);
+  if (addrinfo)
+  { resaddr = *addrinfo;
+    addrstorage = *((struct sockaddr_storage*)addrinfo->ai_addr);
+    resaddr.ai_addr = (struct sockaddr*)&addrstorage;
+    freeaddrinfo(addrinfo);
+  }
+  if (err)
+  { soap_set_sender_error(soap, gai_strerror(err), 
+    "TCP getaddrinfo on proxy host failed in tcp_connect()", SOAP_TCP_ERROR);
+    return -1;
+  }
+  fd = (int)socket(resaddr.ai_family, resaddr.ai_socktype, resaddr.ai_protocol); /* modified to use fd */
+  soap->errmode = 0;
+#else /* WITH_IPV6 */
+/* ]WR */
+  fd = (int)socket(AF_INET, SOCK_STREAM, 0);
+/* WR[ */
+#endif /* WITH_IPV6 */
+/* ]WR */
+  if (fd < 0)
+  { soap->errnum = soap_socket_errno;
+    soap_set_sender_error(soap, tcp_error(soap), "TCP socket failed in tcp_connect()", SOAP_TCP_ERROR);
+    return -1;
+  }
+#ifdef SOCKET_CLOSE_ON_EXEC
+#ifdef WIN32
+#ifndef UNDER_CE
+  SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
+#endif
+#else
+  fcntl (fd, F_SETFD, 1);
+#endif
+#endif
+#ifndef WITH_LEAN
+  if (soap->connect_flags & SO_LINGER)
+  { struct linger linger;
+    memset((void*)&linger, 0, sizeof(linger));
+    linger.l_onoff = 1;
+    linger.l_linger = 0;
+    if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
+    { soap->errnum = soap_socket_errno;
+      soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR);
+      soap->fclosesocket(soap, (SOAP_SOCKET)fd);
+      return -1;
+    }
+  }
+  if ((soap->connect_flags & ~SO_LINGER) && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, soap->connect_flags & ~SO_LINGER, (char*)&set, sizeof(int)))
+  { soap->errnum = soap_socket_errno;
+    soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt failed in tcp_connect()", SOAP_TCP_ERROR);
+    soap->fclosesocket(soap, (SOAP_SOCKET)fd);
+    return -1;
+  }
+  if (soap->keep_alive && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
+  { soap->errnum = soap_socket_errno;
+    soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR);
+    soap->fclosesocket(soap, (SOAP_SOCKET)fd);
+    return -1;
+  }
+  if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
+  { soap->errnum = soap_socket_errno;
+    soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR);
+    soap->fclosesocket(soap, (SOAP_SOCKET)fd);
+    return -1;
+  }
+  if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
+  { soap->errnum = soap_socket_errno;
+    soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR);
+    soap->fclosesocket(soap, (SOAP_SOCKET)fd);
+    return -1;
+  }
+#ifdef TCP_NODELAY
+  if (setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
+  { soap->errnum = soap_socket_errno;
+    soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR);
+    soap->fclosesocket(soap, (SOAP_SOCKET)fd);
+    return -1;
+  }
+#endif
+#endif
+/* WR[ */
+#ifndef WITH_IPV6
+/* ]WR */
+  memset((void*)&sockaddr, 0, sizeof(sockaddr));
+  sockaddr.sin_family = AF_INET;
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Open socket %d to host='%s'\n", fd, host));
+  soap->errmode = 2;
+  if (soap->proxy_host)
+  { if (soap->fresolve(soap, soap->proxy_host, &sockaddr.sin_addr))
+    { soap_set_sender_error(soap, tcp_error(soap), "TCP get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR);
+      soap->fclosesocket(soap, (SOAP_SOCKET)fd);
+      return -1;
+    }
+    sockaddr.sin_port = htons((short)soap->proxy_port);
+  }
+  else
+  { if (soap->fresolve(soap, host, &sockaddr.sin_addr))
+    { soap_set_sender_error(soap, tcp_error(soap), "TCP get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
+      soap->fclosesocket(soap, (SOAP_SOCKET)fd);
+      return -1;
+    }
+    sockaddr.sin_port = htons((short)port);
+  }
+  soap->errmode = 0;
+/* WR[ */
+#endif /* WITH_IPV6 */
+/* ]WR */
+#ifndef WITH_LEAN
+  if (soap->connect_timeout)
+#if defined(WIN32)
+  { u_long nonblocking = 1;
+    ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking);
+  }
+/* WR[ */
+#elif defined(VXWORKS)
+  { vx_nonblocking = TRUE;
+    ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */
+  }
+/* ]WR */
+#else
+    fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK);
+#endif
+  else
+#if defined(WIN32)
+  { u_long blocking = 0;
+    ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking);
+  }
+/* WR[ */
+#elif defined(VXWORKS)
+  { vx_nonblocking = FALSE;
+    ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */
+  }
+/* ]WR */
+#else
+    fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK);
+#endif
+#endif
+  for (;;)
+  { 
+/* WR[ */
+#ifdef WITH_IPV6
+    if (connect((SOAP_SOCKET)fd, resaddr.ai_addr, resaddr.ai_addrlen)) /* modified to use fd */
+#else /* WITH_IPV6 */
+    if (connect((SOAP_SOCKET)fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)))
+#endif /* WITH_IPV6 */
+/* ]WR */
+    { 
+#ifndef WITH_LEAN
+      if (soap->connect_timeout && (soap_socket_errno == SOAP_EINPROGRESS || soap_socket_errno == SOAP_EWOULDBLOCK))
+      { struct timeval timeout;
+#if defined(SOCKLEN_T)
+        SOCKLEN_T n = sizeof(struct sockaddr_in);
+#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN)
+        socklen_t n = sizeof(struct sockaddr_in);
+#elif defined(WIN32) || defined(__APPLE__) || defined(HP_UX) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS)
+        int n = sizeof(struct sockaddr_in);
+#else
+        size_t n = sizeof(struct sockaddr_in);
+#endif
+        fd_set fds;
+        if (soap->connect_timeout > 0)
+        { timeout.tv_sec = soap->connect_timeout;
+          timeout.tv_usec = 0;
+        }
+        else
+        { timeout.tv_sec = -soap->connect_timeout/1000000;
+          timeout.tv_usec = -soap->connect_timeout%1000000;
+        }
+        FD_ZERO(&fds);
+        FD_SET((SOAP_SOCKET)fd, &fds);
+        for (;;)
+        { int r = select((SOAP_SOCKET)(fd + 1), NULL, &fds, NULL, &timeout);
+          if (r > 0)
+	    break;
+          if (!r)
+          { soap->errnum = 0;
+            DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
+            soap_set_sender_error(soap, "Timeout", "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR);
+            soap->fclosesocket(soap, (SOAP_SOCKET)fd);
+            return -1;
+          }
+          if (soap_socket_errno != SOAP_EINTR)
+          { soap->errnum = soap_socket_errno;
+            DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
+            soap_set_sender_error(soap, tcp_error(soap), "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR);
+            soap->fclosesocket(soap, (SOAP_SOCKET)fd);
+            return -1;
+          }
+        }
+	n = sizeof(soap->errnum);
+        if (!getsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &n) && !soap->errnum)
+          break;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
+        soap_set_sender_error(soap, tcp_error(soap), "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR);
+        soap->fclosesocket(soap, (SOAP_SOCKET)fd);
+        return -1;
+      }
+      else
+#endif
+      if (soap_socket_errno != SOAP_EINTR)
+      { soap->errnum = soap_socket_errno;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
+        soap_set_sender_error(soap, tcp_error(soap), "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR);
+        soap->fclosesocket(soap, (SOAP_SOCKET)fd);
+        return -1;
+      }
+    }  
+    else
+      break;
+  }
+#ifndef WITH_LEAN
+  if (soap->connect_timeout)
+#if defined(WIN32)
+  { u_long blocking = 0;
+    ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking);
+  }
+/* WR[ */
+#elif defined(VXWORKS)
+  { vx_nonblocking = FALSE;
+    ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */
+  }
+/* ]WR */
+#else
+    fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK);
+#endif
+#endif
+  soap->socket = fd;
+#ifdef WITH_OPENSSL
+  soap->imode &= ~SOAP_ENC_SSL;
+  soap->omode &= ~SOAP_ENC_SSL;
+  if (!strncmp(endpoint, "https:", 6))
+  { int r;
+    if (soap->proxy_host)
+    { unsigned int k = soap->omode; /* make sure we only parse HTTP */
+      size_t n = soap->count; /* save the content length */
+      soap->omode &= ~0xFF; /* mask IO and ENC */
+      soap->omode |= SOAP_IO_BUFFER;
+      soap_begin_send(soap);
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to proxy server\n"));
+      sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->http_version);
+      if ((soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL)))
+        return -1;
+#ifndef WITH_LEAN
+      if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
+      { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
+        strcpy(soap->tmpbuf, "Basic ");
+        soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262));
+        if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
+          return soap->error;
+      }
+#endif
+      if ((soap->error = soap->fposthdr(soap, NULL, NULL))
+       || soap_flush(soap))
+        return -1;
+      soap->omode = k;
+      k = soap->imode;
+      soap->imode &= ~0xFF; /* mask IO and ENC */
+      if (soap_begin_recv(soap))
+        return -1;
+      soap->imode = k;
+      soap->count = n;
+      soap_begin_send(soap);
+    }
+    if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
+    { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR);
+      return -1;
+    }
+    soap->ssl = SSL_new(soap->ctx);
+    if (!soap->ssl)
+    { soap->error = SOAP_SSL_ERROR;
+      return -1;
+    }
+    if (soap->session)
+    { if (!strcmp(soap->session_host, host) && soap->session_port == port)
+        SSL_set_session(soap->ssl, soap->session);
+      SSL_SESSION_free(soap->session);
+      soap->session = NULL;
+    }
+    soap->imode |= SOAP_ENC_SSL;
+    soap->omode |= SOAP_ENC_SSL;
+    soap->bio = BIO_new_socket((SOAP_SOCKET)fd, BIO_NOCLOSE);
+    SSL_set_bio(soap->ssl, soap->bio, soap->bio);
+#ifndef WITH_LEAN
+    if (soap->connect_timeout)
+#ifdef WIN32
+    { u_long nonblocking = 1;
+      ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking);
+    }
+#else
+      fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK);
+#endif
+#endif
+    for (;;)
+    { if ((r = SSL_connect(soap->ssl)) <= 0)
+      { int err = SSL_get_error(soap->ssl, r);
+        if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
+        { soap_set_sender_error(soap, ssl_error(soap, r), "SSL connect failed in tcp_connect()", SOAP_SSL_ERROR);
+          return -1;
+        }
+        if (soap->connect_timeout)
+        { struct timeval timeout;
+          fd_set fds;
+          if (soap->connect_timeout > 0)
+          { timeout.tv_sec = soap->connect_timeout;
+            timeout.tv_usec = 0;
+          }
+          else
+          { timeout.tv_sec = -soap->connect_timeout/1000000;
+            timeout.tv_usec = -soap->connect_timeout%1000000;
+          }
+          FD_ZERO(&fds);
+          FD_SET((SOAP_SOCKET)(soap->socket), &fds);
+          for (;;)
+          { int r = select((SOAP_SOCKET)(soap->socket + 1), &fds, NULL, &fds, &timeout);
+            if (r > 0)
+	      break;
+            if (!r)
+            { soap->errnum = 0;
+              DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
+              soap_set_sender_error(soap, "Timeout", "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR);
+              return -1;
+            }
+          }
+	  continue;
+        }
+      }
+      break;
+    }
+#ifndef WITH_LEAN
+    if (soap->connect_timeout)
+#ifdef WIN32
+    { u_long blocking = 0;
+      ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking);
+    }
+#else
+      fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK);
+#endif
+#endif
+    if (soap->require_server_auth)
+    { X509 *peer;
+      int err;
+      if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
+      { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR);
+        return -1;
+      }
+      peer = SSL_get_peer_certificate(soap->ssl);
+      if (!peer)
+      { soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR);
+        return -1;
+      }
+      X509_NAME_get_text_by_NID(X509_get_subject_name(peer), NID_commonName, soap->msgbuf, sizeof(soap->msgbuf));
+      X509_free(peer);
+      if (soap_tag_cmp(soap->msgbuf, host))
+      { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR);
+        return -1;
+      }
+    }
+  }
+#endif
+  return fd;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef MAC_CARBON
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_bind(struct soap *soap, const char *host, int port, int backlog)
+{ struct sockaddr_in sockaddr;
+/* WR[ */
+#ifdef WITH_IPV6
+  struct addrinfo *addrinfo;
+  struct addrinfo hints;
+  struct addrinfo resaddr;
+  struct sockaddr_storage addrstorage;
+  int err;
+#endif /* WITH_IPV6 */
+/* ]WR */
+#ifndef WITH_LEAN
+  int len = SOAP_BUFLEN;
+  int set = 1;
+#endif
+  if (soap_valid_socket(soap->master))
+  { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master);
+    soap->master = SOAP_INVALID_SOCKET;
+  }
+  soap->socket = SOAP_INVALID_SOCKET;
+  soap->errmode = 1;
+  if (tcp_init(soap))
+  { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR);
+    return -1;
+  }
+/* WR[ */
+#ifdef WITH_IPV6
+  memset((void*)&hints, 0, sizeof(hints));
+  hints.ai_family = PF_UNSPEC;
+  hints.ai_socktype = SOCK_STREAM;
+  hints.ai_flags = AI_PASSIVE;
+  soap->errmode = 2;
+  if (host)
+    err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);
+  else
+    err = getaddrinfo(NULL, soap_int2s(soap, port), &hints, &addrinfo);
+  if (NULL != addrinfo)
+  {
+    resaddr = *addrinfo;
+    addrstorage = *((struct sockaddr_storage *) addrinfo->ai_addr);
+    resaddr.ai_addr = (struct sockaddr *) &addrstorage;
+    freeaddrinfo(addrinfo);
+  }
+  if (err)
+  { soap_set_receiver_error(soap, gai_strerror(err), "TCP getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR);
+    return -1;
+  }
+  soap->errmode = 0;
+  if ((soap->master = socket(resaddr.ai_family, resaddr.ai_socktype, resaddr.ai_protocol)) < 0)
+  { soap->errnum = soap_socket_errno;
+    soap_set_receiver_error(soap, tcp_error(soap), "TCP socket failed in soap_bind()", SOAP_TCP_ERROR);
+    return -1;
+  }
+#else /* WITH_IPV6 */
+/* ]WR */
+  soap->errmode = 0;
+  if ((soap->master = (int)socket(AF_INET, SOCK_STREAM, 0)) < 0)
+  { soap->errnum = soap_socket_errno;
+    soap_set_receiver_error(soap, tcp_error(soap), "TCP socket failed in soap_bind()", SOAP_TCP_ERROR);
+    return -1;
+  }
+/* WR[ */
+#endif /* WITH_IPV6 */
+/* ]WR */
+#ifdef SOCKET_CLOSE_ON_EXEC
+#ifdef WIN32
+#ifndef UNDER_CE
+  SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0);
+#endif
+#else
+  fcntl (soap->master, F_SETFD, 1);
+#endif
+#endif
+#ifndef WITH_LEAN
+  if (soap->bind_flags && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int)))
+  { soap->errnum = soap_socket_errno;
+    soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt failed in soap_bind()", SOAP_TCP_ERROR);
+    return -1;
+  }
+  if (soap->keep_alive && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
+  { soap->errnum = soap_socket_errno;
+    soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR);
+    return -1;
+  }
+  if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
+  { soap->errnum = soap_socket_errno;
+    soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR);
+    return -1;
+  }
+  if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
+  { soap->errnum = soap_socket_errno;
+    soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR);
+    return -1;
+  }
+#ifdef TCP_NODELAY
+  if (setsockopt((SOAP_SOCKET)soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
+  { soap->errnum = soap_socket_errno;
+    soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR);
+    return -1;
+  }
+#endif
+#endif
+/* WR[ */
+#ifdef WITH_IPV6
+  soap->errmode = 0;
+  if (bind(soap->master, resaddr.ai_addr, resaddr.ai_addrlen) || listen(soap->master, backlog))
+  { 
+    soap->errnum = soap_socket_errno;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
+    soap_closesock(soap);
+    soap_set_receiver_error(soap, tcp_error(soap), "TCP bind failed in soap_bind()", SOAP_TCP_ERROR);
+    return -1;
+  }  
+#else /* WITH_IPV6 */
+/* ]WR */
+  memset((void*)&sockaddr, 0, sizeof(sockaddr));
+  sockaddr.sin_family = AF_INET;
+  soap->errmode = 2;
+  if (host)
+  { if (soap->fresolve(soap, host, &sockaddr.sin_addr))
+    { soap_set_receiver_error(soap, tcp_error(soap), "TCP get host by name failed in soap_bind()", SOAP_TCP_ERROR);
+      return -1;
+    }
+  }
+  else
+    sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+  sockaddr.sin_port = htons((short)port);
+  soap->errmode = 0;
+  if (bind((SOAP_SOCKET)soap->master, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) || listen((SOAP_SOCKET)soap->master, backlog))
+  { soap->errnum = soap_socket_errno;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
+    soap_closesock(soap);
+    soap_set_receiver_error(soap, tcp_error(soap), "TCP bind failed in soap_bind()", SOAP_TCP_ERROR);
+    return -1;
+  }  
+/* WR[ */
+#endif /* WITH_IPV6 */
+/* ]WR */
+#ifdef WITH_OPENSSL
+  if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
+    return -1;
+#endif
+  return soap->master;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef MAC_CARBON
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_poll(struct soap *soap)
+{ 
+#ifndef WITH_LEAN
+  struct timeval timeout;
+  fd_set sfd,rfd;
+  int r;
+  timeout.tv_sec = 0;
+  timeout.tv_usec = 0;
+  FD_ZERO(&rfd);
+  FD_ZERO(&sfd);
+  if (soap->socket >= 0)
+  { FD_SET(soap->socket, &rfd);
+    FD_SET(soap->socket, &sfd);
+    r = select(soap->socket + 1, &rfd, &sfd, NULL, &timeout);
+  }
+  else if (soap->master >= 0)
+  { FD_SET(soap->master, &rfd);
+    r = select(soap->master + 1, &rfd, &sfd, NULL, &timeout);
+  }
+  else
+  { FD_SET(soap->sendfd, &sfd);
+    FD_SET(soap->recvfd, &rfd);
+    r = select((soap->sendfd > soap->recvfd ? soap->sendfd : soap->recvfd) + 1, &rfd, &sfd, NULL, &timeout);
+  }
+  if (r > 0)
+  {
+#ifdef WITH_OPENSSL
+    if (soap->ssl)
+    { if ((soap->socket >= 0) && FD_ISSET(soap->socket, &rfd))
+      { char buf = '\0';
+	if (SSL_peek(soap->ssl, &buf, 1) <= 0)
+  	  return SOAP_EOF;
+      }
+    }
+#endif   
+    return SOAP_OK;
+  }
+  if (r < 0 && (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno != SOAP_EINTR)
+  { soap->errnum = soap_socket_errno;
+    soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR);
+    return soap->error = SOAP_TCP_ERROR;
+  }
+  else
+    soap->errnum = soap_errno;
+  return SOAP_EOF;
+#else
+  return SOAP_OK;
+#endif
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef MAC_CARBON
+#ifndef PALM_1
+static int
+tcp_accept(struct soap *soap, int s, struct sockaddr *a, int *n)
+{ int fd;
+#if defined(SOCKLEN_T)
+  fd = (int)accept((SOAP_SOCKET)s, a, (SOCKLEN_T*)n);
+#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN)
+  fd = (int)accept((SOAP_SOCKET)s, a, (socklen_t*)n);
+#elif defined(WIN32) || defined(__APPLE__) || defined(HP_UX) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS)
+  fd = (int)accept((SOAP_SOCKET)s, a, n);
+#else
+  fd = (int)accept((SOAP_SOCKET)s, a, (size_t*)n);
+#endif
+#ifdef SOCKET_CLOSE_ON_EXEC
+#ifdef WIN32
+#ifndef UNDER_CE
+  SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
+#endif
+#else
+  fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
+#endif
+  return fd;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef MAC_CARBON
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_accept(struct soap *soap)
+{ 
+/* WR[ */
+#ifdef WITH_IPV6
+  struct sockaddr_storage sockaddr;
+#else /* WITH_IPV6 */
+/* ]WR */
+  struct sockaddr_in sockaddr;
+/* WR[ */
+#endif
+/* ]WR */
+  int n = (int)sizeof(sockaddr);
+#ifndef WITH_LEAN
+  int len = SOAP_BUFLEN;
+  int set = 1;
+#endif
+  soap->error = SOAP_OK;
+  memset((void*)&sockaddr, 0, sizeof(sockaddr));
+  soap->socket = SOAP_INVALID_SOCKET;
+  soap->errmode = 0;
+  if (soap_valid_socket(soap->master))
+  { for (;;)
+    { 
+#ifndef WITH_LEAN
+      if (soap->accept_timeout)
+      { struct timeval timeout;
+        fd_set fd;
+        if (soap->accept_timeout > 0)
+        { timeout.tv_sec = soap->accept_timeout;
+          timeout.tv_usec = 0;
+        }
+        else
+        { timeout.tv_sec = -soap->accept_timeout/1000000;
+          timeout.tv_usec = -soap->accept_timeout%1000000;
+        }
+        FD_ZERO(&fd);
+        FD_SET((SOAP_SOCKET)soap->master, &fd);
+        for (;;)
+        { int r = select((SOAP_SOCKET)(soap->master + 1), &fd, &fd, NULL, &timeout);
+          if (r > 0)
+            break;
+          if (!r)
+          { soap->errnum = 0;
+            soap_set_receiver_error(soap, "Timeout", "TCP accept failed in soap_accept()", SOAP_TCP_ERROR);
+            return -1;
+          }
+          if (soap_socket_errno != SOAP_EINTR)
+          { soap->errnum = soap_socket_errno;
+            soap_closesock(soap);
+            soap_set_sender_error(soap, tcp_error(soap), "TCP accept failed in soap_accept()", SOAP_TCP_ERROR);
+            return -1;
+          }
+        }
+#if defined(WIN32)
+	{ u_long nonblocking = 1;
+          ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &nonblocking);
+        }
+#elif defined(VXWORKS)
+        { vx_nonblocking = TRUE;
+          ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking));
+        }
+#else
+        fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)|O_NONBLOCK);
+#endif
+      }
+      else
+#if defined(WIN32)
+      { u_long blocking = 0;
+        ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking);
+      }
+/* WR[ */
+#elif defined(VXWORKS)
+      { vx_nonblocking = FALSE;
+        ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking));
+      }
+/* ]WR */
+#else
+        fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK);
+#endif
+#endif
+      if ((soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&sockaddr, &n)) >= 0)
+      {
+/* WR[ */
+#ifdef WITH_IPV6
+/* Use soap->host to store the numeric form of the remote host */
+        getnameinfo((struct sockaddr*)&sockaddr, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); 
+        DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host));
+        soap->ip = 0; /* info stored in soap->host */
+        soap->port = 0; /* info stored in soap->host */
+#else /* WITH_IPV6 */
+/* ]WR */
+        soap->ip = ntohl(sockaddr.sin_addr.s_addr);
+        soap->port = (int)ntohs(sockaddr.sin_port); /* does not return port number on some systems */
+        DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d at port %d from IP %d.%d.%d.%d\n", soap->socket, soap->port, (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF));
+/* WR[ */
+#endif /* WITH_IPV6 */
+/* ]WR */
+        soap->keep_alive = ((soap->imode & SOAP_IO_KEEPALIVE) != 0);
+#ifndef WITH_LEAN
+	if (soap->accept_flags & SO_LINGER)
+        { struct linger linger;
+          memset((void*)&linger, 0, sizeof(linger));
+          linger.l_onoff = 1;
+          linger.l_linger = 0;
+	  if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
+          { soap->errnum = soap_socket_errno;
+	    soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR);
+            return -1;
+	  }
+        }
+        if ((soap->accept_flags & ~SO_LINGER) && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, soap->accept_flags & ~SO_LINGER, (char*)&set, sizeof(int)))
+        { soap->errnum = soap_socket_errno;
+          soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt failed in soap_accept()", SOAP_TCP_ERROR);
+          return -1;
+        }
+        if (soap->keep_alive && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
+        { soap->errnum = soap_socket_errno;
+          soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR);
+          return -1;
+        }
+        if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
+        { soap->errnum = soap_socket_errno;
+          soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR);
+          return -1;
+        }
+        if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
+        { soap->errnum = soap_socket_errno;
+          soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR);
+          return -1;
+        }
+#ifdef TCP_NODELAY
+        if (setsockopt((SOAP_SOCKET)soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
+        { soap->errnum = soap_socket_errno;
+          soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR);
+          return -1;
+        }
+#endif
+#endif
+        if (soap->accept_timeout)
+        {
+#if defined(WIN32)
+          u_long blocking = 0;
+          ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking);
+          ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking);
+/* WR[ */
+#elif defined(VXWORKS)
+          vx_nonblocking = FALSE;
+          ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking));
+          ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)(&vx_nonblocking));
+/* ]WR */
+#elif defined(PALM)
+          fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL,0)&~O_NONBLOCK);
+          fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL,0)&~O_NONBLOCK);
+#elif defined(SYMBIAN)
+          long blocking = 0;
+          ioctl((SOAP_SOCKET)soap->master, 0/*FIONBIO*/, &blocking);
+#else
+          fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK);
+          fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK);
+#endif
+	}
+        return soap->socket;
+      }
+      if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN)
+      { soap->errnum = soap_socket_errno;
+        soap_set_receiver_error(soap, tcp_error(soap), "TCP accept failed in soap_accept()", SOAP_TCP_ERROR);
+        return -1;
+      }
+    }
+  }
+  else
+  { soap_set_receiver_error(soap, tcp_error(soap), "TCP no master socket in soap_accept()", SOAP_TCP_ERROR);
+    return -1;
+  }
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef MAC_CARBON
+#ifndef PALM_1
+static int
+tcp_disconnect(struct soap *soap)
+{
+#ifdef WITH_OPENSSL
+  if (soap->ssl)
+  { int r, s = 0;
+    if (soap->session)
+      SSL_SESSION_free(soap->session);
+    if (*soap->host)
+    { soap->session = SSL_get1_session(soap->ssl);
+      if (soap->session)
+      { strcpy(soap->session_host, soap->host);
+        soap->session_port = soap->port;
+      }
+    }
+    r = SSL_shutdown(soap->ssl);
+    if (r != 1)
+    { s = ERR_get_error();
+      if (s)
+      { if (soap_valid_socket(soap->socket))
+        { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1);
+          soap->socket = SOAP_INVALID_SOCKET;
+        }
+        r = SSL_shutdown(soap->ssl);
+      }
+    }
+    DBGLOG(TEST, if (s) SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r)));
+    SSL_free(soap->ssl);
+    soap->ssl = NULL;
+    if (s)
+      return SOAP_SSL_ERROR;
+    ERR_remove_state(0);
+  }
+#endif
+  if (soap_valid_socket(soap->socket))
+  { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Closing socket %d\n", soap->socket));
+    soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 2);
+    soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket);
+    soap->socket = SOAP_INVALID_SOCKET;
+  }
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef MAC_CARBON
+#ifndef PALM_1
+static int
+tcp_closesocket(struct soap *soap, SOAP_SOCKET fd)
+{ return closesocket(fd);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef MAC_CARBON
+#ifndef PALM_1
+static int
+tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how)
+{ return shutdown(fd, how);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_closesock(struct soap *soap)
+{ register int status = soap->error;
+#ifndef MAC_CARBON
+  if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive)
+  { if ((soap->error = soap->fclose(soap)))
+      return soap->error;
+    soap->socket = SOAP_INVALID_SOCKET;
+  }
+#endif
+#ifdef WITH_ZLIB
+  if (soap->zlib_state == SOAP_ZLIB_DEFLATE)
+    deflateEnd(&soap->d_stream);
+  else if (soap->zlib_state == SOAP_ZLIB_INFLATE)
+    inflateEnd(&soap->d_stream);
+  soap->zlib_state = SOAP_ZLIB_NONE;
+#endif
+  return soap->error = status;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+size_t
+SOAP_FMAC2
+soap_hash(register const char *s)
+{ register size_t h = 0;
+  while (*s)
+    h = 65599*h + *s++;
+  return h % SOAP_IDHASH;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static void
+soap_init_pht(struct soap *soap)
+{ register int i;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing pointer hashtable\n"));
+  for (i = 0; i < (int)SOAP_PTRHASH; i++)
+    soap->pht[i] = NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+struct soap*
+SOAP_FMAC2
+soap_new()
+{ struct soap *soap = (struct soap*)SOAP_MALLOC(sizeof(struct soap));
+  if (soap)
+    soap_init(soap);
+  return soap;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+struct soap*
+SOAP_FMAC2
+soap_new1(int mode)
+{ return soap_new2(mode, mode);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+struct soap*
+SOAP_FMAC2
+soap_new2(int imode, int omode)
+{ struct soap *soap = (struct soap*)SOAP_MALLOC(sizeof(struct soap));
+  if (soap)
+    soap_init2(soap, imode, omode);
+  return soap;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static void
+soap_free_pht(struct soap *soap)
+{ register struct soap_plist *pp, *next;
+  register int i;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n"));
+  for (i = 0; i < (int)SOAP_PTRHASH; i++)
+  { for (pp = soap->pht[i]; pp; pp = next)
+    { next = pp->next;
+      SOAP_FREE(pp);
+    }
+    soap->pht[i] = NULL;
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type)
+{ register int i;
+  struct soap_plist *pp;
+  if (soap->version != 1)
+    soap->encoding = 1;
+  if (a)
+    i = soap_array_pointer_lookup(soap, p, a, n, type, &pp);
+  else
+    i = soap_pointer_lookup(soap, p, type, &pp);
+  if (i)
+  { if (soap_is_embedded(soap, pp)
+     || soap_is_single(soap, pp))
+      return 0;
+    soap_set_embedded(soap, pp);
+  }
+  return i;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp)
+{ register struct soap_plist *pp;
+  *ppp = NULL;
+  if (p)
+    for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next)
+      if (pp->ptr == p && pp->type == type)
+      { *ppp = pp;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id));
+        return pp->id;
+      }
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type));
+  return 0;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
+{ register int h;
+  register struct soap_plist *pp = *ppp = (struct soap_plist*)SOAP_MALLOC(sizeof(struct soap_plist));
+  if (!pp)
+    return 0;
+  if (a)
+    h = soap_hash_ptr(a->__ptr);
+  else
+    h = soap_hash_ptr(p);
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%d dim=%d type=%d id=%lu\n", p, a?a->__ptr:NULL, a?a->__size:0, n, type, soap->idnum+1));
+  pp->next = soap->pht[h];
+  pp->type = type;
+  pp->mark1 = 0;
+  pp->mark2 = 0;
+  pp->ptr = p;
+  pp->array = a;
+  soap->pht[h] = pp;
+  pp->id = ++soap->idnum;
+  return pp->id;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
+{ register struct soap_plist *pp;
+  *ppp = NULL;
+  if (!p || !a->__ptr)
+    return 0;
+  for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next)
+  { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr)
+    { register int i;
+      for (i = 0; i < n; i++)
+        if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i])
+	  break;
+      if (i == n)
+      { *ppp = pp;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id));
+        return pp->id;
+      }
+    }
+  }
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type));
+  return 0;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_begin_count(struct soap *soap)
+{ soap_clr_attr(soap);
+  soap_set_local_namespaces(soap);
+#ifndef WITH_LEANER
+  if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME))
+    soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME;
+  else
+#endif
+  { soap->mode = soap->omode;
+    if ((soap->mode & SOAP_IO) == SOAP_IO_STORE
+     || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML)) && !soap->fpreparesend))
+      soap->mode &= ~SOAP_IO_LENGTH;
+    else
+      soap->mode |= SOAP_IO_LENGTH;
+  }
+  if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
+  { if (!(soap->mode & SOAP_ENC_DIME))
+      soap->mode &= ~SOAP_IO_LENGTH;
+    if (soap->mode & SOAP_ENC_XML)
+      soap->mode |= SOAP_IO_BUFFER;
+    else
+      soap->mode |= SOAP_IO_STORE;
+  }
+  if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
+    soap->mode |= SOAP_XML_TREE;
+#ifndef WITH_LEANER
+  if (soap->mode & SOAP_ENC_MIME)
+    soap_select_mime_boundary(soap);
+  soap->dime.list = soap->dime.last;	/* keep track of last DIME attachment */
+#endif
+  soap->count = 0;
+  soap->ns = 0;
+  soap->null = 0;
+  soap->position = 0;
+  soap->mustUnderstand = 0;
+  soap->encoding = 0;
+  soap->part = SOAP_BEGIN;
+  soap->idnum = 0;
+  soap->dime.count = 0; /* count # of attachments */
+  soap->dime.size = 0; /* accumulate total size of attachments */
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count));
+  if (soap->fprepareinit && (soap->mode & SOAP_IO) != SOAP_IO_STORE)
+    soap->fprepareinit(soap);   
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_begin_send(struct soap *soap)
+{ soap->error = SOAP_OK;
+  soap_clr_attr(soap);
+  soap_set_local_namespaces(soap);
+  soap->mode = (soap->omode & ~SOAP_IO_LENGTH) | (soap->mode & SOAP_ENC_DIME);
+  if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
+  { if (soap->mode & SOAP_ENC_XML)
+      soap->mode |= SOAP_IO_BUFFER;
+    else
+      soap->mode |= SOAP_IO_STORE;
+  }
+  if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket))
+  { if (soap->count || (soap->mode & SOAP_ENC_XML))
+      soap->mode |= SOAP_IO_BUFFER;
+    else
+      soap->mode |= SOAP_IO_STORE;
+  }
+  if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
+    soap_new_block(soap);
+  if (!(soap->mode & SOAP_IO_KEEPALIVE))
+    soap->keep_alive = 0;
+  if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
+    soap->mode |= SOAP_XML_TREE;
+#ifndef WITH_LEANER
+  if (soap->mode & SOAP_ENC_MIME)
+    soap_select_mime_boundary(soap);
+#endif
+#ifdef WIN32
+#ifndef UNDER_CE
+#ifndef WITH_FASTCGI
+  if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
+#ifdef __BORLANDC__
+    setmode((SOAP_SOCKET)soap->sendfd, O_BINARY);
+#else
+    _setmode((SOAP_SOCKET)soap->sendfd, _O_BINARY);
+#endif
+#endif
+#endif
+#endif
+  if (soap->mode & SOAP_IO)
+  { soap->bufidx = 0;
+    soap->buflen = 0;
+  }
+  soap->chunksize = 0;
+  soap->ns = 0;
+  soap->null = 0;
+  soap->position = 0;
+  soap->mustUnderstand = 0;
+  soap->encoding = 0;
+  soap->part = SOAP_BEGIN;
+  soap->idnum = 0;
+  soap->level = 0;
+#ifdef WITH_ZLIB
+  soap->z_ratio_out = 1.0;
+  if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE)
+  {
+#ifdef WITH_GZIP
+    memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10);
+    soap->d_stream.next_out = (Byte*)soap->z_buf + 10;
+    soap->d_stream.avail_out = SOAP_BUFLEN - 10;
+    soap->z_crc = crc32(0L, NULL, 0);
+    if (deflateInit2(&soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK)
+#else
+    soap->d_stream.next_out = (Byte*)soap->z_buf;
+    soap->d_stream.avail_out = SOAP_BUFLEN;
+    if (deflateInit(&soap->d_stream, soap->z_level) != Z_OK)
+#endif
+      return soap->error = SOAP_ZLIB_ERROR;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n"));
+    soap->zlib_state = SOAP_ZLIB_DEFLATE;
+  }
+#endif
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count));
+  if (soap->fprepareinit && (soap->mode & SOAP_IO) == SOAP_IO_STORE)
+    soap->fprepareinit(soap);   
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_embedded(struct soap *soap, const void *p, int t)
+{ struct soap_plist *pp;
+  if (soap_pointer_lookup(soap, p, t, &pp))
+  { pp->mark1 = 1;
+    pp->mark2 = 1;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t));
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_reference(struct soap *soap, const void *p, int t)
+{ struct soap_plist *pp;
+  if (!p || (soap->mode & SOAP_XML_TREE))
+    return 1;
+  if (soap_pointer_lookup(soap, p, t, &pp))
+  { if (pp->mark1 == 0)
+    { pp->mark1 = 2;
+      pp->mark2 = 2;
+    }
+  }
+  else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp))
+  { pp->mark1 = 0;
+    pp->mark2 = 0;
+  }
+  else
+    return 1;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2));
+  return pp->mark1;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t)
+{ register int i;
+  struct soap_plist *pp;
+  if (!p)
+    return 1;
+  i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
+  if (i)
+  { if (pp->mark1 == 0)
+    { pp->mark1 = 2;
+      pp->mark2 = 2;
+    }
+  }
+  else if (!soap_pointer_enter(soap, p, a, n, t, &pp))
+    return 1;
+  else
+  { pp->mark1 = 0;
+    pp->mark2 = 0;
+  }
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p dim=%d type=%d (%d %d)\n", p, a->__ptr, n, t, (int)pp->mark1, (int)pp->mark2));
+  return pp->mark1;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_embedded_id(struct soap *soap, int id, const void *p, int t)
+{ struct soap_plist *pp;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id));
+  if (soap->mode & SOAP_XML_TREE)
+    return id;
+  if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
+  { if (id < 0)
+    { id = soap_pointer_lookup(soap, p, t, &pp);
+      if (id)
+      { if (soap->mode & SOAP_IO_LENGTH)
+          pp->mark1 = 2;
+        else
+          pp->mark2 = 2;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2));
+      }
+      return -1;
+    }
+    return id;
+  }
+  if (id < 0)
+    id = soap_pointer_lookup(soap, p, t, &pp);
+  else if (id && !soap_pointer_lookup(soap, p, t, &pp))
+    return 0;
+  if (id && pp)
+  { if (soap->mode & SOAP_IO_LENGTH)
+      pp->mark1 = 1;
+    else
+      pp->mark2 = 1;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2));
+  }
+  return id;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_is_embedded(struct soap *soap, struct soap_plist *pp)
+{ if (!pp)
+    return 0;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2));
+  if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
+  { if (soap->mode & SOAP_IO_LENGTH)
+      return pp->mark1 != 0;
+    return pp->mark2 != 0;
+  }
+  if (soap->mode & SOAP_IO_LENGTH)
+    return pp->mark1 == 1;
+  return pp->mark2 == 1;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_is_single(struct soap *soap, struct soap_plist *pp)
+{ if (soap->part == SOAP_IN_HEADER)
+    return 1;
+  if (!pp)
+    return 0;
+  if (soap->mode & SOAP_IO_LENGTH)
+    return pp->mark1 == 0;
+  return pp->mark2 == 0;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_embedded(struct soap *soap, struct soap_plist *pp)
+{ if (!pp)
+    return;
+  if (soap->mode & SOAP_IO_LENGTH)
+    pp->mark1 = 1;
+  else
+    pp->mark2 = 1;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_dime(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, const char *aid, const char *atype, const char *aoptions, int n, const char *type, int t) 
+{ struct soap_plist *pp;
+  if (!p || !a->__ptr || (!aid && !atype))
+    return soap_element_id(soap, tag, id, p, a, n, type, t);
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid?aid:"", id, atype?atype:""));
+  if (id < 0)
+    id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
+  if (!aid)
+  { sprintf(soap->tmpbuf, soap->dime_id_format, id);
+    aid = soap_strdup(soap, soap->tmpbuf);
+  }
+  if (soap_element_href(soap, tag, 0, "href", aid))
+    return soap->error;
+  if (soap->mode & SOAP_IO_LENGTH)
+  { if (pp->mark1 != 3)
+    { struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size);
+      if (!content)
+        return soap->error = SOAP_EOM;
+      content->id = aid;
+      content->type = atype;
+      content->options = aoptions;
+      pp->mark1 = 3;
+    }
+  }
+  else
+    pp->mark2 = 3;
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static void
+soap_init_iht(struct soap *soap)
+{ register int i;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing ID hashtable\n"));
+  for (i = 0; i < SOAP_IDHASH; i++)
+    soap->iht[i] = NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static void
+soap_free_iht(struct soap *soap)
+{ register int i;
+  register struct soap_ilist *ip, *p;
+  register struct soap_flist *fp, *fq;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n"));
+  for (i = 0; i < SOAP_IDHASH; i++)
+  { for (ip = soap->iht[i]; ip; ip = p)
+    { for (fp = ip->flist; fp; fp = fq)
+      { fq = fp->next;
+        SOAP_FREE(fp);
+      }
+      p = ip->next;
+      SOAP_FREE(ip);
+    }
+    soap->iht[i] = NULL;
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+static struct soap_ilist *
+soap_hlookup(struct soap *soap, const char *id)
+{ register struct soap_ilist *ip;
+  for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next)
+    if (!strcmp(ip->id, id))
+      return ip;
+  return NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+struct soap_ilist *
+SOAP_FMAC2
+soap_lookup(struct soap *soap, const char *id)
+{ register struct soap_ilist *ip;
+  ip = soap_hlookup(soap, id);
+#ifndef WITH_LEANER
+  if (!ip && *id != '#' && !strchr(id, ':')) /* try content id "cid:" with DIME attachments */
+  { char cid[SOAP_TAGLEN];
+    strcpy(cid, "cid:");
+    strncat(cid + 4, id, sizeof(cid) - 5);
+    cid[sizeof(cid) - 1] = '\0';
+    ip = soap_hlookup(soap, cid);
+  }
+#endif
+  return ip;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+struct soap_ilist *
+SOAP_FMAC2
+soap_enter(struct soap *soap, const char *id)
+{ register size_t h;
+  register struct soap_ilist *ip;
+  ip = (struct soap_ilist*)SOAP_MALLOC(sizeof(struct soap_ilist) + strlen(id));
+  if (ip)
+  { h = soap_hash(id);
+    strcpy(ip->id, id);
+    ip->next = soap->iht[h];
+    soap->iht[h] = ip;
+    return ip;
+  }
+  return NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void*
+SOAP_FMAC2
+soap_malloc(struct soap *soap, size_t n)
+{ register char *p;
+  if (!n)
+    return NULL;
+  if (!soap)
+    return SOAP_MALLOC(n);
+  n += (-(long)n) & 7;
+  if (!(p = (char*)SOAP_MALLOC(n + sizeof(void*) + sizeof(size_t))))
+  { soap->error = SOAP_EOM;
+    return NULL;
+  }
+  /* keep chain of alloced cells for later destruction */
+  soap->alloced = 1;
+  *(void**)(p + n) = soap->alist;
+  *(size_t*)(p + n + sizeof(void*)) = n;
+  soap->alist = p + n;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Malloc %u bytes at location %p\n", (unsigned int)n, p));
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_dealloc(struct soap *soap, void *p)
+{ if (!soap)
+    return;
+  if (p)
+  { register char **q;
+    for (q = (char**)&soap->alist; *q; q = *(char***)q)
+    { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
+      { *q = **(char***)q;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p));
+        SOAP_FREE(p);
+        return;
+      }
+    }
+    soap_delete(soap, p);
+  }
+  else
+  { register char *q;
+    while (soap->alist)
+    { q = (char*)soap->alist;
+      soap->alist = *(void**)q;
+      q -= *(size_t*)(q + sizeof(void*));
+      SOAP_FREE(q);
+    }
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Dealloc all data done\n"));
+  }
+  /* we must assume these were deallocated: */
+  soap->action = NULL;
+  soap->fault = NULL;
+  soap->header = NULL;
+  soap->authrealm = NULL;
+#ifndef WITH_LEANER
+  soap_clr_mime(soap);
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_delete(struct soap *soap, void *p)
+{ register struct soap_clist **cp = &soap->clist;
+  if (p)
+  { while (*cp)
+    { if (p == (*cp)->ptr)
+      { register struct soap_clist *q = *cp;
+        *cp = q->next;
+        q->fdelete(q);
+        SOAP_FREE(q);
+        return;
+      }
+      cp = &(*cp)->next;
+    }
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p));
+  }
+  else
+  { while (*cp)
+    { register struct soap_clist *q = *cp;
+      *cp = q->next;
+      if (q->ptr == (void*)soap->fault)
+        soap->fault = NULL; /* this was deallocated */
+      else if (q->ptr == (void*)soap->header)
+        soap->header = NULL; /* this was deallocated */
+      q->fdelete(q);
+      SOAP_FREE(q);
+    }
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+struct soap_clist *
+SOAP_FMAC2
+soap_link(struct soap *soap, void *p, int t, int n, void (*fdelete)(struct soap_clist*))
+{ register struct soap_clist *cp;
+  if ((cp = (struct soap_clist*)SOAP_MALLOC(sizeof(struct soap_clist))))
+  { cp->next = soap->clist;
+    cp->type = t;
+    cp->size = n; 
+    cp->ptr = p;
+    cp->fdelete = fdelete;
+    soap->clist = cp;
+  }
+  return cp;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_unlink(struct soap *soap, const void *p)
+{ register char **q;
+  register struct soap_clist **cp;
+  if (!soap || !p)
+    return;
+  for (q = (char**)&soap->alist; *q; q = *(char***)q)
+  { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
+    { *q = **(char***)q;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p));
+      return;
+    }
+  }
+  for (cp = &soap->clist; *cp; cp = &(*cp)->next)
+  { if (p == (*cp)->ptr)
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p));
+      q = (char**)*cp;
+      *cp = (*cp)->next;
+      SOAP_FREE(q);
+      return;
+    }
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_lookup_type(struct soap *soap, const char *id)
+{ register struct soap_ilist *ip;
+  if (id && *id)
+  { ip = soap_lookup(soap, id);
+    if (ip)
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type));
+      return ip->type;
+    }
+  }
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id));
+  return 0;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void*
+SOAP_FMAC2
+soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k)
+{ struct soap_ilist *ip;
+  void **q;
+  if (!id || !*id)
+    return p;
+  soap->alloced = 0;
+  if (!p)
+    p = (void**)soap_malloc(soap, sizeof(void*));
+  ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
+  if (!ip)
+  { ip = soap_enter(soap, id); /* new hash table entry for string id */
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n));
+    ip->type = t;
+    ip->size = n; 
+    ip->link = p;
+    ip->copy = NULL;
+    ip->flist = NULL;
+    ip->ptr = NULL;
+    ip->level = k;
+    *p = NULL;
+  }
+  else if (ip->ptr)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n));
+    if (ip->type != t)
+    { strcpy(soap->id, id);
+      soap->error = SOAP_HREF;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: id type=%d href type=%d\n", ip->type, t));
+      return NULL;
+    }
+    while (ip->level < k)
+    { q = (void**)soap_malloc(soap, sizeof(void*));  
+      if (!q)
+        return NULL;
+      *p = (void*)q;
+      p = q;
+      k--;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
+    }
+    *p = ip->ptr;
+  }
+  else if (ip->level > k)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id));
+    while (ip->level > k)
+    { void *s, **r = &ip->link;
+      q = (void**)ip->link;
+      while (q)
+      { *r = (void*)soap_malloc(soap, sizeof(void*));
+        s = *q;
+        *q = *r;
+        r = (void**)*r;
+        q = (void**)s;
+      }
+      *r = NULL;
+      ip->size = n; 
+      ip->copy = NULL;
+      ip->level = ip->level - 1;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
+    }
+    q = (void**)ip->link;
+    ip->link = p;
+    *p = (void*)q;
+  }
+  else
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n));
+    while (ip->level < k)
+    { q = (void**)soap_malloc(soap, sizeof(void*));  
+      *p = q;
+      p = q;
+      k--;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
+    }
+    q = (void**)ip->link;
+    ip->link = p;
+    *p = (void*)q;
+  }
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void*
+SOAP_FMAC2
+soap_id_forward(struct soap *soap, const char *href, void *p, int st, int tt, size_t n, unsigned int k, void (*fcopy)(struct soap*, int, int, void*, const void*, size_t))
+{ struct soap_ilist *ip;
+  if (!p || !href || !*href)
+    return p;
+  ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */
+  if (!ip)
+  { ip = soap_enter(soap, href); /* new hash table entry for string id */
+    ip->type = st;
+    ip->size = n;
+    ip->link = NULL;
+    ip->copy = NULL;
+    ip->ptr = NULL;
+    ip->level = 0;
+    ip->flist = NULL;
+    DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, st, (unsigned long)n, k, p));
+  }
+  else if (ip->type != st || (ip->level == k && ip->size != n))
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, st, (unsigned long)n));
+    strcpy(soap->id, href);
+    soap->error = SOAP_HREF;
+    return NULL;
+  }
+  if (fcopy || n < sizeof(void*) || *href != '#')
+  { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(sizeof(struct soap_flist));
+    if (!fp)
+    { soap->error = SOAP_EOM;
+      return NULL;
+    }
+    fp->next = ip->flist;
+    fp->type = tt;
+    fp->ptr = p;
+    fp->level = k;
+    if (fcopy)
+      fp->fcopy = fcopy;
+    else
+      fp->fcopy = soap_fcopy;
+    ip->flist = fp;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u href='%s'\n", st, tt, (unsigned long)n, p, k, href));
+  }
+  else
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href));
+    *(void**)p = ip->copy;
+    ip->copy = p;
+  }
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void*
+SOAP_FMAC2
+soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*))
+{ struct soap_ilist *ip;
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k));
+  soap->alloced = 0;
+  if (!p)
+  { if (finstantiate)
+      p = finstantiate(soap, t, type, arrayType, &n);
+    else
+      p = soap_malloc(soap, n);
+    if (p)
+      soap->alloced = 1;
+  }
+  if (!id || !*id)
+    return p;
+  ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p));
+  if (!ip)
+  { ip = soap_enter(soap, id); /* new hash table entry for string id */
+    ip->type = t;
+    ip->link = NULL;
+    ip->copy = NULL;
+    ip->flist = NULL;
+    ip->size = n;
+    ip->ptr = p;
+    ip->level = k;
+    DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu level=%u location=%p\n", id, t, (unsigned long)n, k, p));
+  }
+  else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist))
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n));
+    strcpy(soap->id, id);
+    soap->error = SOAP_HREF;
+    return NULL;
+  }
+  else if (ip->ptr)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id));
+    strcpy(soap->id, id);
+    soap->error = SOAP_MULTI_ID;
+    return NULL;
+  }
+  else 
+  { ip->size = n;
+    ip->ptr = p;
+    ip->level = k;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update entry id='%s' type=%d location=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k));
+  }
+  return ip->ptr;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_fcopy(struct soap *soap, int st, int tt, void *p, const void *q, size_t n)
+{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n));
+  memcpy(p, q, n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_end_send(struct soap *soap)
+{ 
+#ifndef WITH_LEANER
+  if (soap->dime.list)
+  { /* SOAP body referenced attachments must appear first */
+    soap->dime.last->next = soap->dime.first;
+    soap->dime.first = soap->dime.list->next;
+    soap->dime.list->next = NULL;
+    soap->dime.last = soap->dime.list;
+  }
+  if (soap_putdime(soap) || soap_putmime(soap))
+    return soap->error;
+  soap->mime.list = NULL;
+  soap->mime.first = NULL;
+  soap->mime.last = NULL;
+  soap->dime.list = NULL;
+  soap->dime.first = NULL;
+  soap->dime.last = NULL;
+#endif
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n"));
+  if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */
+  { if (soap_flush(soap))
+#ifdef WITH_ZLIB
+    { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE)
+      { soap->zlib_state = SOAP_ZLIB_NONE;
+        deflateEnd(&soap->d_stream);
+      }
+      return soap->error;
+    }
+#else
+      return soap->error;
+#endif
+#ifdef WITH_ZLIB
+    if (soap->mode & SOAP_ENC_ZLIB)
+    { int r;
+      soap->d_stream.avail_in = 0;
+      do
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n"));
+        r = deflate(&soap->d_stream, Z_FINISH);
+        if (soap->d_stream.avail_out != SOAP_BUFLEN)
+        { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream.avail_out))
+          { soap->zlib_state = SOAP_ZLIB_NONE;
+            deflateEnd(&soap->d_stream);
+            return soap->error;
+	  }
+          soap->d_stream.next_out = (Byte*)soap->z_buf;
+          soap->d_stream.avail_out = SOAP_BUFLEN;
+        }
+      } while (r == Z_OK);
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out));
+      soap->z_ratio_out = (float)soap->d_stream.total_out / (float)soap->d_stream.total_in;
+      soap->mode &= ~SOAP_ENC_ZLIB;
+      soap->zlib_state = SOAP_ZLIB_NONE;
+      if (deflateEnd(&soap->d_stream) != Z_OK || r != Z_STREAM_END)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:""));
+        return soap->error = SOAP_ZLIB_ERROR;
+      }
+#ifdef WITH_GZIP
+      soap->z_buf[0] = soap->z_crc & 0xFF;
+      soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF;
+      soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF;
+      soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF;
+      soap->z_buf[4] = soap->d_stream.total_in & 0xFF;
+      soap->z_buf[5] = (soap->d_stream.total_in >> 8) & 0xFF;
+      soap->z_buf[6] = (soap->d_stream.total_in >> 16) & 0xFF;
+      soap->z_buf[7] = (soap->d_stream.total_in >> 24) & 0xFF;
+      if (soap_flush_raw(soap, soap->z_buf, 8))
+        return soap->error;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc));
+#endif
+    }
+#endif
+    if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
+    { char *p;
+      if (!(soap->mode & SOAP_ENC_XML))
+      { soap->mode--;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size));
+        if (soap->status >= SOAP_POST)
+          soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size);
+        else if (soap->status != SOAP_STOP)
+          soap->error = soap->fresponse(soap, soap->status, soap->blist->size);
+        if (soap->error || soap_flush(soap))
+          return soap->error;
+        soap->mode++;
+      }
+      for (p = soap_first_block(soap); p; p = soap_next_block(soap))
+      { DBGMSG(SENT, p, soap_block_size(soap));
+        if ((soap->error = soap->fsend(soap, p, soap_block_size(soap))))
+        { soap_end_block(soap);
+          return soap->error;
+        }
+      }
+      soap_end_block(soap);
+    }
+    else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
+    { DBGMSG(SENT, "\r\n0\r\n\r\n", 7);
+      if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7)))
+        return soap->error;
+    }
+  }
+#ifdef WITH_OPENSSL
+  if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive)
+    soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */
+#else
+  if (soap_valid_socket(soap->socket) && !soap->keep_alive)
+    soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */
+#endif
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send message ok\n"));
+  soap->part = SOAP_END;
+  soap->count = 0;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_end_recv(struct soap *soap)
+{ soap->part = SOAP_END;
+#ifndef WITH_LEANER
+  if ((soap->mode & SOAP_ENC_MIME) && soap_getmime(soap))
+    return soap->error;
+  soap->mime.list = soap->mime.first;
+  soap->mime.first = NULL;
+  soap->mime.last = NULL;
+  soap->dime.list = soap->dime.first;
+  soap->dime.first = NULL;
+  soap->dime.last = NULL;
+#endif
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n"));
+#ifdef WITH_ZLIB
+  if (soap->mode & SOAP_ENC_ZLIB)
+  { soap->mode &= ~SOAP_ENC_ZLIB;
+    memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
+    soap->bufidx = (char*)soap->d_stream.next_in - soap->z_buf;
+    soap->buflen = soap->z_buflen;
+    soap->zlib_state = SOAP_ZLIB_NONE;
+    if (inflateEnd(&soap->d_stream) != Z_OK)
+      return soap->error = SOAP_ZLIB_ERROR;
+#ifdef WITH_GZIP
+    if (soap->zlib_in == SOAP_ZLIB_GZIP)
+    { soap_wchar c;
+      short i;
+      for (i = 0; i < 8; i++)
+      { if ((int)(c = soap_getchar(soap)) == EOF)
+          return soap->error = SOAP_EOF;
+        soap->z_buf[i] = (char)c;
+      }
+      if (soap->z_crc != ((uLong)(unsigned char)soap->z_buf[0] | ((uLong)(unsigned char)soap->z_buf[1] << 8) | ((uLong)(unsigned char)soap->z_buf[2] << 16) | ((uLong)(unsigned char)soap->z_buf[3] << 24)))
+      { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc));
+        return soap->error = SOAP_ZLIB_ERROR;
+      }
+      if (soap->d_stream.total_out != ((uLong)(unsigned char)soap->z_buf[4] | ((uLong)(unsigned char)soap->z_buf[5] << 8) | ((uLong)(unsigned char)soap->z_buf[6] << 16) | ((uLong)(unsigned char)soap->z_buf[7] << 24)))
+      { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n"));
+        return soap->error = SOAP_ZLIB_ERROR;
+      }
+    }
+#endif
+  }
+#endif
+  if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
+    while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */
+      ;
+  if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap)))
+    return soap->error;
+  return soap_resolve(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_free(struct soap *soap)
+{ register struct soap_nlist *np;
+  register struct soap_attribute *tp;
+  register struct Namespace *ns;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n"));
+  while (soap->nlist)
+  { np = soap->nlist->next;
+    if (soap->nlist->ns)
+      SOAP_FREE(soap->nlist->ns);
+    SOAP_FREE(soap->nlist);
+    soap->nlist = np;
+  }
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n"));
+  while (soap->blist)
+    soap_end_block(soap);
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attributes\n"));
+  while (soap->attributes)
+  { tp = soap->attributes->next;
+    if (soap->attributes->value)
+      SOAP_FREE(soap->attributes->value);
+    SOAP_FREE(soap->attributes);
+    soap->attributes = tp;
+  }
+#ifdef WITH_FAST
+  if (soap->labbuf)
+    SOAP_FREE(soap->labbuf);
+  soap->labbuf = NULL;
+  soap->lablen = 0;
+  soap->labidx = 0;
+#endif
+  soap_free_pht(soap);
+  soap_free_iht(soap);
+  ns = soap->local_namespaces;
+  if (ns)
+  { for (; ns->id; ns++)
+    { if (ns->out)
+      { SOAP_FREE(ns->out);
+	if (soap->encodingStyle == ns->out)
+          soap->encodingStyle = SOAP_STR_EOS;
+        ns->out = NULL;
+      }
+      if (soap->encodingStyle == ns->ns)
+        soap->encodingStyle = SOAP_STR_EOS;
+    }
+    SOAP_FREE(soap->local_namespaces);
+    soap->local_namespaces = NULL;
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifdef SOAP_DEBUG
+static void
+soap_init_logs(struct soap *soap)
+{ int i;
+  for (i = 0; i < SOAP_MAXLOGS; i++)
+  { soap->logfile[i] = NULL;
+    soap->fdebug[i] = NULL;
+  }
+}
+#endif
+
+/******************************************************************************/
+#if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_open_logfile(struct soap *soap, int i)
+{ if (soap->logfile[i])
+    soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a");
+}
+#endif
+
+/******************************************************************************/
+#ifdef SOAP_DEBUG
+static void
+soap_close_logfile(struct soap *soap, int i)
+{ if (soap->fdebug[i])
+  { fclose(soap->fdebug[i]);
+    soap->fdebug[i] = NULL;
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifdef SOAP_DEBUG
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_close_logfiles(struct soap *soap)
+{ int i;
+  for (i = 0; i < SOAP_MAXLOGS; i++)
+    soap_close_logfile(soap, i);
+}
+#endif
+
+/******************************************************************************/
+#ifdef SOAP_DEBUG
+static void
+soap_set_logfile(struct soap *soap, int i, const char *logfile)
+{ char *s = NULL;
+  soap_close_logfile(soap, i);
+  if (soap->logfile[i])
+    SOAP_FREE((void*)soap->logfile[i]);
+  if (logfile)
+    if ((s = (char*)SOAP_MALLOC(strlen(logfile) + 1)))
+      strcpy(s, logfile);
+  soap->logfile[i] = s;
+}
+#endif
+
+/******************************************************************************/
+#ifdef SOAP_DEBUG
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_recv_logfile(struct soap *soap, const char *logfile)
+{ soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
+}
+#endif
+
+/******************************************************************************/
+#ifdef SOAP_DEBUG
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_sent_logfile(struct soap *soap, const char *logfile)
+{ soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
+}
+#endif
+
+/******************************************************************************/
+#ifdef SOAP_DEBUG
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_test_logfile(struct soap *soap, const char *logfile)
+{ soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+struct soap*
+SOAP_FMAC2
+soap_copy(struct soap *soap)
+{ return soap_copy_context((struct soap*)SOAP_MALLOC(sizeof(struct soap)), soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+struct soap*
+SOAP_FMAC2
+soap_copy_context(struct soap *copy, struct soap *soap)
+{ if (copy)
+  { register struct soap_plugin *p;
+    memcpy(copy, soap, sizeof(struct soap));
+    copy->copy = 1;
+    copy->user = NULL;
+    copy->userid = NULL;
+    copy->passwd = NULL;
+    copy->nlist = NULL;
+    copy->blist = NULL;
+    copy->clist = NULL;
+    copy->alist = NULL;
+    copy->attributes = NULL;
+    copy->local_namespaces = NULL;
+    soap_set_local_namespaces(copy);
+    soap_init_iht(copy);
+    soap_init_pht(copy);
+    copy->header = NULL;
+    copy->fault = NULL;
+    copy->action = NULL;
+    *copy->host = '\0';
+#ifndef WITH_LEAN
+#ifdef WITH_COOKIES
+    copy->cookies = soap_copy_cookies(soap);
+#else
+    copy->cookies = NULL;
+#endif
+#endif
+#ifdef SOAP_DEBUG
+    soap_init_logs(copy);
+    soap_set_recv_logfile(copy, "RECV.log");
+    soap_set_sent_logfile(copy, "SENT.log");
+    soap_set_test_logfile(copy, "TEST.log");
+#endif
+    copy->plugins = NULL;
+    for (p = soap->plugins; p; p = p->next)
+    { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(sizeof(struct soap_plugin));
+      if (!q)
+        return NULL;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id));
+      *q = *p;
+      if (p->fcopy && (soap->error = p->fcopy(soap, q, p)))
+      { SOAP_FREE(q);
+        return NULL;
+      }
+      q->next = copy->plugins;
+      copy->plugins = q;
+    }
+  }
+  else
+    soap->error = SOAP_EOM;
+  return copy;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_init(struct soap *soap)
+{ soap->version = 0;
+  soap_imode(soap, SOAP_IO_DEFAULT);
+  soap_omode(soap, SOAP_IO_DEFAULT);
+  soap->copy = 0;
+  soap->plugins = NULL;
+  soap->user = NULL;
+  soap->userid = NULL;
+  soap->passwd = NULL;
+  soap->fpost = http_post;
+  soap->fget = http_get;
+  soap->fposthdr = http_post_header;
+  soap->fresponse = http_response;
+  soap->fparse = http_parse;
+  soap->fparsehdr = http_parse_header;
+  soap->fconnect = NULL;
+  soap->fdisconnect = NULL;
+#ifndef MAC_CARBON
+#ifndef WITH_IPV6
+  soap->fresolve = tcp_gethost;
+#else
+  soap->fresolve = NULL;
+#endif
+  soap->faccept = tcp_accept;
+  soap->fopen = tcp_connect;
+  soap->fclose = tcp_disconnect;
+  soap->fclosesocket = tcp_closesocket;
+  soap->fshutdownsocket = tcp_shutdownsocket;
+  soap->fsend = fsend;
+  soap->frecv = frecv;
+  soap->fpoll = soap_poll;
+#else
+  soap->fpoll = NULL;
+#endif
+  soap->fprepareinit = NULL;
+  soap->fpreparesend = NULL;
+  soap->fpreparerecv = NULL;
+  soap->fignore = NULL;
+  soap->fserveloop = NULL;
+  soap->fplugin = fplugin;
+  soap->fdimereadopen = NULL;
+  soap->fdimewriteopen = NULL;
+  soap->fdimereadclose = NULL;
+  soap->fdimewriteclose = NULL;
+  soap->fdimeread = NULL;
+  soap->fdimewrite = NULL;
+  soap->float_format = "%.8g"; /* .8 preserves single FP precision as much as possible, but might not be very efficient */
+  soap->double_format = "%.17lg"; /* .17 preserves double FP precision as much as possible, but might not be very efficient */
+  soap->dime_id_format = "cid:id%d"; /* default DIME id format */
+  soap->http_version = "1.1";
+  soap->actor = NULL;
+  soap->max_keep_alive = SOAP_MAXKEEPALIVE;
+  soap->keep_alive = 0;
+  soap->recv_timeout = 0;
+  soap->send_timeout = 0;
+  soap->connect_timeout = 0;
+  soap->accept_timeout = 0;
+  soap->socket_flags = 0;
+  soap->connect_flags = 0;
+  soap->bind_flags = 0;
+  soap->accept_flags = 0;
+  soap->ip = 0;
+  soap->labbuf = NULL;
+  soap->lablen = 0;
+  soap->labidx = 0;
+  soap->encodingStyle = SOAP_STR_EOS;
+#ifndef WITH_NONAMESPACES
+  soap->namespaces = namespaces;
+#else
+  soap->namespaces = NULL;
+#endif
+  soap->local_namespaces = NULL;
+  soap->nlist = NULL;
+  soap->blist = NULL;
+  soap->clist = NULL;
+  soap->alist = NULL;
+  soap->attributes = NULL;
+  soap->header = NULL;
+  soap->fault = NULL;
+  soap->master = SOAP_INVALID_SOCKET;
+  soap->socket = SOAP_INVALID_SOCKET;
+  soap->os = NULL;
+  soap->is = NULL;
+  soap->dom = NULL;
+  soap->dime.list = NULL;
+  soap->dime.first = NULL;
+  soap->dime.last = NULL;
+  soap->mime.list = NULL;
+  soap->mime.first = NULL;
+  soap->mime.last = NULL;
+  soap->mime.boundary = NULL;
+  soap->mime.start = NULL;
+#ifndef UNDER_CE
+  soap->recvfd = 0;
+  soap->sendfd = 1;
+#else
+  soap->recvfd = stdin;
+  soap->sendfd = stdout;
+#endif 
+  soap->host[0] = '\0';
+  soap->port = 0;
+  soap->action = NULL;
+  soap->proxy_host = NULL;
+  soap->proxy_port = 8080;
+  soap->proxy_userid = NULL;
+  soap->proxy_passwd = NULL;
+  soap->authrealm = NULL;
+  soap->prolog = NULL;
+#ifdef WITH_OPENSSL
+  soap->fsslauth = ssl_auth_init;
+  soap->fsslverify = ssl_verify_callback;
+  soap->bio = NULL;
+  soap->ssl = NULL;
+  soap->ctx = NULL;
+  soap->require_server_auth = 0;
+  soap->require_client_auth = 0;
+  soap->rsa = 0;
+  soap->keyfile = NULL;
+  soap->password = NULL;
+  soap->dhfile = NULL;
+  soap->cafile = NULL;
+  soap->capath = NULL;
+  soap->randfile = NULL;
+  soap->session = NULL;
+#endif
+#ifdef WITH_ZLIB
+  soap->zlib_state = SOAP_ZLIB_NONE;
+  soap->zlib_in = SOAP_ZLIB_NONE;
+  soap->zlib_out = SOAP_ZLIB_NONE;
+  soap->d_stream.zalloc = NULL;
+  soap->d_stream.zfree = NULL;
+  soap->d_stream.opaque = NULL;
+  soap->z_level = 6;
+#endif
+#ifndef WITH_LEAN
+  soap->cookies = NULL;
+  soap->cookie_domain = NULL;
+  soap->cookie_path = NULL;
+  soap->cookie_max = 32;
+#endif
+#ifdef SOAP_DEBUG
+  soap_init_logs(soap);
+  soap_set_recv_logfile(soap, "RECV.log");
+  soap_set_sent_logfile(soap, "SENT.log");
+  soap_set_test_logfile(soap, NULL);
+#endif
+/* WR[ */
+#ifdef WMW_RPM_IO
+  soap->rpmreqid = NULL;
+#endif /* WMW_RPM_IO */
+/* ]WR */
+#ifdef PALM
+  palmNetLibOpen();
+#endif
+  soap_init_iht(soap);
+  soap_init_pht(soap);
+  soap_begin(soap);
+#ifdef SOAP_DEBUG
+  soap_set_test_logfile(soap, "TEST.log");
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_init1(struct soap *soap, int mode)
+{ soap_init2(soap, mode, mode);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_init2(struct soap *soap, int imode, int omode)
+{ soap_init(soap);
+  soap_imode(soap, imode);
+  soap_omode(soap, omode);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_begin(struct soap *soap)
+{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing\n"));
+  if (!soap->keep_alive)
+  { soap->buflen = 0;
+    soap->bufidx = 0;
+  }
+  soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
+  soap->null = 0;
+  soap->position = 0;
+  soap->encoding = 0;
+  soap->mustUnderstand = 0;
+  soap->mode = 0;
+  soap->ns = 0;
+  soap->part = SOAP_BEGIN;
+  soap->alloced = 0;
+  soap->count = 0;
+  soap->length = 0;
+  soap->cdata = 0;
+  soap->error = SOAP_OK;
+  soap->peeked = 0;
+  soap->ahead = 0;
+  soap->idnum = 0;
+  soap->level = 0;
+  soap->endpoint[0] = '\0';
+  soap->dime.chunksize = 0;
+  soap->dime.buflen = 0;
+  soap_free(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_end(struct soap *soap)
+{ register struct soap_clist *cp;
+  soap_free(soap);
+  soap_dealloc(soap, NULL);
+  while (soap->clist)
+  { cp = soap->clist->next;
+    SOAP_FREE(soap->clist);
+    soap->clist = cp;
+  }
+  soap_closesock(soap);
+#ifdef SOAP_DEBUG
+  soap_close_logfiles(soap);
+#endif
+#ifdef PALM
+  palmNetLibClose();
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_set_namespaces(struct soap *soap, struct Namespace *p)
+{ struct Namespace *ns = soap->local_namespaces;
+  struct soap_nlist *np, *nq, *nr;
+  unsigned int level = soap->level;
+  soap->namespaces = p;
+  soap->local_namespaces = NULL;
+  soap_set_local_namespaces(soap);
+  /* reverse the list */
+  np = soap->nlist;
+  soap->nlist = NULL;
+  if (np)
+  { nq = np->next;
+    np->next = NULL;
+    while (nq)
+    { nr = nq->next;
+      nq->next = np;
+      np = nq;
+      nq = nr;
+    }
+  }
+  while (np)
+  { soap->level = np->level; /* preserve element nesting level */
+    if (np->ns)
+    { if (soap_push_namespace(soap, np->id, np->ns))
+        return soap->error;
+    }
+    else if (np->index >= 0 && ns)
+    { if (ns[np->index].out)
+      { if (soap_push_namespace(soap, np->id, ns[np->index].out))
+          return soap->error;
+      }
+      else if (soap_push_namespace(soap, np->id, ns[np->index].ns))
+        return soap->error;
+    }
+    if (np->ns)
+      SOAP_FREE(np->ns);
+    nq = np;
+    np = np->next;
+    SOAP_FREE(nq);
+  }
+  if (ns)
+  { int i;
+    for (i = 0; ns[i].id; i++)
+    { if (ns[i].out)
+      { SOAP_FREE(ns[i].out);
+        ns[i].out = NULL;
+      }
+    }
+    SOAP_FREE(ns);
+  }
+  soap->level = level; /* restore level */
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static void
+soap_set_local_namespaces(struct soap *soap)
+{ if (soap->namespaces && !soap->local_namespaces)
+  { register const struct Namespace *ns1;
+    register struct Namespace *ns2;
+    register size_t n = 1;
+    for (ns1 = soap->namespaces; ns1->id; ns1++)
+      n++;
+    if (n > 3)
+    { n *= sizeof(struct Namespace);
+      ns2 = (struct Namespace*)SOAP_MALLOC(n);
+      if (ns2)
+      { memcpy(ns2, soap->namespaces, n);
+        ns2[0].id = "SOAP-ENV";
+        ns2[1].id = "SOAP-ENC";
+        ns2[2].id = "xsi";
+        if (ns2[0].ns)
+        { if (!strcmp(ns2[0].ns, soap_env1))
+            soap->version = 1;
+          else
+            soap->version = 2;
+        }
+        soap->local_namespaces = ns2;
+      }
+    }
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element(struct soap *soap, const char *tag, int id, const char *type)
+{ struct Namespace *ns = soap->local_namespaces;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:""));
+/**/
+#ifdef WITH_DOM
+  if (soap->mode & SOAP_XML_DOM)
+  { register struct soap_dom_element *p, *e = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
+    e->next = NULL;
+    e->prnt = soap->dom;
+    e->nstr = NULL;
+    e->name = soap_strdup(soap, tag); /* check EOM? */
+    e->data = NULL;
+    e->type = 0;
+    e->node = NULL;
+    e->elts = NULL;
+    e->atts = NULL;
+    if (soap->dom)
+    { p = soap->dom->elts;
+      if (p)
+      { while (p->next)
+          p = p->next;
+        p->next = e;
+      }
+      else
+        soap->dom->elts = e;
+    }
+    soap->dom = e;
+  }
+  else
+#endif
+{
+  soap->level++;
+  if (!soap->ns && !(soap->mode & SOAP_XML_CANONICAL))
+    if (soap_send(soap, soap->prolog ? soap->prolog : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"))
+      return soap->error;
+  if (soap_send_raw(soap, "<", 1)
+   || soap_send(soap, tag))
+    return soap->error;
+}
+/**/
+  if (!soap->ns)
+  { for (ns = soap->local_namespaces; ns && ns->id; ns++)
+    { if (*ns->id && (ns->out || ns->ns))
+      { sprintf(soap->tmpbuf, "xmlns:%s", ns->id);
+        if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns))
+          return soap->error;
+      }
+    }   
+    soap->ns = 1;
+  }
+  if (id > 0)
+  { sprintf(soap->tmpbuf, "_%d", id);
+    if (soap_attribute(soap, "id", soap->tmpbuf))
+      return soap->error;
+  }
+  if (type && *type)
+  { if (soap_attribute(soap, "xsi:type", type))
+      return soap->error;
+  }
+  if (soap->null && soap->position > 0)
+  { int i;
+    sprintf(soap->tmpbuf, "[%d", soap->positions[0]);
+    for (i = 1; i < soap->position; i++)
+      sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]);
+    strcat(soap->tmpbuf, "]");
+    if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf))
+      return soap->error;
+  }
+  if (soap->mustUnderstand)
+  { if (soap->actor && *soap->actor)
+    { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor))
+        return soap->error;
+    }
+    if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1"))
+      return soap->error;
+    soap->mustUnderstand = 0;
+  }
+  if (soap->encoding)
+  { if (soap->encodingStyle && soap->local_namespaces)
+    { if (!*soap->encodingStyle)
+      { if (soap->local_namespaces[1].out)
+          soap->encodingStyle = soap->local_namespaces[1].out;
+        else
+          soap->encodingStyle = soap->local_namespaces[1].ns;
+      }
+      if (soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
+        return soap->error;
+    }
+    soap->encoding = 0;
+  }
+  soap->null = 0;
+  soap->position = 0;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type)
+{ if (*tag == '-')
+    return SOAP_OK;
+  if (soap_element(soap, tag, id, type))
+    return soap->error;
+  return soap_element_start_end_out(soap, NULL);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+#ifndef HAVE_STRRCHR
+SOAP_FMAC1
+char*
+SOAP_FMAC2
+soap_strrchr(const char *s, int t)
+{ register char *r = NULL;
+  while (*s)
+    if (*s++ == t)
+      r = (char*)s - 1;
+  return r;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+#ifndef HAVE_STRTOL
+SOAP_FMAC1
+long
+SOAP_FMAC2
+soap_strtol(const char *s, char **t, int b)
+{ register long n = 0;
+  register int c;
+  while (*s > 0 && *s <= 32)
+    s++;
+  if (b == 10)
+  { short neg = 0;
+    if (*s == '-')
+    { s++;
+      neg = 1;
+    }
+    else if (*s == '+')
+      s++;
+    while ((c = *s) && c >= '0' && c <= '9')
+    { if (n > 214748364)
+        break;
+      n *= 10;
+      n += c - '0';
+      s++;
+    }
+    if (neg)
+      n = -n;
+  }
+  else /* b == 16 and value is always positive */
+  { while ((c = *s))
+    { if (c >= '0' && c <= '9')
+        c -= '0';
+      else if (c >= 'A' && c <= 'F')
+        c -= 'A' - 10;
+      else if (c >= 'a' && c <= 'f')
+        c -= 'a' - 10;
+      if (n > 0x07FFFFFF)
+        break;
+      n <<= 4;
+      n += c;
+      s++;
+    }
+  }
+  if (t)
+    *t = (char*)s;
+  return n;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+#ifndef HAVE_STRTOUL
+SOAP_FMAC1
+unsigned long
+SOAP_FMAC2
+soap_strtoul(const char *s, char **t, int b)
+{ unsigned long n = 0;
+  register int c;
+  while (*s > 0 && *s <= 32)
+    s++;
+  if (b == 10)
+  { if (*s == '+')
+      s++;
+    while ((c = *s) && c >= '0' && c <= '9')
+    { if (n > 429496729)
+        break;
+      n *= 10;
+      n += c - '0';
+      s++;
+    }
+  }
+  else /* b == 16 */
+  { while ((c = *s))
+    { if (c >= '0' && c <= '9')
+        c -= '0';
+      else if (c >= 'A' && c <= 'F')
+        c -= 'A' - 10;
+      else if (c >= 'a' && c <= 'f')
+        c -= 'a' - 10;
+      if (n > 0x0FFFFFFF)
+        break;
+      n <<= 4;
+      n += c;
+      s++;
+    }
+  }
+  if (t)
+    *t = (char*)s;
+  return n;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset)
+{ if (soap_element(soap, tag, id, "SOAP-ENC:Array"))
+    return soap->error;
+  if (soap->version == 2)
+  { const char *s;
+    s = soap_strrchr(type, '[');
+    if ((size_t)(s - type) < sizeof(soap->tmpbuf))
+    { strncpy(soap->tmpbuf, type, s - type);
+      soap->tmpbuf[s - type] = '\0';
+      if (type && *type && (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf)))
+        return soap->error;
+      if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1)))
+        return soap->error;
+    }
+  }
+  else
+  { if (offset && (soap_attribute(soap, "SOAP-ENC:offset", offset)))
+      return soap->error;
+    if (type && *type && (soap_attribute(soap, "SOAP-ENC:arrayType", type)))
+      return soap->error;
+  }
+  return soap_element_start_end_out(soap, NULL);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_start_end_out(struct soap *soap, const char *tag)
+{ register struct soap_attribute *tp;
+/**/
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+  { for (tp = soap->attributes; tp; tp = tp->next)
+    { if (tp->visible)
+      { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
+	a->next = soap->dom->atts;
+        a->nstr = NULL;
+        a->name = soap_strdup(soap, tp->name); /* check EOM */
+        a->data = soap_strdup(soap, tp->value); /* check EOM */
+        a->wide = NULL;
+	soap->dom->atts = a;
+        tp->visible = 0;
+      }
+    }
+    return SOAP_OK;
+  }
+#endif
+/**/
+  for (tp = soap->attributes; tp; tp = tp->next)
+  { if (tp->visible)
+    { if (soap_send2(soap, " ", tp->name))
+        return soap->error;
+      if (tp->visible == 2 && tp->value)
+        if (soap_send_raw(soap, "=\"", 2)
+	 || soap_string_out(soap, tp->value, 1)
+	 || soap_send_raw(soap, "\"", 1))
+          return soap->error;
+      tp->visible = 0;
+    }
+  }
+  if (tag)
+  { soap->level--;
+#ifndef WITH_LEAN
+    if (soap->mode & SOAP_XML_CANONICAL)
+    { if (soap_send_raw(soap, ">", 1)
+       || soap_element_end_out(soap, tag))
+        return soap->error;
+      return SOAP_OK;
+    }
+#endif
+    return soap_send_raw(soap, "/>", 2);
+  }
+  return soap_send_raw(soap, ">", 1);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_end_out(struct soap *soap, const char *tag)
+{ if (*tag == '-')
+    return SOAP_OK;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag));
+/**/
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+  { if (soap->dom->prnt)
+      soap->dom = soap->dom->prnt;
+    return SOAP_OK;
+  }
+#endif
+/**/
+  soap->level--;
+  if (soap_send_raw(soap, "</", 2)
+   || soap_send(soap, tag))
+    return soap->error;
+  return soap_send_raw(soap, ">", 1);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_ref(struct soap *soap, const char *tag, int id, int href)
+{ register int n = 0;
+  if (soap->version == 2)
+    n = 1;
+  sprintf(soap->href, "#_%d", href);
+  return soap_element_href(soap, tag, id, "href" + n, soap->href + n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val)
+{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val));
+  if (soap_element(soap, tag, id, NULL)
+   || soap_attribute(soap, ref, val)
+   || soap_element_start_end_out(soap, tag))
+    return soap->error;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_null(struct soap *soap, const char *tag, int id, const char *type)
+{ struct soap_attribute *tp;
+  for (tp = soap->attributes; tp; tp = tp->next)
+    if (tp->visible)
+      break;
+  if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL))
+  { if (soap_element(soap, tag, id, type))
+      return soap->error;
+    if (soap->part != SOAP_IN_HEADER && soap->encodingStyle)
+      if (soap_attribute(soap, "xsi:nil", "true"))
+        return soap->error;
+    return soap_element_start_end_out(soap, tag);
+  }
+  soap->null = 1;
+  soap->position = 0;
+  soap->mustUnderstand = 0;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, int n, const char *type, int t) 
+{ struct soap_plist *pp;
+  if (!p || (a && !a->__ptr))
+  { soap_element_null(soap, tag, id, type);
+    return -1;
+  }
+  if (soap->mode & SOAP_XML_TREE)
+    return 0;
+  if (id < 0)
+  { if (a)
+      id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
+    else
+      id = soap_pointer_lookup(soap, p, t, &pp);
+    if (id)
+    { if (soap_is_embedded(soap, pp))
+      { soap_element_ref(soap, tag, 0, id);
+        return -1;
+      }
+      if (soap_is_single(soap, pp))
+        return 0;
+      soap_set_embedded(soap, pp);
+    }
+  }
+  return id;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_result(struct soap *soap, const char *tag)
+{ if (soap->version == 2 && soap->encodingStyle)
+    if (soap_element(soap, "SOAP-RPC:result", 0, NULL)
+     || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc)
+     || soap_element_start_end_out(soap, NULL)
+     || soap_string_out(soap, tag, 0)
+     || soap_element_end_out(soap, "SOAP-RPC:result"))
+      return soap->error;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_attribute(struct soap *soap, const char *name, const char *value)
+{ 
+/**/
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+  { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
+    a->next = soap->dom->atts;
+    a->nstr = NULL;
+    a->name = soap_strdup(soap, name); /* check EOM */
+    a->data = soap_strdup(soap, value); /* check EOM */
+    a->wide = NULL;
+    soap->dom->atts = a;
+    return SOAP_OK;
+  }
+#endif
+/**/
+#ifndef WITH_LEAN
+  if (soap->mode & SOAP_XML_CANONICAL)
+  { if (soap_set_attr(soap, name, value))
+      return soap->error;
+  }
+  else
+#endif
+  { if (soap_send2(soap, " ", name))
+      return soap->error;
+    if (value)
+      if (soap_send_raw(soap, "=\"", 2)
+       || soap_string_out(soap, value, 1)
+       || soap_send_raw(soap, "\"", 1))
+        return soap->error;
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_begin_in(struct soap *soap, const char *tag, int nillable)
+{ if (!soap_peek_element(soap))
+  { if (soap->other)
+      return soap->error = SOAP_TAG_MISMATCH;
+    if (tag && *tag == '-')
+      return SOAP_OK;
+    if (!(soap->error = soap_match_tag(soap, soap->tag, tag)))
+    { soap->peeked = 0;
+      if (soap->body)
+        soap->level++;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"" ));
+      if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT))
+        return soap->error = SOAP_NULL;
+    }
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_end_in(struct soap *soap, const char *tag)  
+{ register soap_wchar c;
+  register char *s;
+  register const char *t;
+  if (tag && *tag == '-')
+    return SOAP_OK;
+  soap->level--;
+  soap_pop_namespace(soap);
+  if (soap->peeked)
+  { if (*soap->tag == '\0')
+    { soap->peeked = 0;
+      if (soap->error == SOAP_NO_TAG || soap->error == SOAP_TAG_END)
+        soap->error = SOAP_OK;
+    }
+    else
+      return soap->error = SOAP_TAG_END;
+  }
+  else
+  { while (((c = soap_get(soap)) != SOAP_TT))
+    { if ((int)c == EOF)
+        return soap->error = SOAP_EOF;
+      if (c == SOAP_LT)
+        return soap->error = SOAP_TAG_END;
+    }
+  }
+  s = soap->tag;
+  do c = soap_get(soap);
+  while (soap_blank(c));
+  do
+  { *s++ = (char)c;
+    c = soap_get(soap);
+  } while (soap_notblank(c));
+  *s = '\0';
+  if ((int)c == EOF)
+    return soap->error = SOAP_EOF;
+  while (soap_blank(c))
+    c = soap_get(soap);
+  if (c != SOAP_GT)
+    return soap->error = SOAP_SYNTAX_ERROR;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:""));
+  if (!tag)
+    return SOAP_OK;
+  if ((s = strchr(soap->tag, ':')))
+    s++;
+  else
+    s = soap->tag;
+  if ((t = strchr(tag, ':')))
+    t++;
+  else
+    t = tag;
+  if (!SOAP_STRCMP(s, t))
+    return SOAP_OK;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n"));
+  return soap->error = SOAP_SYNTAX_ERROR;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char *
+SOAP_FMAC2
+soap_attr_value(struct soap *soap, const char *name, int flag)
+{ register struct soap_attribute *tp;
+  for (tp = soap->attributes; tp; tp = tp->next)
+    if (!soap_match_tag(soap, tp->name, name))
+      break;
+  if (tp && tp->visible == 2)
+  { if (flag == 2 && (soap->mode & SOAP_XML_STRICT))
+      soap->error = SOAP_PROHIBITED;
+    else
+      return tp->value;
+  }
+  else if (flag == 1 && (soap->mode & SOAP_XML_STRICT))
+    soap->error = SOAP_REQUIRED;
+  return NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_set_attr(struct soap *soap, const char *name, const char *value)
+{ register struct soap_attribute *tp;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:""));
+  for (tp = soap->attributes; tp; tp = tp->next)
+    if (!strcmp(tp->name, name))
+      break;
+  if (!tp)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name));
+    if (!(tp = (struct soap_attribute*)SOAP_MALLOC(sizeof(struct soap_attribute) + strlen(name))))
+      return soap->error = SOAP_EOM;
+    tp->ns = NULL;
+#ifndef WITH_LEAN
+    if (soap->mode & SOAP_XML_CANONICAL)
+    { struct soap_attribute **tpp = &soap->attributes;
+      const char *s = strchr(name, ':');
+      if (!strncmp(name, "xmlns", 5))
+      { for (; *tpp; tpp = &(*tpp)->next)
+          if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0)
+            break;
+      }
+      else if (!s)
+      { for (; *tpp; tpp = &(*tpp)->next)
+          if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0))
+            break;
+      }
+      else
+      { int k;
+        for (; *tpp; tpp = &(*tpp)->next)
+	{ if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name])
+	  { if (!tp->ns)
+            { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p(%s)\n", name, (*tpp)->ns, (*tpp)->ns));
+	      tp->ns = (*tpp)->ns;
+	    }
+	  }
+          else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0)))
+            break;
+        }
+      }
+      tp->next = *tpp;
+      *tpp = tp;
+    }
+    else
+#endif
+    { tp->next = soap->attributes;
+      soap->attributes = tp;
+    }
+    strcpy(tp->name, name);
+    tp->value = NULL;
+  }
+  else if (value && tp->value && tp->size <= strlen(value))
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value));
+    SOAP_FREE(tp->value);
+    tp->value = NULL;
+    tp->ns = NULL;
+  }
+  if (value)
+  { if (!tp->value)
+    { tp->size = strlen(value) + 1;
+      if (!(tp->value = (char*)SOAP_MALLOC(tp->size)))
+        return soap->error = SOAP_EOM;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value of %s (%p)\n", tp->name, tp->value));
+    }
+    strcpy(tp->value, value);
+    if (!strncmp(tp->name, "xmlns:", 6))
+      tp->ns = tp->value;
+    tp->visible = 2;
+  }
+  else
+    tp->visible = 1;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_clr_attr(struct soap *soap)
+{ register struct soap_attribute *tp;
+#ifndef WITH_LEAN
+  if (soap->mode & SOAP_XML_CANONICAL)
+  { while (soap->attributes)
+    { tp = soap->attributes->next;
+      SOAP_FREE(soap->attributes->value);
+      SOAP_FREE(soap->attributes);
+      soap->attributes = tp;
+    }
+  }
+  else
+#endif
+  { for (tp = soap->attributes; tp; tp = tp->next)
+      tp->visible = 0;
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+static int
+soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d)
+{ size_t i;
+  soap_wchar c;
+  for (i = 0; i < n; i++)
+  { c = soap_getutf8(soap);
+    switch (c)
+    {
+    case SOAP_TT:
+      *s++ = '<';
+      soap_unget(soap, '/');
+      break;
+    case SOAP_LT:
+      *s++ = '<';
+      break;
+    case SOAP_GT:
+      if (d == ' ')
+      { soap_unget(soap, c);
+        *s = '\0';
+        return SOAP_OK;
+      }
+      *s++ = '>';
+      break;
+    case SOAP_QT:
+      if (c == d)
+      { *s = '\0';
+        return SOAP_OK;
+      }
+      *s++ = '"';
+      break;
+    case SOAP_AP:
+      if (c == d)
+      { *s = '\0';
+        return SOAP_OK;
+      }
+      *s++ = '\'';
+      break;
+    case '\t':
+    case '\n':
+    case '\r':
+    case ' ':
+    case '/':
+      if (d == ' ')
+      { soap_unget(soap, c);
+        *s = '\0';
+        return SOAP_OK;
+      }
+    default:
+      if ((int)c == EOF)
+        return soap->error = SOAP_EOF;
+      *s++ = (char)c;
+    }
+  }
+  return soap->error = SOAP_EOM;
+}
+#endif
+
+/******************************************************************************/
+#ifdef WITH_FAST
+#ifndef PALM_2
+static int 
+soap_append_lab(struct soap *soap, const char *s, size_t n)
+{ if (soap->labidx + n >= soap->lablen)
+  { register char *t = soap->labbuf;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen));
+    if (soap->lablen == 0)
+      soap->lablen = SOAP_LABLEN;
+    while (soap->labidx + n >= soap->lablen)
+      soap->lablen <<= 1;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen));
+    soap->labbuf = (char*)SOAP_MALLOC(soap->lablen);
+    if (!soap->labbuf)
+    { if (t)
+        free(t);
+      return soap->error = SOAP_EOM;
+    }
+    if (t && soap->labidx)
+    { memcpy(soap->labbuf, t, soap->labidx);
+      free(t);
+    }
+  }
+  if (s)
+  { memcpy(soap->labbuf + soap->labidx, s, n);
+    soap->labidx += n;
+  }
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_peek_element(struct soap *soap)
+{ register struct soap_attribute *tp;
+  const char *t;
+  register char *s;
+  register soap_wchar c;
+  register int i;
+  if (soap->error == SOAP_NO_TAG || soap->error == SOAP_TAG_END || soap->error == SOAP_TAG_MISMATCH)
+    soap->error = SOAP_OK;	/* retry */
+  if (soap->peeked)
+  { if (*soap->tag == '\0')
+      return soap->error = SOAP_NO_TAG;
+    return SOAP_OK;
+  }
+  soap->peeked = 1;
+  for (;;)
+  { while (((c = soap_getutf8(soap)) != SOAP_LT) && c != SOAP_TT)
+    { if ((int)c == EOF)
+        return soap->error = SOAP_EOF;
+    }
+    if (c == SOAP_TT)
+    { *soap->tag = '\0';
+      return soap->error = SOAP_NO_TAG; /* ending tag found */
+    }
+    s = soap->tag;
+    do c = soap_get(soap);
+    while (soap_blank(c));
+    i = sizeof(soap->tag);
+    while (c != '/' && soap_notblank(c))
+    { if (--i > 0)
+        *s++ = (char)c;
+      c = soap_get(soap);
+    }
+    while (soap_blank(c))
+      c = soap_get(soap);
+    *s = '\0';
+    if (*soap->tag != '?')
+      break;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <%s?>\n", soap->tag));
+    while ((int)c != EOF && c != SOAP_GT && c != '?')
+    { s = soap->tmpbuf;
+      i = sizeof(soap->tmpbuf) - 2;
+      while (c != '=' && c != SOAP_GT && c != '?' && soap_notblank(c))
+      { if (--i > 0)
+          *s++ = (char)c;
+        c = soap_get(soap);
+      }
+      while (soap_blank(c))
+        c = soap_get(soap);
+      if (c == '=')
+      { *s++ = '=';
+	do c = soap_get(soap);
+        while (soap_blank(c));
+        if (c != SOAP_QT && c != SOAP_AP)
+        { soap_unget(soap, c);
+          c = ' '; /* blank delimiter */
+        }
+        if (soap_getattrval(soap, s, i, c) == SOAP_EOM)
+	  while (soap_getattrval(soap, soap->tmpbuf, sizeof(soap->tmpbuf), c) == SOAP_EOM)
+	    ;
+        else if (!strcmp(soap->tag, "?xml") && (!soap_tag_cmp(soap->tmpbuf, "encoding=iso-8859-1") || !soap_tag_cmp(soap->tmpbuf, "encoding=latin1")))
+        { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML latin1 encoding\n"));
+          soap->mode |= SOAP_ENC_LATIN;
+        }
+      }
+      do c = soap_get(soap);
+      while (soap_blank(c));
+    }
+  }
+  soap->id[0] = '\0';
+  soap->href[0] = '\0';
+  soap->type[0] = '\0';
+  soap->arrayType[0] = '\0';
+  soap->arraySize[0] = '\0';
+  soap->arrayOffset[0] = '\0';
+  soap->other = 0;
+  soap->root = -1;
+  soap->position = 0;
+  soap->null = 0;
+  soap->mustUnderstand = 0;
+  soap_clr_attr(soap);
+  while ((int)c != EOF && c != SOAP_GT && c != '/')
+  { s = soap->tmpbuf;
+    i = sizeof(soap->tmpbuf);
+    while (c != '=' && c != '/' && soap_notblank(c))
+    { if (--i > 0)
+        *s++ = (char)c;
+      c = soap_get(soap);
+    }
+    *s = '\0';
+    if (i == sizeof(soap->tmpbuf))
+      return soap->error = SOAP_SYNTAX_ERROR;
+    if (!strncmp(soap->tmpbuf, "xmlns:", 6))
+    { soap->tmpbuf[5] = '\0';
+      t = soap->tmpbuf + 6;
+    }
+    else if (!strcmp(soap->tmpbuf, "xmlns"))
+      t = SOAP_STR_EOS;
+    else
+      t = NULL;
+    for (tp = soap->attributes; tp; tp = tp->next)
+      if (!SOAP_STRCMP(tp->name, soap->tmpbuf))
+        break;
+    if (!tp)
+    { tp = (struct soap_attribute*)SOAP_MALLOC(sizeof(struct soap_attribute) + strlen(soap->tmpbuf));
+      if (!tp)
+        return soap->error = SOAP_EOM;
+      strcpy(tp->name, soap->tmpbuf);
+      tp->value = NULL;
+      tp->size = 0;
+      tp->next = soap->attributes;
+      soap->attributes = tp;
+    }
+    while (soap_blank(c))
+      c = soap_get(soap);
+    if (c == '=')
+    { do c = soap_get(soap);
+      while (soap_blank(c));
+      if (c != SOAP_QT && c != SOAP_AP)
+      { soap_unget(soap, c);
+        c = ' '; /* blank delimiter */
+      }
+      if (soap_getattrval(soap, tp->value, tp->size, c))
+      {
+#ifdef WITH_FAST
+        if (soap->error != SOAP_EOM)
+          return soap->error;
+        soap->error = SOAP_OK;
+	soap->labidx = 0;
+	if (soap_append_lab(soap, tp->value, tp->size))
+	  return soap->error;
+	SOAP_FREE(tp->value);
+	for (;;)
+	{ if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c))
+	  { if (soap->error != SOAP_EOM)
+	      return soap->error;
+            soap->error = SOAP_OK;
+	    soap->labidx = soap->lablen;
+	    if (soap_append_lab(soap, NULL, 0))
+	      return soap->error;
+	  }
+	  else
+	    break;
+	}
+        tp->size = soap->lablen;
+	if (!(tp->value = (char*)SOAP_MALLOC(tp->size)))
+	  return soap->error = SOAP_EOM;
+        memcpy(tp->value, soap->labbuf, soap->lablen);
+#else
+	size_t n;
+        if (soap->error != SOAP_EOM)
+          return soap->error;
+        soap->error = SOAP_OK;
+        if (soap_new_block(soap))
+          return soap->error;
+        for (;;)
+        { if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN)))
+            return soap->error;
+          if (soap_getattrval(soap, s, SOAP_BLKLEN, c))
+          { if (soap->error != SOAP_EOM)
+              return soap->error;
+            soap->error = SOAP_OK;
+          }
+          else
+            break;
+        }
+	n = tp->size + soap->blist->size;
+        if (!(s = (char*)SOAP_MALLOC(n)))
+          return soap->error = SOAP_EOM;
+        if (tp->value)
+        { memcpy(s, tp->value, tp->size);
+          SOAP_FREE(tp->value);
+        }
+        soap_save_block(soap, s + tp->size, 0);
+        tp->value = s;
+        tp->size = n;
+#endif
+      }
+      do c = soap_get(soap);
+      while (soap_blank(c));
+      tp->visible = 2; /* seen this attribute w/ value */
+    }
+    else
+      tp->visible = 1; /* seen this attribute w/o value */
+    if (t && tp->value)
+    { if (soap_push_namespace(soap, t, tp->value))
+        return soap->error;
+      tp->visible = 0;
+    }
+  }
+  if ((int)c == EOF)
+    return soap->error = SOAP_EOF;
+  for (tp = soap->attributes; tp; tp = tp->next)
+  { if (tp->visible && tp->value)
+    { if (!strcmp(tp->name, "id"))
+      { *soap->id = '#';
+        strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2);
+        soap->id[sizeof(soap->id)-1] = '\0';
+      }
+      else if (!strcmp(tp->name, "href"))
+      { strncpy(soap->href, tp->value, sizeof(soap->href) - 1);
+        soap->href[sizeof(soap->href)-1] = '\0';
+      }
+      else if ((soap->version == 2 || (soap->mode & SOAP_XML_GRAPH)) && !strcmp(tp->name, "ref"))
+      { *soap->href = '#';
+        strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2);
+        soap->href[sizeof(soap->href)-1] = '\0';
+      }
+      else if (!soap_match_tag(soap, tp->name, "xsi:type"))
+      { strncpy(soap->type, tp->value, sizeof(soap->type) - 1);
+        soap->type[sizeof(soap->type)-1] = '\0';
+      }
+      else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType"))
+      { s = soap_strrchr(tp->value, '[');
+        if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType))
+        { strncpy(soap->arrayType, tp->value, s - tp->value);
+          soap->arrayType[s - tp->value] = '\0';
+          strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1);
+        }
+        else
+          strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
+        soap->arraySize[sizeof(soap->arrayType)-1] = '\0';
+        soap->arrayType[sizeof(soap->arrayType)-1] = '\0';
+      }
+      else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:itemType"))
+        strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
+      else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize"))
+        strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1);
+      else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:offset"))
+        strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset));
+      else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:position"))
+        soap->position = soap_getposition(tp->value, soap->positions);
+      else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:root"))
+        soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true")));
+      else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor")
+            || !soap_match_tag(soap, tp->name, "SOAP-ENV:role"))
+      { if ((!soap->actor || strcmp(soap->actor, tp->value))
+         && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next")
+         && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next"))
+          soap->other = 1;
+      }
+      else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
+            && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
+        soap->mustUnderstand = 1;
+      else if ((!soap_match_tag(soap, tp->name, "xsi:null")
+             || !soap_match_tag(soap, tp->name, "xsi:nil"))
+            && (!strcmp(tp->value, "1")
+             || !strcmp(tp->value, "true")))
+        soap->null = 1;
+    }
+  }
+  if (!(soap->body = (c != '/')))
+    do c = soap_get(soap);
+    while (soap_blank(c));
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_retry(struct soap *soap)
+{ soap->peeked = 1;
+  soap->error = SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_revert(struct soap *soap)
+{ if (!soap->peeked)
+  { soap->peeked = 1;
+    if (soap->body)
+      soap->level--;
+  }
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level));
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_string_out(struct soap *soap, const char *s, int flag)
+{ register const char *t;
+  register soap_wchar c;
+  register soap_wchar mask = 0x80000000;
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+  { soap->dom->data = soap_strdup(soap, s); /* check EOM */
+    return SOAP_OK;
+  }
+#endif
+  if (soap->mode & SOAP_C_UTFSTRING)
+    mask = 0;
+  t = s;
+  while ((c = *t++))
+  { switch (c)
+    { 
+    case 9:
+      if (flag)
+      { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#x9;", 5))
+	  return soap->error;
+        s = t;
+      }
+      break;
+    case 10:
+      if (flag || !(soap->mode & SOAP_XML_CANONICAL))
+      { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xA;", 5))
+	  return soap->error;
+        s = t;
+      }
+      break;
+    case 13:
+      if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xD;", 5))
+        return soap->error;
+      s = t;
+      break;
+    case '&':
+      if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&amp;", 5))
+        return soap->error;
+      s = t;
+      break;
+    case '<':
+      if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&lt;", 4))
+        return soap->error;
+      s = t;
+      break;
+    case '>':
+      if (!flag)
+      { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&gt;", 4))
+	  return soap->error;
+        s = t;
+      }
+      break;
+    case '"':
+      if (flag)
+      { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&quot;", 6))
+	  return soap->error;
+        s = t;
+      }
+      break;
+    default:
+#ifdef HAVE_MBTOWC
+      if (soap->mode & SOAP_C_MBSTRING)
+      { wchar_t wc;
+        register int m = mbtowc(&wc, t - 1, MB_CUR_MAX);
+        if (m > 0 && wc != c)
+        { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc))
+            return soap->error;
+	  s = t + m - 1;
+	  continue;
+        }
+      }
+#endif
+      if (c & mask)
+      { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c))
+          return soap->error;
+        s = t;
+      }
+    }
+  }
+  return soap_send_raw(soap, s, t - s - 1);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
+{ register char *s;
+  char *t = NULL;
+  register size_t i;
+  register long l = 0;
+  register int n = 0;
+  register int m = 0;
+  register soap_wchar c;
+#ifdef HAVE_WCTOMB
+  char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8];
+#else
+  char buf[8];
+#endif
+#ifdef WITH_CDATA
+  if (!flag)
+  { register int state = 0;
+#ifdef WITH_FAST
+    soap->labidx = 0;			/* use look-aside buffer */
+#else
+    if (soap_new_block(soap))
+      return NULL;
+#endif
+    for (;;)
+    { 
+#ifdef WITH_FAST
+      register size_t k;
+      if (soap_append_lab(soap, NULL, 0))	/* allocate more space in look-aside buffer if necessary */
+        return NULL;
+      s = soap->labbuf + soap->labidx;	/* space to populate */
+      k = soap->lablen - soap->labidx;	/* number of bytes available */
+      soap->labidx = soap->lablen;	/* claim this space */
+#else
+      register size_t k = SOAP_BLKLEN;
+      if (!(s = (char*)soap_push_block(soap, k)))
+        return NULL;
+#endif
+      for (i = 0; i < k; i++)
+      { if (m > 0)
+        { *s++ = *t++;	/* copy multibyte characters */
+	  m--;
+          continue;
+        }
+        c = soap_getchar(soap);
+	if ((int)c == EOF)
+          goto end;
+        if (c >= 0x80 && !(soap->mode & SOAP_ENC_LATIN))
+        { soap_unget(soap, c);
+	  c = soap_getutf8(soap);
+	  if (soap->mode & SOAP_C_UTFSTRING)
+          { if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
+            { c &= 0x7FFFFFFF;
+              t = buf;
+              if (c < 0x0800)
+                *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
+              else
+              { if (c < 0x010000)
+                  *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
+                else
+                { if (c < 0x200000)
+                    *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
+                  else
+                  { if (c < 0x04000000)
+                      *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
+                    else
+                    { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
+                      *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
+                    }
+                    *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
+                  }     
+                  *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
+                }
+                *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
+              }
+              *t++ = (char)(0x80 | (c & 0x3F));
+	      m = (int)(t - buf) - 1;
+              t = buf;
+              *s++ = *t++;
+              continue;
+	    }
+          }
+        }
+	switch (state)
+        { case 1:
+            if (c == ']')
+	      state = 4;
+	    *s++ = c;
+	    continue;
+	  case 2:
+	    if (c == '-')
+              state = 6;
+	    *s++ = c;
+	    continue;
+	  case 3:
+	    if (c == '?')
+	      state = 8;
+	    *s++ = c;
+	    continue;
+          /* CDATA */
+	  case 4:
+	    if (c == ']')
+              state = 5;
+	    else
+	      state = 1;
+	    *s++ = c;
+	    continue;
+	  case 5:
+	    if (c == '>')
+	      state = 0;
+	    else
+	      state = 1;
+	    *s++ = c;
+	    continue;
+          /* comment */
+          case 6:
+            if (c == '-')
+	      state = 7;
+	    else
+	      state = 2;
+	    *s++ = c;
+	    continue;
+          case 7:
+            if (c == '>')
+	      state = 0;
+	    else
+	      state = 2;
+	    *s++ = c;
+	    continue;
+          /* PI */
+	  case 8:
+            if (c == '>')
+	      state = 0;
+	    else
+	      state = 3;
+	    *s++ = c;
+	    continue;
+        }
+        switch (c)
+        {
+        case '/':
+          if (n > 0)
+          { c = soap_getchar(soap);
+            if (c == '>')
+              n--;
+            soap_unget(soap, c);
+          }
+          *s++ = '/';
+          break;
+        case '<':
+	  c = soap_getchar(soap);
+	  if (c == '/')
+	  { if (n == 0)
+	    { c = SOAP_TT;
+	      goto end;
+	    }
+	    n--;
+	  }
+	  else if (c == '!')
+	  { c = soap_getchar(soap);
+	    if (c == '[')
+            { do c = soap_getchar(soap);
+              while ((int)c != EOF && c != '[');
+              if ((int)c == EOF)
+                 goto end;
+	      t = (char*)"![CDATA[";
+	      m = 8;
+	      state = 1;
+	    }
+            else if (c == '-')
+	    { if ((c = soap_getchar(soap)) == '-')
+	        state = 2;
+	      t = (char*)"!-";
+	      m = 2;
+	      soap_unget(soap, c);
+	    }
+	    else
+	    { t = (char*)"!";
+	      m = 1;
+	      soap_unget(soap, c);
+	    }
+	    *s++ = '<';
+	    break;
+	  }
+	  else if (c == '?')
+	    state = 3;
+	  else
+	    n++;
+          soap_unget(soap, c);
+          *s++ = '<';
+          break;
+        case '>':
+          *s++ = '>';
+          break;
+        case '"':
+          *s++ = '"';
+          break;
+        default:
+#ifdef HAVE_WCTOMB
+          if (soap->mode & SOAP_C_MBSTRING)
+          { m = wctomb(buf, c & 0x7FFFFFFF);
+            if (m >= 1)
+            { t = buf;
+              *s++ = *t++;
+              m--;
+            }
+            else
+              *s++ = SOAP_UNKNOWN_CHAR;
+          }
+          else
+#endif
+            *s++ = (char)(c & 0xFF);
+        }
+	l++;
+        if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen)
+        { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
+          soap->error = SOAP_LENGTH;
+          return NULL;
+        }
+      }
+    }
+  }
+#endif
+#ifdef WITH_FAST
+  soap->labidx = 0;			/* use look-aside buffer */
+#else
+  if (soap_new_block(soap))
+    return NULL;
+#endif
+  for (;;)
+  { 
+#ifdef WITH_FAST
+    register size_t k;
+    if (soap_append_lab(soap, NULL, 0))	/* allocate more space in look-aside buffer if necessary */
+      return NULL;
+    s = soap->labbuf + soap->labidx;	/* space to populate */
+    k = soap->lablen - soap->labidx;	/* number of bytes available */
+    soap->labidx = soap->lablen;	/* claim this space */
+#else
+    register size_t k = SOAP_BLKLEN;
+    if (!(s = (char*)soap_push_block(soap, k)))
+      return NULL;
+#endif
+    for (i = 0; i < k; i++)
+    { if (m > 0)
+      { *s++ = *t++;	/* copy multibyte characters */
+        m--;
+        continue;
+      }
+      if (soap->mode & SOAP_C_UTFSTRING)
+      { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
+        { c &= 0x7FFFFFFF;
+          t = buf;
+          if (c < 0x0800)
+            *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
+          else
+          { if (c < 0x010000)
+              *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
+            else
+            { if (c < 0x200000)
+                *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
+              else
+              { if (c < 0x04000000)
+                  *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
+                else
+                { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
+                  *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
+                }
+                *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
+              }     
+              *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
+            }
+            *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
+          }
+          *t++ = (char)(0x80 | (c & 0x3F));
+	  m = (int)(t - buf) - 1;
+          t = buf;
+          *s++ = *t++;
+          continue;
+        }
+      }
+      else
+        c = soap_getutf8(soap);
+      switch (c)
+      {
+      case SOAP_TT:
+        if (n == 0)
+          goto end;
+        n--;
+        *s++ = '<';
+        t = (char*)"/";
+	m = 1;
+        break;
+      case SOAP_LT:
+        n++;
+        *s++ = '<';
+        break;
+      case SOAP_GT:
+        *s++ = '>';
+        break;
+      case SOAP_QT:
+        *s++ = '"';
+        break;
+      case SOAP_AP:
+        *s++ = '\'';
+        break;
+      case '/':
+        if (n > 0)
+        { c = soap_get(soap);
+          if (c == SOAP_GT)
+            n--;
+          soap_unget(soap, c);
+        }
+        *s++ = '/';
+        break;
+      case '<' | 0x80000000:
+        if (flag)
+          *s++ = '<';
+        else
+        { *s++ = '&';
+          t = (char*)"lt;";
+	  m = 3;
+        }
+        break;
+      case '>' | 0x80000000:
+        if (flag)
+          *s++ = '>';
+        else
+        { *s++ = '&';
+          t = (char*)"gt;";
+	  m = 3;
+        }
+        break;
+      case '"' | 0x80000000:
+        if (flag)
+          *s++ = '"';
+        else
+        { *s++ = '&';
+          t = (char*)"quot;";
+	  m = 5;
+        }
+        break;
+      case '\'' | 0x80000000:
+        if (flag)
+          *s++ = '\'';
+        else
+        { *s++ = '&';
+          t = (char*)"apos;";
+	  m = 5;
+        }
+        break;
+      default:
+        if ((int)c == EOF)
+          goto end;
+#ifdef HAVE_WCTOMB
+        if (soap->mode & SOAP_C_MBSTRING)
+        { m = wctomb(buf, c & 0x7FFFFFFF);
+          if (m >= 1)
+          { t = buf;
+            *s++ = *t++;
+            m--;
+          }
+          else
+            *s++ = SOAP_UNKNOWN_CHAR;
+        }
+        else
+#endif
+          *s++ = (char)(c & 0xFF);
+      }
+      l++;
+      if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen)
+      { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
+        soap->error = SOAP_LENGTH;
+        return NULL;
+      }
+    }
+  }
+end:
+  soap_unget(soap, c);
+  *s = '\0';
+#ifdef WITH_FAST
+  t = soap_strdup(soap, soap->labbuf);
+#else
+  soap_size_block(soap, i+1);
+  t = soap_save_block(soap, NULL, 0);
+#endif
+  if ((soap->mode & SOAP_XML_STRICT) && l < minlen)
+  { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
+    soap->error = SOAP_LENGTH;
+    return NULL;
+  }
+  if (flag == 2)
+    if (soap_s2QName(soap, t, &t))
+      return NULL;
+  return t;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_wstring_out(struct soap *soap, const wchar_t *s, int flag)
+{ const char *t;
+  char tmp;
+  register soap_wchar c;
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+  { soap->dom->wide = NULL; /* soap_malloc() ??? */
+    return SOAP_OK;
+  }
+#endif
+  while ((c = *s++))
+  { switch (c)
+    { 
+    case 9:
+      if (flag)
+        t = "&#x9;";
+      else
+        t = "\t";
+      break;
+    case 10:
+      if (flag || !(soap->mode & SOAP_XML_CANONICAL))
+        t = "&#xA;";
+      else
+        t = "\n";
+      break;
+    case 13:
+      t = "&#xD;";
+      break;
+    case '&':
+      t = "&amp;";
+      break;
+    case '<':
+      t = "&lt;";
+      break;
+    case '>':
+      if (flag)
+        t = ">";
+      else
+	t = "&gt;";
+      break;
+    case '"':
+      if (flag)
+        t = "&quot;";
+      else
+        t = "\"";
+      break;
+    default:
+      if (c > 0 && c < 0x80)
+      { tmp = (char)c;
+        if (soap_send_raw(soap, &tmp, 1))
+          return soap->error;
+      }
+      else if (soap_pututf8(soap, (unsigned long)c))
+        return soap->error;
+      continue;
+    }
+    if (soap_send(soap, t))
+      return soap->error;
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+wchar_t *
+SOAP_FMAC2
+soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen)
+{ wchar_t *s;
+  register int i, n = 0;
+  register long l = 0;
+  register soap_wchar c;
+  const char *t = NULL;
+  if (soap_new_block(soap))
+    return NULL;
+  for (;;)
+  { if (!(s = (wchar_t*)soap_push_block(soap, sizeof(wchar_t)*SOAP_BLKLEN)))
+      return NULL;
+    for (i = 0; i < SOAP_BLKLEN; i++)
+    { if (t)
+      { *s++ = (wchar_t)*t++;
+        if (!*t)
+          t = NULL;
+        continue;
+      }
+      c = soap_getutf8(soap);
+      switch (c)
+      {
+      case SOAP_TT:
+        if (n == 0)
+          goto end;
+        n--;
+        *s++ = '<';
+        soap_unget(soap, '/');
+        break;
+      case SOAP_LT:
+        n++;
+        *s++ = '<';
+        break;
+      case SOAP_GT:
+        *s++ = '>';
+        break;
+      case SOAP_QT:
+        *s++ = '"';
+        break;
+      case SOAP_AP:
+        *s++ = '\'';
+        break;
+      case '/':
+        if (n > 0)
+        { c = soap_getutf8(soap);
+          if (c == SOAP_GT)
+            n--;
+          soap_unget(soap, c);
+        }
+        *s++ = '/';
+        break;
+      case '<':
+        if (flag)
+          *s++ = (soap_wchar)'<';
+        else
+        { *s++ = (soap_wchar)'&';
+          t = "lt;";
+        }
+        break;
+      case '>':
+        if (flag)
+          *s++ = (soap_wchar)'>';
+        else
+        { *s++ = (soap_wchar)'&';
+          t = "gt;";
+        }
+        break;
+      case '"':
+        if (flag)
+          *s++ = (soap_wchar)'"';
+        else
+        { *s++ = (soap_wchar)'&';
+          t = "quot;";
+        }
+        break;
+      default:
+        if ((int)c == EOF)
+          goto end;
+        *s++ = (wchar_t)c & 0x7FFFFFFF;
+      }
+      l++;
+      if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen)
+      { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
+        soap->error = SOAP_LENGTH;
+        return NULL;
+      }
+    }
+  }
+end:
+  soap_unget(soap, c);
+  *s = '\0';
+  soap_size_block(soap, sizeof(wchar_t) * (i + 1));
+  if ((soap->mode & SOAP_XML_STRICT) && l < minlen)
+  { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
+    soap->error = SOAP_LENGTH;
+    return NULL;
+  }
+  return (wchar_t*)soap_save_block(soap, NULL, 0);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_int2s(struct soap *soap, int n)
+{ return soap_long2s(soap, (long)n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2int(struct soap *soap, const char *s, int *p)
+{ if (s)
+  { char *r;
+    *p = (int)soap_strtol(s, &r, 10);
+    if (*r)
+      soap->error = SOAP_TYPE;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int *
+SOAP_FMAC2
+soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":int")
+   && soap_match_tag(soap, soap->type, ":short")
+   && soap_match_tag(soap, soap->type, ":byte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL);
+  if (p)
+  { if (soap_s2int(soap, soap_value(soap), p))
+      return NULL;
+  }
+  p = (int*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(int), 0, NULL);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_long2s(struct soap *soap, long n)
+{ sprintf(soap->tmpbuf, "%ld", n);
+  return soap->tmpbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_long2s(soap, *p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2long(struct soap *soap, const char *s, long *p)
+{ if (s)
+  { char *r;
+    *p = soap_strtol(s, &r, 10);
+    if (*r)
+      soap->error = SOAP_TYPE;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+long *
+SOAP_FMAC2
+soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":int")
+   && soap_match_tag(soap, soap->type, ":short")
+   && soap_match_tag(soap, soap->type, ":byte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL);
+  if (p)
+  { if (soap_s2long(soap, soap_value(soap), p))
+      return NULL;
+  }
+  p = (long*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(long), 0, NULL);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_LONG642s(struct soap *soap, LONG64 n)
+{ sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n);
+  return soap->tmpbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_LONG642s(soap, *p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p)
+{ if (s && sscanf(s, SOAP_LONG_FORMAT, p) != 1)
+    soap->error = SOAP_TYPE;
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+LONG64 *
+SOAP_FMAC2
+soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":integer")
+   && soap_match_tag(soap, soap->type, ":positiveInteger")
+   && soap_match_tag(soap, soap->type, ":negativeInteger")
+   && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
+   && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
+   && soap_match_tag(soap, soap->type, ":long")
+   && soap_match_tag(soap, soap->type, ":int")
+   && soap_match_tag(soap, soap->type, ":short")
+   && soap_match_tag(soap, soap->type, ":byte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL);
+  if (p)
+  { if (soap_s2LONG64(soap, soap_value(soap), p))
+      return NULL;
+  }
+  p = (LONG64*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(LONG64), 0, NULL);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_byte2s(struct soap *soap, char n)
+{ return soap_long2s(soap, (long)n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2byte(struct soap *soap, const char *s, char *p)
+{ if (s)
+  { long n;
+    char *r;
+    n = soap_strtol(s, &r, 10);
+    if (*r || n < -128 || n > 127)
+      soap->error = SOAP_TYPE;
+    *p = (char)n;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":byte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL);
+  if (p)
+  { if (soap_s2byte(soap, soap_value(soap), p))
+      return NULL;
+  }
+  p = (char*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(char), 0, NULL);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_short2s(struct soap *soap, short n)
+{ return soap_long2s(soap, (long)n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2short(struct soap *soap, const char *s, short *p)
+{ if (s)
+  { long n;
+    char *r;
+    n = soap_strtol(s, &r, 10);
+    if (*r || n < -32768 || n > 32767)
+      soap->error = SOAP_TYPE;
+    *p = (short)n;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+short *
+SOAP_FMAC2
+soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":short")
+   && soap_match_tag(soap, soap->type, ":byte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL);
+  if (p)
+  { if (soap_s2short(soap, soap_value(soap), p))
+      return NULL;
+  }
+  p = (short*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(short), 0, NULL);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_float2s(struct soap *soap, float n)
+{ const char *s;
+  if (soap_isnan((double)n))
+    s = "NaN";
+  else if (soap_ispinff(n))
+    s = "INF";
+  else if (soap_isninff(n))
+    s = "-INF";
+  else
+  { sprintf(soap->tmpbuf, soap->float_format, n);
+    s = soap->tmpbuf;
+  }
+  return s;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_float2s(soap, *p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2float(struct soap *soap, const char *s, float *p)
+{ if (s)
+  { if (!soap_tag_cmp(s, "INF"))
+      *p = FLT_PINFTY;
+    else if (!soap_tag_cmp(s, "+INF"))
+      *p = FLT_PINFTY;
+    else if (!soap_tag_cmp(s, "-INF"))
+      *p = FLT_NINFTY;
+    else if (!soap_tag_cmp(s, "NaN"))
+      *p = FLT_NAN;
+    else
+    {
+#ifdef HAVE_STRTOD
+      char *r;
+      *p = (float)strtod(s, &r);
+      if (*r)
+#endif
+#ifdef HAVE_SSCANF
+        if (sscanf(s, soap->float_format, p) != 1)
+          soap->error = SOAP_TYPE;
+#else
+        soap->error = SOAP_TYPE;
+#endif
+    }
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+static int soap_isnumeric(struct soap *soap, const char *type)
+{ if (soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":float")
+   && soap_match_tag(soap, soap->type, ":double")
+   && soap_match_tag(soap, soap->type, ":decimal")
+   && soap_match_tag(soap, soap->type, ":integer")
+   && soap_match_tag(soap, soap->type, ":positiveInteger")
+   && soap_match_tag(soap, soap->type, ":negativeInteger")
+   && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
+   && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
+   && soap_match_tag(soap, soap->type, ":long")
+   && soap_match_tag(soap, soap->type, ":int")
+   && soap_match_tag(soap, soap->type, ":short")
+   && soap_match_tag(soap, soap->type, ":byte")
+   && soap_match_tag(soap, soap->type, ":unsignedLong")
+   && soap_match_tag(soap, soap->type, ":unsignedInt")
+   && soap_match_tag(soap, soap->type, ":unsignedShort")
+   && soap_match_tag(soap, soap->type, ":unsignedByte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return SOAP_ERR;
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+float *
+SOAP_FMAC2
+soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type != '\0' && soap_isnumeric(soap, type))
+    return NULL;
+#endif
+  p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL);
+  if (p)
+  { if (soap_s2float(soap, soap_value(soap), p))
+      return NULL;
+  }
+  p = (float*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(float), 0, NULL);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_double2s(struct soap *soap, double n)
+{ const char *s;
+  if (soap_isnan(n))
+    s = "NaN";
+  else if (soap_ispinfd(n))
+    s = "INF";
+  else if (soap_isninfd(n))
+    s = "-INF";
+  else
+  { sprintf(soap->tmpbuf, soap->double_format, n);
+    s = soap->tmpbuf;
+  }
+  return s;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_double2s(soap, *p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2double(struct soap *soap, const char *s, double *p)
+{ if (s)
+  { if (!soap_tag_cmp(s, "INF"))
+      *p = DBL_PINFTY;
+    else if (!soap_tag_cmp(s, "+INF"))
+      *p = DBL_PINFTY;
+    else if (!soap_tag_cmp(s, "-INF"))
+      *p = DBL_NINFTY;
+    else if (!soap_tag_cmp(s, "NaN"))
+      *p = DBL_NAN;
+    else
+    {
+#ifdef HAVE_STRTOD
+      char *r;
+      *p = strtod(s, &r);
+      if (*r)
+#endif
+#ifdef HAVE_SSCANF
+        if (sscanf(s, soap->double_format, p) != 1)
+          soap->error = SOAP_TYPE;
+#else
+        soap->error = SOAP_TYPE;
+#endif
+    }
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+double *
+SOAP_FMAC2
+soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type != '\0' && soap_isnumeric(soap, type))
+    return NULL;
+#endif
+  p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL);
+  if (p)
+  { if (soap_s2double(soap, soap_value(soap), p))
+      return NULL;
+  }
+  p = (double*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(double), 0, NULL);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_unsignedByte2s(struct soap *soap, unsigned char n)
+{ return soap_unsignedLong2s(soap, (unsigned long)n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p)
+{ if (s)
+  { unsigned long n;
+    char *r;
+    n = soap_strtoul(s, &r, 10);
+    if (*r || n > 255)
+      soap->error = SOAP_TYPE;
+    *p = (unsigned char)n;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+unsigned char *
+SOAP_FMAC2
+soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":unsignedByte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL);
+  if (p)
+  { if (soap_s2unsignedByte(soap, soap_value(soap), p))
+      return NULL;
+  }
+  p = (unsigned char*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned char), 0, NULL);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_unsignedShort2s(struct soap *soap, unsigned short n)
+{ return soap_unsignedLong2s(soap, (unsigned long)n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p)
+{ if (s)
+  { unsigned long n;
+    char *r;
+    n = soap_strtoul(s, &r, 10);
+    if (*r || n > 65535)
+      soap->error = SOAP_TYPE;
+    *p = (unsigned short)n;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+unsigned short *
+SOAP_FMAC2
+soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":unsignedShort")
+   && soap_match_tag(soap, soap->type, ":unsignedByte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL);
+  if (p)
+  { if (soap_s2unsignedShort(soap, soap_value(soap), p))
+      return NULL;
+  }
+  p = (unsigned short*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned short), 0, NULL);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_unsignedInt2s(struct soap *soap, unsigned int n)
+{ return soap_unsignedLong2s(soap, (unsigned long)n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p)
+{ if (s)
+  { char *r;
+    *p = (unsigned int)soap_strtoul(s, &r, 10);
+    if (*r)
+      soap->error = SOAP_TYPE;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+unsigned int *
+SOAP_FMAC2
+soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":unsignedInt")
+   && soap_match_tag(soap, soap->type, ":unsignedShort")
+   && soap_match_tag(soap, soap->type, ":unsignedByte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL);
+  if (p)
+  { if (soap_s2unsignedInt(soap, soap_value(soap), p))
+      return NULL;
+  }
+  p = (unsigned int*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned int), 0, NULL);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_unsignedLong2s(struct soap *soap, unsigned long n)
+{ sprintf(soap->tmpbuf, "%lu", n);
+  return soap->tmpbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p)
+{ if (s)
+  { char *r;
+    *p = soap_strtoul(s, &r, 10);
+    if (*r)
+      soap->error = SOAP_TYPE;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+unsigned long *
+SOAP_FMAC2
+soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":unsignedInt")
+   && soap_match_tag(soap, soap->type, ":unsignedShort")
+   && soap_match_tag(soap, soap->type, ":unsignedByte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL);
+  if (p)
+  { if (soap_s2unsignedLong(soap, soap_value(soap), p))
+      return NULL;
+  }
+  p = (unsigned long*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned long), 0, NULL);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_ULONG642s(struct soap *soap, ULONG64 n)
+{ sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n);
+  return soap->tmpbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_ULONG642s(soap, *p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p)
+{ if (s && sscanf(s, SOAP_ULONG_FORMAT, p) != 1)
+    soap->error = SOAP_TYPE;
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+ULONG64 *
+SOAP_FMAC2
+soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0))
+    return NULL;
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":positiveInteger")
+   && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
+   && soap_match_tag(soap, soap->type, ":unsignedLong")
+   && soap_match_tag(soap, soap->type, ":unsignedInt")
+   && soap_match_tag(soap, soap->type, ":unsignedShort")
+   && soap_match_tag(soap, soap->type, ":unsignedByte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+  p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL);
+  if (p)
+  { if (soap_s2ULONG64(soap, soap_value(soap), p))
+      return NULL;
+  }
+  p = (ULONG64*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(ULONG64), 0, NULL);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2string(struct soap *soap, const char *s, char **t)
+{ *t = NULL;
+  if (s && !(*t = soap_strdup(soap, s)))
+    soap->error = SOAP_EOM;
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2QName(struct soap *soap, const char *s, char **t)
+{ if (s)
+  { struct soap_nlist *np;
+    const char *p;
+    if (!strncmp(s, "xml:", 4))
+    { *t = soap_strdup(soap, s);
+      return SOAP_OK;
+    }
+    np = soap->nlist;
+    p = strchr(s, ':');
+    if (p)
+    { register int n = p - s;
+      while (np && (strncmp(np->id, s, n) || np->id[n]))
+        np = np->next;
+      p++;
+    }
+    else
+    { while (np && *np->id)
+        np = np->next;
+      p = s;
+    }
+    if (np)
+    { if (np->index >= 0 && soap->local_namespaces)
+      { register const char *q = soap->local_namespaces[np->index].id;
+        if (q)
+        { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(q) + 2)))
+            sprintf(*t, "%s:%s", q, p);
+          return SOAP_OK;
+        }
+      }
+      if (np->ns)
+      { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(np->ns) + 4)))
+          sprintf(*t, "\"%s\":%s", np->ns, p);
+        return SOAP_OK;
+      }
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined (index=%d, URI=%s)\n", s, np->index, np->ns?np->ns:""));
+      return soap->error = SOAP_NAMESPACE; 
+    }
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined, assuming empty namespace\n", s));
+    if ((*t = (char*)soap_malloc(soap, strlen(p) + 4)))
+      sprintf(*t, "\"\":%s", p);
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_QName2s(struct soap *soap, const char *s)
+{ struct Namespace *p;
+  char *t;
+  int n;
+  if (!s || *s != '"')
+    return s;
+  s++;
+  if ((p = soap->local_namespaces))
+  { for (; p->id; p++)
+    { if (p->ns)
+        if (!soap_tag_cmp(s, p->ns))
+          break;
+      if (p->in)
+        if (!soap_tag_cmp(s, p->in))
+          break;
+    }
+    if (p && p->id)
+    { s = strchr(s, '"');
+      if (s)
+      { t = (char*)soap_malloc(soap, strlen(p->id) + strlen(s));
+        strcpy(t, p->id);
+	strcat(t, s + 1);
+        return t;
+      }
+    }
+  }
+  t = (char*)strchr(s, '"');
+  if (t)
+    n = t - s;
+  else
+    n = 0;
+  t = soap_strdup(soap, s);
+  t[n] = '\0';
+  sprintf(soap->tmpbuf, "xmlns:_%lu", soap->idnum++);
+  soap_set_attr(soap, soap->tmpbuf, t);
+  s = strchr(s, '"');
+  if (s)
+  { t = (char*)soap_malloc(soap, strlen(soap->tmpbuf) + strlen(s) - 6);
+    strcpy(t, soap->tmpbuf + 6);
+    strcat(t, s + 1);
+  }
+  return t;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n) 
+{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
+  if (id < 0
+   || soap_element_begin_out(soap, tag, id, type)
+   || soap_string_out(soap, *p, 0)
+   || soap_element_end_out(soap, tag))
+    return soap->error;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char **
+SOAP_FMAC2
+soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen)
+{ if (soap_element_begin_in(soap, tag, 1))
+    return NULL;
+  if (!p)
+    if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
+      return NULL;
+  if (soap->body)
+  { *p = soap_string_in(soap, flag, minlen, maxlen);
+    if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL))
+      return NULL;
+  }
+  else
+    *p = NULL;
+  p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n) 
+{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
+  if (id < 0
+   || soap_element_begin_out(soap, tag, id, type)
+   || soap_wstring_out(soap, *p, 0)
+   || soap_element_end_out(soap, tag))
+    return soap->error;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+wchar_t **
+SOAP_FMAC2
+soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen)
+{ if (soap_element_begin_in(soap, tag, 1))
+    return NULL;
+  if (!p)
+    if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
+      return NULL;
+  if (soap->body)
+  { *p = soap_wstring_in(soap, 1, minlen, maxlen);
+    if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL))
+      return NULL;
+  }
+  else
+    *p = NULL;
+  p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+static time_t
+soap_timegm(struct tm *T)
+{
+#if defined(HAVE_TIMEGM)
+  return timegm(T);
+#elif defined(HAVE_GETTIMEOFDAY)
+  struct timezone t;
+  struct timeval tv;
+  memset((void*)&t, 0, sizeof(t));
+  gettimeofday(&tv, &t);
+  T->tm_min -= t.tz_minuteswest - (t.tz_dsttime != 0)*60;
+  T->tm_isdst = 0;
+  return mktime(T);
+/* WR[ */
+  /* The following define was added for VxWorks*/
+#elif defined(HAVE_MKTIME)
+  /* FOR VXWORKS:
+  vxWorks does not seem to have any variable representation of time zones, but
+  timezone information can be set in INSTALL_DIR/target/h/private/timeP.h header
+  file, by setting the ZONEBUFFER define.  The ZONEBUFFER define follows this 
+  format:
+    name_of_zone:<(unused)>:time_in_minutes_from_UTC:daylight_start:daylight_end 
+  To calculate local time, the value of time_in_minutes_from_UTC is subtracted
+  from UTC; time_in_minutes_from_UTC must be positive. Daylight information is 
+  expressed as mmddhh (month-day-hour), for example: 
+    UTC::0:040102:100102
+  */
+  return mktime(T);
+/* ]WR */
+#elif defined(HAVE_FTIME)
+  struct timeb t;
+  memset((void*)&t, 0, sizeof(t));
+  t.timezone = 0;
+  t.dstflag = -1;
+  ftime(&t);
+  T->tm_min -= t.timezone - (t.dstflag != 0)*60;
+  T->tm_isdst = 0;
+  return mktime(T);
+#else
+#warning "time_t (de)serialization is not MT safe on this platform"
+  time_t t;
+  char *tz = getenv("TZ");
+  putenv("TZ=UTC");
+  tzset();
+  t = mktime(T);
+  if (tz)
+  { char tmp[16];
+    strcpy(tmp, "TZ=");
+    strncat(tmp, tz, 12);
+    tmp[15] = '\0';
+    putenv(tmp);
+  }
+  else
+    putenv("TZ=");
+  tzset();
+  return t;
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_dateTime2s(struct soap *soap, time_t n)
+{ struct tm T;
+  struct tm *pT = &T;
+#if defined(HAVE_GMTIME_R)
+  if (gmtime_r(&n, pT))
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
+/* WR[ */
+  /* The following defines were added for VxWorks*/
+#elif defined(HAVE_PGMTIME_R)
+  if (gmtime_r(&n, pT))
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
+#elif defined(HAVE_PGMTIME)
+  if (gmtime(&n, pT))
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
+/* ]WR */
+#elif defined(HAVE_GMTIME)
+  if ((pT = gmtime(&n)))
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
+#elif defined(HAVE_GETTIMEOFDAY)
+  struct timezone tz;
+  memset((void*)&tz, 0, sizeof(tz));
+#if defined(HAVE_LOCALTIME_R)
+  if (localtime_r(&n, pT))
+  { struct timeval tv;
+    gettimeofday(&tv, &tz);
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+    sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(tz.tz_dsttime!=0), abs(tz.tz_minuteswest)%60);
+  }
+#else
+  if ((pT = localtime(&n)))
+  { struct timeval tv;
+    gettimeofday(&tv, &tz);
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+    sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(tz.tz_dsttime!=0), abs(tz.tz_minuteswest)%60);
+  }
+#endif
+#elif defined(HAVE_FTIME)
+  struct timeb t;
+  memset((void*)&t, 0, sizeof(t));
+#if defined(HAVE_LOCALTIME_R)
+  if (localtime_r(&n, pT))
+  { ftime(&t);
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+    sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(t.dstflag!=0), abs(t.timezone)%60);
+  }
+/* WR[ */
+  /* The following defines were added for VxWorks*/
+#elif defined(HAVE_PLOCALTIME_R)
+  if (localtime_r(&n, pT))
+  { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+    sprintf(soap->tmpbuf+strlen(soap->tmpbuf), "%+03d:%02d", t.timezone/60, abs(t.timezone)%60);
+  }
+/* ]WR */
+#else
+  if ((pT = localtime(&n)))
+  { ftime(&t);
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+    sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(t.dstflag!=0), abs(t.timezone)%60);
+  }
+#endif
+#elif defined(HAVE_LOCALTIME_R)
+  if (localtime_r(&n, pT))
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+/* WR[ */
+  /* The following defines were added for VxWorks*/
+#elif defined(HAVE_PLOCALTIME_R)
+  if (localtime_r(&n, pT))
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+/* ]WR */
+#else
+  if ((pT = localtime(&n)))
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+#endif
+  else
+    strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z");
+  return soap->tmpbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_dateTime2s(soap, *p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2dateTime(struct soap *soap, const char *s, time_t *p)
+{ if (s)
+  { struct tm T;
+    char zone[16];
+    memset((void*)&T, 0, sizeof(T));
+    zone[sizeof(zone)-1] = '\0';
+    sscanf(s, "%d-%d-%dT%d:%d:%d%15s", &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone);
+    if (T.tm_year == 1)
+      T.tm_year = 70;
+    else
+      T.tm_year -= 1900;
+    T.tm_mon--;
+    if (*zone)
+    { if (*zone == '.')
+      { for (s = zone + 1; *s; s++)
+          if (*s < '0' || *s > '9')
+            break;
+      }
+      else
+        s = zone;
+      if (*s != 'Z')
+      { int h = 0, m = 0;
+        sscanf(s, "%d:%d", &h, &m);
+        T.tm_hour -= h;
+        if (h >= 0)
+          T.tm_min -= m;
+        else
+          T.tm_min += m;
+      }
+      *p = soap_timegm(&T);
+    }
+    else
+      *p = mktime(&T); /* no time zone: suppose it is localtime? */
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+time_t *
+SOAP_FMAC2
+soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char * type, int t)
+{ if (soap_element_begin_in(soap, tag, 0))
+    return NULL;
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":dateTime"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+  p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL);
+  if (p)
+  { if (soap_s2dateTime(soap, soap_value(soap), p))
+      return NULL;
+  }
+  p = (time_t*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(time_t), 0, NULL);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outliteral(struct soap *soap, const char *tag, char *const*p)
+{ int i;
+  const char *t = NULL;
+  if (tag && *tag != '-')
+  { if ((t = strchr(tag, ':')))
+    { strncpy(soap->tmpbuf, tag, t-tag);
+      soap->tmpbuf[t-tag] = '\0';
+      for (i = 0; soap->local_namespaces[i].id; i++)
+        if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
+          break;
+      t++;
+      sprintf(soap->tmpbuf, "<%s xmlns=\"%s\">", t, soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS);
+    }
+    else
+    { t = tag;
+      sprintf(soap->tmpbuf, "<%s>", tag);
+    }
+    if (soap_send(soap, soap->tmpbuf))
+      return soap->error;
+  }
+  if (p && *p)
+  { if (soap_send(soap, *p))
+      return soap->error;
+  }
+  if (t)
+  { sprintf(soap->tmpbuf, "</%s>", t);
+    return soap_send(soap, soap->tmpbuf);
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char **
+SOAP_FMAC2
+soap_inliteral(struct soap *soap, const char *tag, char **p)
+{ if (soap_element_begin_in(soap, tag, 1))
+    return NULL;
+  if (!p)
+    if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
+      return NULL;
+  if (soap->null)
+    *p = NULL;
+  else if (soap->body)
+    *p = soap_string_in(soap, 0, -1, -1);
+  else
+    *p = NULL;
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p)
+{ int i;
+  const char *t = NULL;
+  wchar_t c;
+  const wchar_t *s;
+  if (tag && *tag != '-')
+  { if (tag && (t = strchr(tag, ':')))
+    { strncpy(soap->tmpbuf, tag, t-tag);
+      soap->tmpbuf[t-tag] = '\0';
+      for (i = 0; soap->local_namespaces[i].id; i++)
+        if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
+          break;
+      t++;
+      sprintf(soap->tmpbuf, "<%s xmlns=\"%s\">", t, soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS);
+    }
+    else
+    { t = tag;
+      sprintf(soap->tmpbuf, "<%s>", tag);
+    }
+    if (soap_send(soap, soap->tmpbuf))
+      return soap->error;
+  }
+  if (p)
+  { s = *p;
+    while ((c = *s++))
+      if (soap_pututf8(soap, (unsigned char)c))
+        return soap->error;
+  }
+  if (t)
+  { sprintf(soap->tmpbuf, "</%s>", t);
+    return soap_send(soap, soap->tmpbuf);
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+wchar_t **
+SOAP_FMAC2
+soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p)
+{ if (soap_element_begin_in(soap, tag, 1))
+    return NULL;
+  if (!p)
+    if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
+      return NULL;
+  if (soap->null)
+    *p = NULL;
+  else if (soap->body)
+    *p = soap_wstring_in(soap, 0, -1, -1);
+  else
+    *p = NULL;
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char *
+SOAP_FMAC2
+soap_value(struct soap *soap)
+{ size_t i;
+  soap_wchar c = 0;
+  char *s = soap->tmpbuf;
+  if (!soap->body)
+    return SOAP_STR_EOS;
+  for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++)
+  { c = soap_get(soap);
+    if (c == SOAP_TT || (int)c == EOF || soap_blank(c))
+      break;
+    *s++ = (char)c;
+  }
+  if ((int)c == EOF || c == SOAP_TT)
+    soap_unget(soap, c);
+  *s = '\0';
+  return soap->tmpbuf; /* return non-null pointer */
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getline(struct soap *soap, char *s, int len)
+{ int i = len;
+  soap_wchar c = 0;
+  for (;;)
+  { while (--i > 0)
+    { c = soap_getchar(soap);
+      if (c == '\r')
+        break;
+      if ((int)c == EOF)
+        return soap->error = SOAP_EOF;
+      *s++ = (char)c;
+    }
+    c = soap_getchar(soap);
+    if (c == '\n')
+    { *s = '\0';
+      if (i+1 == len) /* empty line: end of HTTP header */
+        break;
+      c = soap_unget(soap, soap_getchar(soap));
+      if (c != ' ' && c != '\t') /* HTTP line continuation? */
+        break;
+    }
+    else if ((int)c == EOF)
+      return soap->error = SOAP_EOF;
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static size_t
+soap_count_attachments(struct soap *soap)
+{ 
+#ifndef WITH_LEANER
+  register struct soap_multipart *content;
+  register size_t count = soap->count;
+  if (soap->mode & SOAP_ENC_DIME)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n"));
+    for (content = soap->dime.first; content; content = content->next)
+    { count += 12 + ((content->size+3)&(~3));
+      if (content->id)
+        count += ((strlen(content->id)+3)&(~3));
+      if (content->type)
+        count += ((strlen(content->type)+3)&(~3));
+      if (content->options)
+        count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3);
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment %lu bytes\n", (unsigned long)content->size));
+    }
+  }
+  if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary)
+  { register size_t n = strlen(soap->mime.boundary);
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n"));
+    for (content = soap->mime.first; content; content = content->next)
+    { register const char *s;
+      /* count \r\n--boundary\r\n */
+      count += 6 + n;
+      /* count Content-Type: ...\r\n */
+      if (content->type)
+        count += 16 + strlen(content->type);
+      s = soap_str_code(mime_codes, content->encoding);
+      /* count Content-Transfer-Encoding: ...\r\n */
+      if (s)
+        count += 29 + strlen(s);
+      /* count Content-ID: ...\r\n */
+      if (content->id)
+        count += 14 + strlen(content->id);
+      /* count Content-Location: ...\r\n */
+      if (content->location)
+        count += 20 + strlen(content->location);
+      /* count Content-Description: ...\r\n */
+      if (content->description)
+        count += 23 + strlen(content->location);
+      /* count \r\n...content */
+      count += 2 + content->size;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment %lu bytes\n", (unsigned long)content->size));
+    }
+    /* count \r\n--boundary--\r\n */
+    count += 8 + n;
+  }
+  return count;
+#else
+  return soap->count;
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+static int
+soap_putdimefield(struct soap *soap, const char *s, size_t n)
+{ if (soap_send_raw(soap, s, n))
+    return soap->error;
+  return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_dime_option(struct soap *soap, unsigned short optype, const char *option)
+{ size_t n;
+  char *s = NULL;
+  if (option)
+  { n = strlen(option);
+    s = (char*)soap_malloc(soap, n + 5);
+    if (s)
+    { s[0] = optype >> 8;
+      s[1] = optype & 0xFF;
+      s[2] = n >> 8;
+      s[3] = n & 0xFF;
+      strcpy(s + 4, option);
+    }
+  }
+  return s;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_putdimehdr(struct soap *soap)
+{ unsigned char tmp[12];
+  size_t optlen = 0, idlen = 0, typelen = 0;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:""));
+  if (soap->dime.options)
+    optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4;
+  if (soap->dime.id)
+    idlen = strlen(soap->dime.id);
+  if (soap->dime.type)
+    typelen = strlen(soap->dime.type);
+  tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7);
+  tmp[1] = soap->dime.flags & 0xF0;
+  tmp[2] = optlen >> 8;
+  tmp[3] = optlen & 0xFF;
+  tmp[4] = idlen >> 8;
+  tmp[5] = idlen & 0xFF;
+  tmp[6] = typelen >> 8;
+  tmp[7] = typelen & 0xFF;
+  tmp[8] = soap->dime.size >> 24;
+  tmp[9] = (soap->dime.size >> 16) & 0xFF;
+  tmp[10] = (soap->dime.size >> 8) & 0xFF;
+  tmp[11] = soap->dime.size & 0xFF;
+  if (soap_send_raw(soap, (char*)tmp, 12)
+   || soap_putdimefield(soap, soap->dime.options, optlen)
+   || soap_putdimefield(soap, soap->dime.id, idlen)
+   || soap_putdimefield(soap, soap->dime.type, typelen))
+    return soap->error;
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_putdime(struct soap *soap)
+{ struct soap_multipart *content;
+  if (!(soap->mode & SOAP_ENC_DIME))
+    return SOAP_OK;
+  for (content = soap->dime.first; content; content = content->next)
+  { void *handle;
+    soap->dime.size = content->size;
+    soap->dime.id = content->id;
+    soap->dime.type = content->type;
+    soap->dime.options = content->options;
+    soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA;
+    if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error))
+    { size_t size = content->size;
+      if (!handle)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n"));
+        return soap->error;
+      }
+      if (!content->size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE))
+      { size_t chunksize = sizeof(soap->tmpbuf);
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n"));
+        do 
+        { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize);
+          DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size));
+          if (size < chunksize)
+ 	  { soap->dime.flags &= ~SOAP_DIME_CF;
+            if (!content->next)
+              soap->dime.flags |= SOAP_DIME_ME;
+	  }
+          else
+            soap->dime.flags |= SOAP_DIME_CF;
+	  soap->dime.size = size;
+          if (soap_putdimehdr(soap)
+	   || soap_putdimefield(soap, soap->tmpbuf, size))
+            break;
+          if (soap->dime.id)
+ 	  { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA);
+            soap->dime.id = NULL;
+            soap->dime.type = NULL;
+            soap->dime.options = NULL;
+          }  
+        } while (size >= chunksize);
+      }
+      else
+      { if (!content->next)
+          soap->dime.flags |= SOAP_DIME_ME;
+        if (soap_putdimehdr(soap))
+          return soap->error;
+        do
+        { size_t bufsize;
+	  if (size < sizeof(soap->tmpbuf))
+            bufsize = size;
+          else
+            bufsize = sizeof(soap->tmpbuf);
+          if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize)))
+          { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)soap->dime.size));
+            soap->error = SOAP_EOF;
+	    break;
+          }
+          if (soap_send_raw(soap, soap->tmpbuf, bufsize))
+            break;
+          size -= bufsize;
+        } while (size);
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
+        soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
+      }
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
+      if (soap->fdimereadclose)
+        soap->fdimereadclose(soap, handle);
+    }
+    else
+    { if (!content->next)
+        soap->dime.flags |= SOAP_DIME_ME;
+      if (soap_putdimehdr(soap)
+       || soap_putdimefield(soap, (char*)content->ptr, content->size))
+        return soap->error;
+    }
+  }
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+static char *
+soap_getdimefield(struct soap *soap, size_t n)
+{ register soap_wchar c;
+  register int i;
+  register char *s;
+  char *p = NULL;
+  if (n)
+  { p = (char*)soap_malloc(soap, n + 1);
+    if (p)
+    { s = p;
+      for (i = n; i > 0; i--)
+      { if ((int)(c = soap_get1(soap)) == EOF)
+        { soap->error = SOAP_EOF;
+          return NULL;
+        }
+        *s++ = (char)c;
+      }
+      *s = '\0';
+      if ((soap->error = soap_move(soap, -(long)n&3)))
+        return NULL;
+    }
+    else
+      soap->error = SOAP_EOM;
+  }
+  return p;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getdimehdr(struct soap *soap)
+{ register soap_wchar c;
+  register char *s;
+  register int i;
+  unsigned char tmp[12];
+  size_t optlen, idlen, typelen;
+  if (!(soap->mode & SOAP_ENC_DIME))
+    return soap->error = SOAP_DIME_END;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n"));
+  if (soap->dime.buflen || soap->dime.chunksize)
+  { if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap))))
+      return soap->error = SOAP_EOF;
+    soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n"));
+    return SOAP_OK;
+  }
+  s = (char*)tmp;
+  for (i = 12; i > 0; i--)
+  { if ((int)(c = soap_getchar(soap)) == EOF)
+      return soap->error = SOAP_EOF;
+    *s++ = (char)c;
+  }
+  if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION)
+    return soap->error = SOAP_DIME_MISMATCH;
+  soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0);
+  optlen = (tmp[2] << 8) | tmp[3];
+  idlen = (tmp[4] << 8) | tmp[5];
+  typelen = (tmp[6] << 8) | tmp[7];
+  soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11];
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags));
+  if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error)
+    return soap->error;
+  if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error)
+    return soap->error;
+  if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error)
+    return soap->error;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id=%s, type=%s, options=%s\n", soap->dime.id?soap->dime.id:"", soap->dime.type?soap->dime.type:"", soap->dime.options?soap->dime.options+4:""));
+  if (soap->dime.flags & SOAP_DIME_ME)
+    soap->mode &= ~SOAP_ENC_DIME;
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getdime(struct soap *soap)
+{ struct soap_multipart *content;
+  if (soap_getdimehdr(soap))
+    return soap->error;
+  if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error))
+  { const char *id, *type, *options;
+    size_t size, n;
+    if (!soap->dime.ptr)
+      return soap->error;
+    id = soap->dime.id;
+    type = soap->dime.type;
+    options = soap->dime.options;
+    for (;;)
+    { size = soap->dime.size;
+      for (;;)
+      { n = soap->buflen - soap->bufidx;
+        if (size < n)
+          n = size;
+        if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n)))
+          break;
+	size -= n;
+	if (!size)
+	{ soap->bufidx += n;
+	  break;
+	}
+	if (soap_recv(soap))
+        { soap->error = SOAP_EOF;
+	  goto end;
+        }
+      }
+      if (soap_move(soap, -(long)soap->dime.size&3))
+      { soap->error = SOAP_EOF;
+	break;
+      }
+      if (!(soap->dime.flags & SOAP_DIME_CF))
+        break;
+      if (soap_getdimehdr(soap))
+        break;
+    }
+end:
+    if (soap->fdimewriteclose)
+      soap->fdimewriteclose(soap, (void*)soap->dime.ptr);
+    soap->dime.size = 0;
+    soap->dime.id = id;
+    soap->dime.type = type;
+    soap->dime.options = options;
+  }
+  else if (soap->dime.flags & SOAP_DIME_CF)
+  { const char *id, *type, *options;
+    register soap_wchar c;
+    register char *s;
+    register int i;
+    id = soap->dime.id;
+    type = soap->dime.type;
+    options = soap->dime.options;
+    if (soap_new_block(soap))
+      return SOAP_EOM;
+    for (;;)
+    { s = (char*)soap_push_block(soap, soap->dime.size);
+      if (!s)
+        return soap->error = SOAP_EOM;
+      for (i = soap->dime.size; i > 0; i--)
+      { if ((int)(c = soap_get1(soap)) == EOF)
+          return soap->error = SOAP_EOF;
+        *s++ = (char)c;
+      }
+      if (soap_move(soap, -(long)soap->dime.size&3))
+        return soap->error = SOAP_EOF;
+      if (!(soap->dime.flags & SOAP_DIME_CF))
+        break;
+      if (soap_getdimehdr(soap))
+        return soap->error;
+    }
+    soap->dime.size = soap->blist->size++; /* allocate one more for '\0' */
+    if (!(soap->dime.ptr = soap_save_block(soap, NULL, 0)))
+      return soap->error;
+    soap->dime.ptr[soap->dime.size] = '\0'; /* force 0-terminated */
+    soap->dime.id = id;
+    soap->dime.type = type;
+    soap->dime.options = options;
+  }
+  else
+    soap->dime.ptr = soap_getdimefield(soap, soap->dime.size);
+  content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size);
+  if (!content)
+    return soap->error = SOAP_EOM;
+  content->id = soap->dime.id;
+  content->type = soap->dime.type;
+  content->options = soap->dime.options;
+  return soap->error;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getmimehdr(struct soap *soap)
+{ struct soap_multipart *content;
+  do
+  { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
+      return soap->error;
+  }
+  while (!*soap->msgbuf);
+  if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-')
+  { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1;
+    /* remove white space */
+    while (soap_blank(*s))
+      s--;
+    s[1] = '\0';
+    if (soap->mime.boundary)
+    { if (strcmp(soap->msgbuf + 2, soap->mime.boundary))
+        return soap->error = SOAP_MIME_ERROR;
+    }
+    else
+      soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2);
+    if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
+      return soap->error;
+  }
+  if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL))
+    return soap->error = SOAP_EOM;
+  content = soap->mime.last;
+  for (;;)
+  { register char *key = soap->msgbuf;
+    register char *val;
+    if (!*key)
+      break;
+    DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key));
+    val = strchr(soap->msgbuf, ':');
+    if (val)
+    { *val = '\0';
+      do val++;
+      while (*val && *val <= 32);
+      if (!soap_tag_cmp(key, "Content-ID"))
+        content->id = soap_strdup(soap, val);
+      else if (!soap_tag_cmp(key, "Content-Location"))
+        content->location = soap_strdup(soap, val);
+      else if (!soap_tag_cmp(key, "Content-Type"))
+        content->type = soap_strdup(soap, val);
+      else if (!soap_tag_cmp(key, "Content-Description"))
+        content->description = soap_strdup(soap, val);
+      else if (!soap_tag_cmp(key, "Content-Transfer-Encoding"))
+        content->encoding = (enum soap_mime_encoding)soap_int_code(mime_codes, val, (long)SOAP_MIME_NONE);
+    }
+    if (soap_getline(soap, key, sizeof(soap->msgbuf)))
+      return soap->error;
+  }
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getmime(struct soap *soap)
+{ register soap_wchar c;
+  if (!soap->mime.last)
+    return SOAP_OK;
+  for (;;)
+  { register size_t i, m = 0;
+    register char *s;
+    struct soap_multipart *content = soap->mime.last;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id=%s type=%s\n", content->id?content->id:"", content->type?content->type:""));
+    if (soap_new_block(soap))
+      return soap->error = SOAP_EOM;
+    for (;;)
+    { register char *t = NULL;
+      if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN)))
+        return soap->error = SOAP_EOM;
+      for (i = 0; i < SOAP_BLKLEN; i++)
+      { if (m > 0)
+        { *s++ = *t++;
+	  m--;
+	}
+	else
+        { c = soap_get1(soap);
+	  if ((int)c == EOF)
+	    return soap->error = SOAP_EOF;
+	  if (c == '\r')
+	  { t = soap->tmpbuf;
+            strcpy(t, "\n--");
+            strncat(t, soap->mime.boundary, sizeof(soap->tmpbuf)-3);
+            t[sizeof(soap->tmpbuf)-1] = '\0';
+	    do c = soap_getchar(soap);
+	    while (c == *t++);
+	    if ((int)c == EOF)
+	      return soap->error = SOAP_EOF;
+	    if (!*--t)
+	      goto end;
+	    *t = (char)c;
+	    m = t - soap->tmpbuf + 1;
+	    t = soap->tmpbuf;
+	    c = '\r';
+	  }
+	  *s++ = (char)c;
+        }
+      }
+    }
+end:
+    *s = '\0'; /* force 0-terminated */
+    content->size = soap_size_block(soap, i+1)-1;
+    content->ptr = soap_save_block(soap, NULL, 0);
+    if (c == '-' && soap_getchar(soap) == '-')
+      break;
+    while (c != '\r' && (int)c != EOF && soap_blank(c))
+      c = soap_getchar(soap);
+    if (c != '\r' || soap_getchar(soap) != '\n')
+      return soap->error = SOAP_MIME_ERROR;
+    if (soap_getmimehdr(soap))
+      return soap->error;
+  }
+  do c = soap_getchar(soap);
+  while ((int)c != EOF && c != '\r');
+  if ((int)c == EOF)
+    return soap->error = SOAP_EOF;
+  if (soap_getchar(soap) != '\n')
+    return soap->error = SOAP_MIME_ERROR;
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_putmimehdr(struct soap *soap, struct soap_multipart *content)
+{ const char *s;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type?content->type:""));
+  if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n"))
+    return soap->error;
+  if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n"))
+    return soap->error;
+  s = soap_str_code(mime_codes, content->encoding);
+  if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n"))
+    return soap->error;
+  if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n"))
+    return soap->error;
+  if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n"))
+    return soap->error;
+  if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n"))
+    return soap->error;
+  return soap_send_raw(soap, "\r\n", 2);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_putmime(struct soap *soap)
+{ struct soap_multipart *content;
+  if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary)
+    return SOAP_OK;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n"));
+  for (content = soap->mime.first; content; content = content->next)
+    if (soap_putmimehdr(soap, content)
+     || soap_send_raw(soap, content->ptr, content->size))
+      return soap->error;
+  return soap_send3(soap, "\r\n--", soap->mime.boundary, "--\r\n");
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_dime(struct soap *soap)
+{ soap->omode |= SOAP_ENC_DIME;
+  soap->dime.first = NULL;
+  soap->dime.last = NULL;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_mime(struct soap *soap, const char *boundary, const char *start)
+{ soap->omode |= SOAP_ENC_MIME;
+  soap->mime.first = NULL;
+  soap->mime.last = NULL;
+  soap->mime.boundary = soap_strdup(soap, boundary);
+  soap->mime.start = soap_strdup(soap, start);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_clr_dime(struct soap *soap)
+{ soap->omode &= ~SOAP_ENC_DIME;
+  soap->dime.first = NULL;
+  soap->dime.last = NULL;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_clr_mime(struct soap *soap)
+{ soap->omode &= ~SOAP_ENC_MIME;
+  soap->mime.first = NULL;
+  soap->mime.last = NULL;
+  soap->mime.boundary = NULL;
+  soap->mime.start = NULL;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+static struct soap_multipart*
+soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size)
+{ struct soap_multipart *content;
+  content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart));
+  if (content)
+  { content->next = NULL;
+    content->ptr = ptr;
+    content->size = size;
+    content->id = NULL;
+    content->type = NULL;
+    content->options = NULL;
+    content->encoding = SOAP_MIME_NONE;
+    content->location = NULL;
+    content->description = NULL;
+    if (!*first)
+      *first = content;
+    if (*last)
+      (*last)->next = content;
+    *last = content;
+  }
+  return content;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option)
+{ struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size);
+  if (!content)
+    return SOAP_EOM;
+  content->id = soap_strdup(soap, id);
+  content->type = soap_strdup(soap, type);
+  content->options = soap_dime_option(soap, optype, option);
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_set_mime_attachment(struct soap *soap, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description)
+{ struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size);
+  if (!content)
+    return SOAP_EOM;
+  content->id = soap_strdup(soap, id);
+  content->type = soap_strdup(soap, type);
+  content->encoding = encoding;
+  content->location = soap_strdup(soap, location);
+  content->description = soap_strdup(soap, description);
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+struct soap_multipart*
+SOAP_FMAC2
+soap_next_multipart(struct soap_multipart *content)
+{ if (content)
+    return content->next;
+  return NULL;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+static void
+soap_select_mime_boundary(struct soap *soap)
+{ while (!soap->mime.boundary || soap_valid_mime_boundary(soap))
+  { register char *s = soap->mime.boundary;
+    register size_t n = 0;
+    if (s)
+      n = strlen(s);
+    if (n < 16)
+    { n = 72;
+      s = soap->mime.boundary = (char*)soap_malloc(soap, n);
+      if (!s)
+        return;
+    }
+    strcpy(s, "<>");
+    s += 2;
+    n -= 4;
+    while (n)
+    { *s++ = soap_base64o[rand()&0x3F];
+      n--;
+    }
+    *s = '\0';
+    strcat(s, "<>");
+  }
+  if (!soap->mime.start)
+    soap->mime.start = "<SOAP-ENV:Envelope>";
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+static int
+soap_valid_mime_boundary(struct soap *soap)
+{ register struct soap_multipart *content;
+  register size_t k = strlen(soap->mime.boundary);
+  for (content = soap->mime.first; content; content = content->next)
+  { if (content->ptr && content->size >= k)
+    { register const char *p = (const char*)content->ptr; 
+      register size_t i;
+      for (i = 0; i < content->size - k; i++, p++)
+        if (!strncmp(p, soap->mime.boundary, k))
+          return SOAP_ERR;
+    }
+  }
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+
+#ifdef WITH_COOKIES
+/******************************************************************************/
+SOAP_FMAC1
+size_t
+SOAP_FMAC2
+soap_encode_cookie(const char *s, char *t, size_t len)
+{ register int c;
+  register size_t n = len;
+  while ((c = *s++) && --n > 0)
+  { if (c > ' ' && c < 128 && c != ';' && c != ',')
+      *t++ = c;
+    else if (n > 2)
+    { *t++ = '%';
+      *t++ = (c >> 4) + (c > 159 ? '7' : '0');
+      c &= 0xF;
+      *t++ = c + (c > 9 ? '7' : '0');
+      n -= 2;
+    }
+    else
+      break;
+  }
+  *t = '\0';
+  return len - n;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+struct soap_cookie*
+SOAP_FMAC2
+soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
+{ struct soap_cookie *p;
+  size_t n;
+  if (!domain)
+    domain = soap->cookie_domain;
+  if (!path)
+    path = soap->cookie_path;
+  if (*path == '/')
+    path++;
+  n = strlen(path);
+  for (p = soap->cookies; p; p = p->next)
+    if (!strcmp(p->name, name)
+     && domain
+     && p->domain
+     && !strcmp(p->domain, domain)
+     && !strncmp(p->path, path, n))
+      break;
+  return p;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+struct soap_cookie*
+SOAP_FMAC2
+soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path)
+{ struct soap_cookie **p, *q;
+  int n;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie: %s=%s domain=%s path=%s\n", name, value?value:"", domain?domain:"", path?path:""));
+  if (!domain)
+    domain = soap->cookie_domain;
+  if (!path)
+    path = soap->cookie_path;
+  if (!path)
+  { soap_set_receiver_error(soap, "Cookie path not set", NULL, SOAP_HTTP_ERROR);
+    return NULL;
+  }
+  if (*path == '/')
+    path++;
+  q = soap_cookie(soap, name, domain, path);
+  if (!q)
+  { if ((q = (struct soap_cookie*)SOAP_MALLOC(sizeof(struct soap_cookie))))
+    { if ((q->name = (char*)SOAP_MALLOC(strlen(name)+1)))
+        strcpy(q->name, name);
+      q->value = NULL;
+      q->domain = NULL;
+      q->path = NULL;
+      q->expire = -1;
+      q->version = 0;
+      q->secure = 0;
+      q->env = 0;
+      q->modified = 0;
+      for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--)
+        if (!strcmp((*p)->name, name) && (*p)->path && strcmp((*p)->path, path) < 0)
+          break;
+      if (n)
+      { q->next = *p;
+        *p = q;
+      }
+      else
+      { SOAP_FREE(q->name);
+        SOAP_FREE(q);
+        q = NULL;
+      }
+    }
+  }
+  else
+    q->modified = 1;
+  if (q)
+  { if (q->value)
+    { SOAP_FREE(q->value);
+      q->value = NULL;
+    }
+    if (q->domain)
+    { SOAP_FREE(q->domain);
+      q->domain = NULL;
+    }
+    if (q->path)
+    { SOAP_FREE(q->path);
+      q->path = NULL;
+    }
+    if (value && *value && (q->value = (char*)SOAP_MALLOC(strlen(value)+1)))
+      strcpy(q->value, value);
+    if (domain && *domain && (q->domain = (char*)SOAP_MALLOC(strlen(domain)+1)))
+      strcpy(q->domain, domain);
+    if (path && *path && (q->path = (char*)SOAP_MALLOC(strlen(path)+1)))
+      strcpy(q->path, path);
+    q->session = 1;
+  }
+  return q;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
+{ struct soap_cookie **p, *q;
+  if (!domain)
+    domain = soap->cookie_domain;
+  if (!domain)
+  { soap_set_receiver_error(soap, "Cookie domain not set", SOAP_STR_EOS, SOAP_HTTP_ERROR);
+    return;
+  }
+  if (!path)
+    path = soap->cookie_path;
+  if (!path)
+  { soap_set_receiver_error(soap, "Cookie path not set", SOAP_STR_EOS, SOAP_HTTP_ERROR);
+    return;
+  }
+  if (*path == '/')
+    path++;
+  for (p = &soap->cookies, q = *p; q; q = *p)
+    if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path)))
+    { if (q->value)
+        SOAP_FREE(q->value);
+      if (q->domain)
+        SOAP_FREE(q->domain);
+      if (q->path)
+        SOAP_FREE(q->path);
+      *p = q->next;
+      SOAP_FREE(q);
+    }
+    else
+      p = &q->next;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
+{ struct soap_cookie *p;
+  if ((p = soap_cookie(soap, name, domain, path)))
+    return p->value;
+  return NULL;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+long
+SOAP_FMAC2
+soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path)
+{ struct soap_cookie *p;
+  if ((p = soap_cookie(soap, name, domain, path)))
+    return p->expire;
+  return -1;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path)
+{ struct soap_cookie *p;
+  if ((p = soap_cookie(soap, name, domain, path)))
+  { p->expire = expire;
+    p->modified = 1;
+    return SOAP_OK;
+  }
+  return SOAP_ERR;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
+{ struct soap_cookie *p;
+  if ((p = soap_cookie(soap, name, domain, path)))
+  { p->session = 1;
+    p->modified = 1;
+    return SOAP_OK;
+  }
+  return SOAP_ERR;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
+{ struct soap_cookie *p;
+  if ((p = soap_cookie(soap, name, domain, path)))
+  { p->session = 0;
+    p->modified = 1;
+    return SOAP_OK;
+  }
+  return SOAP_ERR;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_putsetcookies(struct soap *soap)
+{ struct soap_cookie *p;
+  char *s, tmp[4096];
+  const char *t;
+  for (p = soap->cookies; p; p = p->next)
+  { if (p->modified || !p->env)
+    { s = tmp;
+      if (p->name)
+        s += soap_encode_cookie(p->name, s, tmp-s+4064);
+      if (p->value && *p->value)
+      { *s++ = '=';
+        s += soap_encode_cookie(p->value, s, tmp-s+4064);
+      }
+      if (p->domain && (int)strlen(p->domain) < tmp-s+4064)
+        sprintf(s, ";Domain=%s", p->domain);
+      else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064)
+        sprintf(s, ";Domain=%s", soap->cookie_domain);
+      strcat(s, ";Path=/");
+      if (p->path)
+        t = p->path;
+      else
+        t = soap->cookie_path;
+      if (t)
+      { if (*t == '/')
+          t++;
+        if ((int)strlen(t) < tmp-s+4064)
+          strcat(s, t);
+      }
+      s += strlen(s);
+      if (p->version > 0)
+        sprintf(s, ";Version=%u", p->version);
+      if (p->expire >= 0)
+        sprintf(s, ";Max-Age=%ld", p->expire);
+      if (p->secure)
+        strcat(s, ";Secure");
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp));
+      if (soap->fposthdr(soap, "Set-Cookie", tmp))
+        return soap->error;
+    }
+  }
+  return SOAP_OK;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure)
+{ struct soap_cookie **p, *q;
+  unsigned int version = 0;
+  time_t now = time(NULL);
+  char *s, tmp[4096];
+  p = &soap->cookies;
+  while ((q = *p))
+  { if (q->expire && now > q->expire)
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name));
+      SOAP_FREE(q->name);
+      if (q->value)
+        SOAP_FREE(q->value);
+      if (q->domain)
+        SOAP_FREE(q->domain);
+      if (q->path)
+        SOAP_FREE(q->path);
+      *p = q->next;
+      SOAP_FREE(q);
+    }
+    else if ((!q->domain || !strcmp(q->domain, domain))
+          && (!q->path || !strncmp(q->path, path, strlen(q->path)))
+          && (!q->secure || secure))
+    { s = tmp;
+      if (q->version != version)
+      { sprintf(s, "$Version=%u;", q->version);
+        version = q->version;
+      }
+      if (q->name)
+        s += soap_encode_cookie(q->name, s, tmp-s+4080);
+      if (q->value && *q->value)
+      { *s++ = '=';
+        s += soap_encode_cookie(q->value, s, tmp-s+4080);
+      }
+      if (q->path && (int)strlen(q->path) < tmp-s+4080)
+      { sprintf(s, ";$Path=/%s", q->path);
+        s += strlen(s);
+      }
+      if (q->domain && (int)strlen(q->domain) < tmp-s+4080)
+        sprintf(s, ";$Domain=%s", q->domain);
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp));
+      if (soap->fposthdr(soap, "Cookie", tmp))
+        return soap->error;
+      p = &q->next;
+    }
+    else
+      p = &q->next;
+  }
+  return SOAP_OK;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_getcookies(struct soap *soap, const char *val)
+{ struct soap_cookie *p = NULL, *q;
+  const char *s;
+  char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
+  char *domain = NULL;
+  char *path = NULL;
+  unsigned int version = 0;
+  time_t now = time(NULL);
+  if (!val)
+    return;
+  s = val;
+  while (*s)
+  { s = soap_decode_key(tmp, sizeof(tmp), s);
+    if (!soap_tag_cmp(tmp, "$Version"))
+    { if ((s = soap_decode_val(tmp, sizeof(tmp), s)))
+      { if (p)
+          p->version = (int)atol(tmp);
+        else
+          version = (int)atol(tmp);
+      }
+    }
+    else if (!soap_tag_cmp(tmp, "$Path"))
+    { s = soap_decode_val(tmp, sizeof(tmp), s);
+      if (*tmp)
+      { if ((t = (char*)SOAP_MALLOC(strlen(tmp)+1)))
+          strcpy(t, tmp);
+      }
+      else
+        t = NULL;
+      if (p)
+      { if (p->path)
+          SOAP_FREE(p->path);
+        p->path = t;
+      }
+      else
+      { if (path)
+          SOAP_FREE(path);
+        path = t;
+      }
+    }
+    else if (!soap_tag_cmp(tmp, "$Domain"))
+    { s = soap_decode_val(tmp, sizeof(tmp), s);
+      if (*tmp)
+      { if ((t = (char*)SOAP_MALLOC(strlen(tmp)+1)))
+          strcpy(t, tmp);
+      }
+      else
+        t = NULL;
+      if (p)
+      { if (p->domain)
+          SOAP_FREE(p->domain);
+	p->domain = t;
+      }
+      else
+      { if (domain)
+          SOAP_FREE(domain);
+        domain = t;
+      }
+    }
+    else if (p && !soap_tag_cmp(tmp, "Path"))
+    { if (p->path)
+        SOAP_FREE(p->path);
+      s = soap_decode_val(tmp, sizeof(tmp), s);
+      if (*tmp)
+      { if ((p->path = (char*)SOAP_MALLOC(strlen(tmp)+1)))
+          strcpy(p->path, tmp);
+      }
+      else
+        p->path = NULL;
+    }
+    else if (p && !soap_tag_cmp(tmp, "Domain"))
+    { if (p->domain)
+        SOAP_FREE(p->domain);
+      s = soap_decode_val(tmp, sizeof(tmp), s);
+      if (*tmp)
+      { if ((p->domain = (char*)SOAP_MALLOC(strlen(tmp)+1)))
+          strcpy(p->domain, tmp);
+      }
+      else
+        p->domain = NULL;
+    }
+    else if (p && !soap_tag_cmp(tmp, "Version"))
+    { s = soap_decode_val(tmp, sizeof(tmp), s);
+      p->version = (unsigned int)atol(tmp);
+    }
+    else if (p && !soap_tag_cmp(tmp, "Max-Age"))
+    { s = soap_decode_val(tmp, sizeof(tmp), s);
+      p->expire = now + atol(tmp);
+    }
+    else if (p && !soap_tag_cmp(tmp, "Expires"))
+    { struct tm T;
+      char a[3]; 
+      static const char mns[] = "anebarprayunulugepctovec";
+      s = soap_decode_val(tmp, sizeof(tmp), s);
+      if (strlen(tmp) > 20)
+      { memset((void*)&T, 0, sizeof(T));
+        a[0] = tmp[4];
+        a[1] = tmp[5];
+        a[2] = '\0';
+        T.tm_mday = (int)atol(a);
+        a[0] = tmp[8];
+        a[1] = tmp[9];
+        T.tm_mon = (strstr(mns, a) - mns) / 2;
+        a[0] = tmp[11];
+        a[1] = tmp[12];
+        T.tm_year = 100 + (int)atol(a);
+        a[0] = tmp[13];
+        a[1] = tmp[14];
+        T.tm_hour = (int)atol(a);
+        a[0] = tmp[16];
+        a[1] = tmp[17];
+        T.tm_min = (int)atol(a);
+        a[0] = tmp[19];
+        a[1] = tmp[20];
+        T.tm_sec = (int)atol(a);
+        p->expire = soap_timegm(&T);
+      }
+    }
+    else if (p && !soap_tag_cmp(tmp, "Secure"))
+      p->secure = 1;
+    else
+    { if (p)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"", p->domain?p->domain:"", p->path?p->path:"", p->expire, p->secure));
+        if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
+        { q->version = p->version;
+          q->expire = p->expire;
+          q->secure = p->secure;
+          q->env = 1;
+        }
+        if (p->name)
+          SOAP_FREE(p->name);
+        if (p->value)
+          SOAP_FREE(p->value);
+        if (p->domain)
+          SOAP_FREE(p->domain);
+        if (p->path)
+          SOAP_FREE(p->path);
+        SOAP_FREE(p);
+      }
+      if ((p = (struct soap_cookie*)SOAP_MALLOC(sizeof(struct soap_cookie))))
+      { p->name = (char*)SOAP_MALLOC(strlen(tmp)+1);
+        strcpy(p->name, tmp);
+        s = soap_decode_val(tmp, sizeof(tmp), s);
+        if (*tmp)
+        { p->value = (char*)SOAP_MALLOC(strlen(tmp)+1);
+          strcpy(p->value, tmp);
+        }
+        else
+          p->value = NULL;
+        p->domain = domain;
+        p->path = path;
+        p->expire = 0;
+        p->secure = 0;
+        p->version = version;
+      }
+    }
+  }
+  if (p)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"", p->domain?p->domain:"", p->path?p->path:"", p->expire, p->secure));
+    if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
+    { q->version = p->version;
+      q->expire = p->expire;
+      q->secure = p->secure;
+    }
+    if (p->name)
+      SOAP_FREE(p->name);
+    if (p->value)
+      SOAP_FREE(p->value);
+    if (p->domain)
+      SOAP_FREE(p->domain);
+    if (p->path)
+      SOAP_FREE(p->path);
+    SOAP_FREE(p);
+  }
+  if (domain)
+    SOAP_FREE(domain);
+  if (path)
+    SOAP_FREE(path);
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getenv_cookies(struct soap *soap)
+{ struct soap_cookie *p;
+  const char *s;
+  char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
+  if (!(s = getenv("HTTP_COOKIE")))
+    return SOAP_ERR;
+  do
+  { s = soap_decode_key(key, sizeof(key), s);
+    s = soap_decode_val(val, sizeof(val), s);
+    p = soap_set_cookie(soap, key, val, NULL, NULL);
+    if (p)
+      p->env = 1;
+  } while (*s);
+  return SOAP_OK;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+struct soap_cookie*
+SOAP_FMAC2
+soap_copy_cookies(struct soap *soap)
+{ struct soap_cookie *p, **q, *r;
+  q = &r;
+  for (p = soap->cookies; p; p = p->next)
+  { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(sizeof(struct soap_cookie))))
+      return r;
+    **q = *p;
+    if (p->name)
+    { if (((*q)->name = (char*)SOAP_MALLOC(strlen(p->name)+1)))
+        strcpy((*q)->name, p->name);
+    }
+    if (p->value)
+    { if (((*q)->value = (char*)SOAP_MALLOC(strlen(p->value)+1)))
+        strcpy((*q)->value, p->value);
+    }
+    if (p->domain)
+    { if (((*q)->domain = (char*)SOAP_MALLOC(strlen(p->domain)+1)))
+        strcpy((*q)->domain, p->domain);
+    }
+    if (p->path)
+    { if (((*q)->path = (char*)SOAP_MALLOC(strlen(p->path)+1)))
+        strcpy((*q)->path, p->path);
+    }
+    q = &(*q)->next;
+  }
+  *q = NULL;
+  return r;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_free_cookies(struct soap *soap)
+{ struct soap_cookie *p;
+  for (p = soap->cookies; p; p = soap->cookies)
+  { soap->cookies = p->next;
+    SOAP_FREE(p->name);
+    if (p->value)
+      SOAP_FREE(p->value);
+    if (p->domain)
+      SOAP_FREE(p->domain);
+    if (p->path)
+      SOAP_FREE(p->path);
+    SOAP_FREE(p);
+  }
+}
+
+/******************************************************************************/
+#endif /* WITH_COOKIES */
+
+/******************************************************************************/
+#ifdef WITH_GZIP
+#ifndef PALM_1
+static int
+soap_getgziphdr(struct soap *soap)
+{ int i;
+  soap_wchar c, f = 0;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n"));
+  for (i = 0; i < 9; i++)
+  { if ((int)(c = soap_get1(soap) == EOF))
+      return soap->error = SOAP_EOF;
+    if (i == 2)
+      f = c;
+  }
+  if (f & 0x04) /* FEXTRA */
+  { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--)
+      if ((int)soap_get1(soap) == EOF)
+        return soap->error = SOAP_EOF;
+  }
+  if (f & 0x08) /* FNAME */
+    do
+      c = soap_get1(soap);
+    while (c && (int)c != EOF);
+  if ((int)c != EOF && (f & 0x10)) /* FCOMMENT */
+    do
+      c = soap_get1(soap);
+    while (c && (int)f != EOF);
+  if ((int)c != EOF && (f & 0x01)) /* FHCRC */
+  { if ((int)(c = soap_get1(soap)) != EOF)
+      c = soap_get1(soap);
+  }
+  if ((int)c == EOF)
+    return soap->error = SOAP_EOF;
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_begin_recv(struct soap *soap)
+{ soap_wchar c;
+  soap->error = SOAP_OK;
+  soap_free(soap);
+  soap_set_local_namespaces(soap);
+  soap->version = 0;	/* don't assume we're parsing SOAP content by default */
+  soap_free_iht(soap);
+  if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
+    soap->omode |= SOAP_IO_CHUNK;
+  soap->imode &= ~SOAP_IO;
+  soap->mode = soap->imode;
+  if (!soap->keep_alive)
+  { soap->buflen = 0;
+    soap->bufidx = 0;
+  }
+  if (!(soap->mode & SOAP_IO_KEEPALIVE))
+    soap->keep_alive = 0;
+  soap->ahead = 0;
+  soap->peeked = 0;
+  soap->level = 0;
+  soap->part = SOAP_BEGIN;
+  soap->alloced = 0;
+  soap->count = 0;
+  soap->length = 0;
+  soap->cdata = 0;
+  *soap->endpoint = '\0';
+  soap->userid = NULL;
+  soap->passwd = NULL;
+  soap->action = NULL;
+  soap->authrealm = NULL;
+  soap->dime.chunksize = 0;
+  soap->dime.buflen = 0;
+  soap->dime.list = NULL;
+  soap->dime.first = NULL;
+  soap->dime.last = NULL;
+  soap->mime.list = NULL;
+  soap->mime.first = NULL;
+  soap->mime.last = NULL;
+  soap->mime.boundary = NULL;
+  soap->mime.start = NULL;
+#ifdef WIN32
+#ifndef UNDER_CE
+#ifndef WITH_FASTCGI
+  if (!soap_valid_socket(soap->socket))
+#ifdef __BORLANDC__
+    setmode((SOAP_SOCKET)soap->recvfd, O_BINARY);
+#else
+    _setmode((SOAP_SOCKET)soap->recvfd, _O_BINARY);
+#endif
+#endif
+#endif
+#endif
+#ifdef WITH_ZLIB
+  soap->mode &= ~SOAP_ENC_ZLIB;
+  soap->zlib_in = SOAP_ZLIB_NONE;
+  soap->zlib_out = SOAP_ZLIB_NONE;
+  soap->d_stream.next_in = Z_NULL;
+  soap->d_stream.avail_in = 0;
+  soap->d_stream.next_out = (Byte*)soap->buf;
+  soap->d_stream.avail_out = SOAP_BUFLEN;
+  soap->z_ratio_in = 1.0;
+  if (soap->fprepareinit)
+    soap->fprepareinit(soap);
+#endif
+  c = soap_getchar(soap);
+#ifdef WITH_GZIP
+  if (c == 0x1F)
+  { if (soap_getgziphdr(soap))
+      return soap->error;
+    if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK)
+      return soap->error = SOAP_ZLIB_ERROR;
+    soap->zlib_state = SOAP_ZLIB_INFLATE;
+    soap->mode |= SOAP_ENC_ZLIB;
+    soap->zlib_in = SOAP_ZLIB_GZIP;
+    soap->z_crc = crc32(0L, NULL, 0);
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
+    memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
+    /* should not chunk over plain transport, so why bother to check? */
+    /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */
+    /*   soap->z_buflen = soap->bufidx; */
+    /* else */
+    soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx);
+    soap->d_stream.avail_in = soap->buflen - soap->bufidx;
+    soap->z_buflen = soap->buflen;
+    soap->buflen = soap->bufidx;
+    c = soap_getchar(soap);
+  }  
+#endif
+  if (c == '-' && soap_get0(soap) == '-')
+    soap->mode |= SOAP_ENC_MIME;
+  else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20)
+    soap->mode |= SOAP_ENC_DIME;
+  else
+  { while (soap_blank(c))
+      c = soap_getchar(soap);
+  }
+  if ((int)c == EOF)
+    return soap->error = SOAP_EOF;
+  soap_unget(soap, c);
+  if (c != '<' && !(soap->mode & (SOAP_ENC_DIME | SOAP_ENC_ZLIB)))
+  { soap->mode &= ~SOAP_IO;
+    if ((soap->error = soap->fparse(soap)))
+    { soap->keep_alive = 0; /* force close later */
+      return soap->error;
+    }
+    if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
+    { soap->chunkbuflen = soap->buflen;
+      soap->buflen = soap->bufidx;
+      soap->chunksize = 0;
+    }
+    else if (soap->fpreparerecv && soap->buflen != soap->bufidx)
+      soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx);
+#ifdef WITH_ZLIB
+    if (soap->zlib_in)
+    { /* fparse should not use soap_unget to push back last char */
+#ifdef WITH_GZIP
+      c = soap_get1(soap);
+      if (c == 0x1F)
+      { if (soap_getgziphdr(soap))
+          return soap->error;
+        if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK)
+          return soap->error = SOAP_ZLIB_ERROR;
+        soap->zlib_state = SOAP_ZLIB_INFLATE;
+        soap->z_crc = crc32(0L, NULL, 0);
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
+      }
+      else
+      { soap_revget1(soap);
+#else
+      {
+#endif
+        if (inflateInit(&soap->d_stream) != Z_OK)
+          return soap->error = SOAP_ZLIB_ERROR;
+        soap->zlib_state = SOAP_ZLIB_INFLATE;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n"));
+      }
+      soap->mode |= SOAP_ENC_ZLIB;
+      memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
+      soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx);
+      soap->d_stream.avail_in = soap->buflen - soap->bufidx;
+      soap->z_buflen = soap->buflen;
+      soap->buflen = soap->bufidx;
+    }
+#endif
+  }
+#ifndef WITH_LEANER
+  if (soap->mode & SOAP_ENC_MIME)
+  { if (soap_getmimehdr(soap))
+      return soap->error;
+    if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime"))
+      soap->mode |= SOAP_ENC_DIME;
+  }
+  if (soap->mode & SOAP_ENC_DIME)
+  { if (soap_getdimehdr(soap))
+      return soap->error;
+    if (soap->dime.flags & SOAP_DIME_CF)
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n"));
+      soap->dime.chunksize = soap->dime.size;
+      if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
+      { soap->dime.buflen = soap->buflen;
+        soap->buflen = soap->bufidx + soap->dime.chunksize;
+      }
+      else
+        soap->dime.chunksize -= soap->buflen - soap->bufidx;
+    }
+    soap->count = soap->buflen - soap->bufidx;
+  }
+#endif
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static int
+http_parse(struct soap *soap)
+{ char header[SOAP_HDRLEN], *s;
+  unsigned short g = 0, k;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for response...\n"));
+  *soap->endpoint = '\0';
+  soap->length = 0;
+  do
+  { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
+      return soap->error;
+    DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf));
+    for (;;)
+    { if (soap_getline(soap, header, SOAP_HDRLEN))
+        return soap->error;
+      if (!*header)
+        break;
+      DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header));
+      s = strchr(header, ':');
+      if (s)
+      { *s = '\0';
+        do s++;
+        while (*s && *s <= 32);
+        if ((soap->error = soap->fparsehdr(soap, header, s)))
+          return soap->error;
+      }
+    }
+    if ((s = strchr(soap->msgbuf, ' ')))
+      k = (unsigned short)soap_strtoul(s, NULL, 10);
+    else
+      k = 0;
+  } while (k == 100);
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing\n"));
+  s = strstr(soap->msgbuf, "HTTP/");
+  if (s && s[7] != '1')
+  { if (soap->keep_alive == 1)
+      soap->keep_alive = 0;
+    if (k == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* k == 0 for HTTP request */
+    { soap->imode |= SOAP_IO_CHUNK;
+      soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE;
+    }
+  }
+  if (soap->keep_alive < 0)
+    soap->keep_alive = 1;
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive));
+  if (s && (((g = !strncmp(soap->msgbuf, "GET ", 4))) || !strncmp(soap->msgbuf, "POST ", 5)))
+  { size_t m = strlen(soap->endpoint);
+    size_t n = m + (s - soap->msgbuf) - 5 - (!g);
+    if (n >= sizeof(soap->endpoint))
+      n = sizeof(soap->endpoint) - 1;
+    strncpy(soap->path, soap->msgbuf + 4 + (!g), n - m);
+    soap->path[n - m] = '\0';
+    strcat(soap->endpoint, soap->path);
+    DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint));
+    if (g)
+    { soap->error = soap->fget(soap);
+      if (soap->error == SOAP_OK)
+        soap->error = SOAP_STOP; /* prevents further processing */
+      return soap->error;
+    }
+    return SOAP_OK;
+  }
+  if (k == 0 || (k >= 200 && k <= 299) || k == 400 || k == 500)
+    return SOAP_OK;
+  return soap_set_receiver_error(soap, "HTTP error", soap->msgbuf, k);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static int
+http_parse_header(struct soap *soap, const char *key, const char *val)
+{ if (!soap_tag_cmp(key, "Host"))
+  { 
+#ifdef WITH_OPENSSL
+    if (soap->imode & SOAP_ENC_SSL)
+      strcpy(soap->endpoint, "https://");
+    else
+#endif
+      strcpy(soap->endpoint, "http://");
+    strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8);
+    soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
+  }
+#ifndef WITH_LEANER
+  else if (!soap_tag_cmp(key, "Content-Type"))
+  { if (soap_get_header_attribute(soap, val, "application/dime"))
+      soap->mode |= SOAP_ENC_DIME;
+    else if (soap_get_header_attribute(soap, val, "multipart/related"))
+    { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary"));
+      soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start"));
+      soap->mode |= SOAP_ENC_MIME;
+    }
+  }
+#endif
+  else if (!soap_tag_cmp(key, "Content-Length"))
+    soap->length = soap_strtoul(val, NULL, 10);
+  else if (!soap_tag_cmp(key, "Content-Encoding"))
+  { if (!soap_tag_cmp(val, "deflate"))
+#ifdef WITH_ZLIB
+      soap->zlib_in = SOAP_ZLIB_DEFLATE;
+#else
+      return SOAP_ZLIB_ERROR;
+#endif
+    else if (!soap_tag_cmp(val, "gzip"))
+#ifdef WITH_GZIP
+      soap->zlib_in = SOAP_ZLIB_GZIP;
+#else
+      return SOAP_ZLIB_ERROR;
+#endif
+  }
+#ifdef WITH_ZLIB
+  else if (!soap_tag_cmp(key, "Accept-Encoding"))
+  {
+#ifdef WITH_GZIP
+    if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip"))
+      soap->zlib_out = SOAP_ZLIB_GZIP;
+    else
+#endif
+    if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate"))
+      soap->zlib_out = SOAP_ZLIB_DEFLATE;
+    else
+      soap->zlib_out = SOAP_ZLIB_NONE;
+  }
+#endif
+  else if (!soap_tag_cmp(key, "Transfer-Encoding"))
+  { soap->mode &= ~SOAP_IO;
+    if (!soap_tag_cmp(val, "chunked"))
+      soap->mode |= SOAP_IO_CHUNK;
+  }
+  else if (!soap_tag_cmp(key, "Connection"))
+  { if (!soap_tag_cmp(val, "keep-alive"))
+      soap->keep_alive = -soap->keep_alive;
+    else if (!soap_tag_cmp(val, "close"))
+      soap->keep_alive = 0;
+  }
+#ifndef WITH_LEAN
+  else if (!soap_tag_cmp(key, "Authorization"))
+  { if (!soap_tag_cmp(val, "Basic *"))
+    { size_t n;
+      char *s;
+      soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n);
+      soap->tmpbuf[n] = '\0';
+      if ((s = strchr(soap->tmpbuf, ':')))
+      { *s = '\0';
+	soap->userid = soap_strdup(soap, soap->tmpbuf);
+	soap->passwd = soap_strdup(soap, s + 1);
+      }
+    }
+  }
+  else if (!soap_tag_cmp(key, "WWW-Authenticate"))
+    soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val+6, "realm"));
+  else if (!soap_tag_cmp(key, "Expect"))
+  { if (!soap_tag_cmp(val, "100-continue"))
+    { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL))
+       || (soap->error = soap->fposthdr(soap, NULL, NULL)))
+        return soap->error;
+    }
+  }
+#endif
+  else if (!soap_tag_cmp(key, "SOAPAction"))
+  { if (val[0] && val[1])
+    { soap->action = soap_strdup(soap, val + 1);
+      soap->action[strlen(soap->action) - 1] = '\0';
+    }
+  }
+  else if (!soap_tag_cmp(key, "Location"))
+  { strncpy(soap->endpoint, val, sizeof(soap->endpoint));
+    soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
+  }
+#ifdef WITH_COOKIES
+  else if (!soap_tag_cmp(key, "Cookie") || !soap_tag_cmp(key, "Set-Cookie"))
+    soap_getcookies(soap, val);
+#endif
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_get_header_attribute(struct soap *soap, const char *line, const char *key)
+{ register const char *s = line;
+  if (s)
+  { while (*s)
+    { register short flag;
+      s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s);
+      flag = soap_tag_cmp(soap->tmpbuf, key);
+      s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s);
+      if (!flag)
+        return soap->tmpbuf;
+    }
+  }
+  return NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_decode_key(char *buf, size_t len, const char *val)
+{ return soap_decode(buf, len, val, "=,;");
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_decode_val(char *buf, size_t len, const char *val)
+{ if (*val != '=')
+  { *buf = '\0';
+    return val;
+  }
+  return soap_decode(buf, len, val + 1, ",;");
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static const char*
+soap_decode(char *buf, size_t len, const char *val, const char *sep)
+{ const char *s;
+  char *t = buf;
+  for (s = val; *s; s++)
+    if (*s != ' ' && *s != '\t' && !strchr(sep, *s))
+      break;
+  if (*s == '"')
+  { s++;
+    while (*s && *s != '"' && --len)
+      *t++ = *s++;
+  }
+  else
+  { while (soap_notblank(*s) && !strchr(sep, *s) && --len)
+    { if (*s == '%')
+      { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4)
+              + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0');
+        s += 3;
+      }
+      else
+        *t++ = *s++;
+    }
+  }
+  *t = '\0';
+  while (*s && !strchr(sep, *s))
+    s++;
+  return s;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_envelope_begin_out(struct soap *soap)
+{
+#ifndef WITH_LEANER
+  size_t n = 0;
+  if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start)
+  { const char *s;
+    if (soap->mode & SOAP_ENC_DIME)
+      s = "application/dime";
+    else if (soap->version == 2)
+      s = "application/soap+xml; charset=utf-8";
+    else
+      s = "text/xml; charset=utf-8";
+    sprintf(soap->tmpbuf, "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start);
+    n = strlen(soap->tmpbuf);
+    if (soap_send_raw(soap, soap->tmpbuf, n))
+      return soap->error;
+  }
+  if (soap->mode & SOAP_IO_LENGTH)
+    soap->dime.size = soap->count;	/* DIME in MIME correction */
+  if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME))
+  { if (soap_putdimehdr(soap))
+      return soap->error;
+  }
+#endif
+  soap->part = SOAP_IN_ENVELOPE;
+  return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_envelope_end_out(struct soap *soap)
+{ if (soap_element_end_out(soap, "SOAP-ENV:Envelope"))
+    return soap->error;
+#ifndef WITH_LEANER
+  if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME))
+  { soap->dime.size = soap->count - soap->dime.size;	/* DIME in MIME correction */
+    sprintf(soap->id, soap->dime_id_format, 0);
+    soap->dime.id = soap->id;
+    if (soap->local_namespaces)
+    { if (soap->local_namespaces[0].out)
+        soap->dime.type = (char*)soap->local_namespaces[0].out;
+      else
+        soap->dime.type = (char*)soap->local_namespaces[0].ns;
+    }
+    soap->dime.options = NULL;
+    soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI;
+    if (!soap->dime.first)
+      soap->dime.flags |= SOAP_DIME_ME;
+    soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + ((strlen(soap->dime.type)+3)&(~3));
+  }
+  if (soap->mode & SOAP_ENC_DIME)
+    return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
+#endif
+  soap->part = SOAP_END_ENVELOPE;
+  return SOAP_OK;
+} 
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_envelope_begin_in(struct soap *soap)
+{ register struct Namespace *p;
+  soap->part = SOAP_IN_ENVELOPE;
+  if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0))
+    return soap->error = SOAP_VERSIONMISMATCH;
+  p = soap->local_namespaces;
+  if (p)
+  { const char *ns = p[0].out;
+    if (!ns)
+      ns = p[0].ns;
+    if (!strcmp(ns, soap_env1))
+    { soap->version = 1; /* make sure we use SOAP 1.1 */
+      if (p[1].out)
+        SOAP_FREE(p[1].out);
+      if ((p[1].out = (char*)SOAP_MALLOC(sizeof(soap_enc1))))
+        strcpy(p[1].out, soap_enc1);
+    }
+    else if (!strcmp(ns, soap_env2))
+    { soap->version = 2; /* make sure we use SOAP 1.2 */
+      if (p[1].out)
+        SOAP_FREE(p[1].out);
+      if ((p[1].out = (char*)SOAP_MALLOC(sizeof(soap_enc2))))
+        strcpy(p[1].out, soap_enc2);
+    }
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_envelope_end_in(struct soap *soap)
+{ if (soap_element_end_in(soap, "SOAP-ENV:Envelope"))
+    return soap->error;
+  soap->part = SOAP_END_ENVELOPE;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_body_begin_out(struct soap *soap)
+{ soap->part = SOAP_IN_BODY;
+  if (soap->version == 1)
+    soap->encoding = 1;
+  if (soap_element(soap, "SOAP-ENV:Body", 0, NULL))
+    return soap->error;
+  if ((soap->mode & SOAP_XML_SEC) && soap_attribute(soap, "id", "_0"))
+    return soap->error;
+  return soap_element_start_end_out(soap, NULL);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_body_end_out(struct soap *soap)
+{ if (soap_element_end_out(soap, "SOAP-ENV:Body"))
+    return soap->error;
+  soap->part = SOAP_IN_BODY;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_body_begin_in(struct soap *soap)
+{ soap->part = SOAP_IN_BODY;
+  return soap_element_begin_in(soap, "SOAP-ENV:Body", 0);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_body_end_in(struct soap *soap)
+{ if (soap_element_end_in(soap, "SOAP-ENV:Body"))
+    return soap->error;
+  soap->part = SOAP_END_BODY;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_recv_header(struct soap *soap)
+{ if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH)
+    soap->error = SOAP_OK;
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_endpoint(struct soap *soap, const char *endpoint)
+{ register const char *s;
+  register size_t i, n;
+  *soap->endpoint = '\0';
+  *soap->host = '\0';
+  *soap->path = '\0';
+  soap->port = 80;
+  if (!endpoint || !*endpoint)
+    return;
+#ifdef WITH_OPENSSL
+  if (!strncmp(endpoint, "https:", 6))
+    soap->port = 443;
+#endif
+  strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1);
+  s = strchr(endpoint, ':');
+  if (s && s[1] == '/' && s[2] == '/')
+    s += 3;
+  else
+    s = endpoint;
+  n = strlen(s);
+  if (n >= sizeof(soap->host))
+    n = sizeof(soap->host) - 1;
+/* WR[ */
+#ifdef WITH_IPV6
+  if ('[' == s[0])
+  { s++;
+    for (i = 0; i < n; i++)
+    { soap->host[i] = s[i];
+      if (']' == s[i])
+      {
+        s++;
+        break; 
+      }
+    }
+  }
+  else
+  { for (i = 0; i < n; i++)
+    { soap->host[i] = s[i];
+      if (s[i] == '/' || s[i] == ':')
+        break; 
+    }
+  }
+#else /* WITH_IPV6 */
+/* ]WR */
+  for (i = 0; i < n; i++)
+  { soap->host[i] = s[i];
+    if (s[i] == '/' || s[i] == ':')
+      break; 
+  }
+/* WR[ */
+#endif /* WITH_IPV6 */
+/* ]WR */
+  soap->host[i] = '\0';
+  if (s[i] == ':')
+  { soap->port = (int)atol(s + i + 1);
+    for (i++; i < n; i++)
+      if (s[i] == '/')
+        break;
+  }
+  if (s[i])
+  { strncpy(soap->path, s + i + 1, sizeof(soap->path));
+    soap->path[sizeof(soap->path) - 1] = '\0';
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_connect(struct soap *soap, const char *endpoint, const char *action)
+{ return soap_connect_command(soap, SOAP_POST, endpoint, action);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action)
+{ char host[sizeof(soap->host)];
+  int port;
+  size_t count;
+  soap->error = SOAP_OK;
+  strcpy(host, soap->host); /* save to compare */
+  port = soap->port; /* save to compare */
+  soap_set_endpoint(soap, endpoint);
+  if (action)
+    soap->action = soap_strdup(soap, action);
+  if (soap->fconnect)
+    if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port)))
+      return soap->error;
+  if (*soap->host)
+  { soap->status = http_command;
+    if (!soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port)
+    { soap->keep_alive = 0; /* force close */
+      soap_closesock(soap);
+      DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port));
+      soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port);
+      if (soap->error)
+        return soap->error;
+      soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0);
+    }
+    else if (!soap->keep_alive || !soap->fpoll || soap->fpoll(soap))
+    { soap->keep_alive = 0; /* force close */
+      soap_closesock(soap);
+      DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port));
+      soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port);
+      if (soap->error)
+        return soap->error;
+    }
+  }
+  if (soap_begin_send(soap))
+    return soap->error;
+  count = soap_count_attachments(soap);
+  if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint)
+  { unsigned int k = soap->mode;
+    soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
+    if ((k & SOAP_IO) != SOAP_IO_FLUSH)
+      soap->mode |= SOAP_IO_BUFFER;
+    if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count)))
+      return soap->error;
+    if ((k & SOAP_IO) == SOAP_IO_CHUNK)
+    { if (soap_flush(soap))
+        return soap->error;
+    }
+    soap->mode = k;
+  }
+  if (http_command != SOAP_POST)
+    return soap_end_send(soap);
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+char*
+SOAP_FMAC2
+soap_s2base64(struct soap *soap, const unsigned char *s, char *t, size_t n)
+{ register size_t i;
+  register unsigned long m;
+  register char *p;
+  if (!t)
+    t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1);
+  if (!t)
+  { soap->error = SOAP_EOM;
+    return NULL;
+  }
+  p = t;
+  t[0] = '\0';
+  if (!s)
+    return p;
+  for (; n > 2; n -= 3, s += 3)
+  { m = s[0];
+    m = (m << 8) | s[1];
+    m = (m << 8) | s[2];
+    for (i = 4; i > 0; m >>= 6)
+      t[--i] = soap_base64o[m & 0x3F];
+    t += 4;
+  }
+  t[0] = '\0';
+  if (n > 0)
+  { m = 0;
+    for (i = 0; i < n; i++)
+      m = (m << 8) | *s++;
+    for (; i < 3; i++)
+      m <<= 8;
+    for (i++; i > 0; m >>= 6)
+      t[--i] = soap_base64o[m & 0x3F];
+    for (i = 3; i > n; i--)
+      t[i] = '=';
+    t[4] = '\0';
+  }
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_base642s(struct soap *soap, const char *s, char *t, size_t l, size_t *n)
+{ register int i, j, c;
+  register unsigned long m;
+  char *p = t;
+  if (n)
+    *n = 0;
+  for (;;)
+  { for (i = 0; i < SOAP_BLKLEN; i++)
+    { m = 0;
+      j = 0;
+      while (j < 4)
+      { c = *s++;
+        if (c == '=' || !c)
+        { i *= 3;
+          switch (j)
+          { case 2:
+              *t++ = (char)((m >> 4) & 0xFF);
+              i++;
+              break;
+            case 3:
+              *t++ = (char)((m >> 10) & 0xFF);
+              *t++ = (char)((m >> 2) & 0xFF);
+              i += 2;
+          }
+          if (n)
+	    *n += i;
+          return p;
+        }
+        c -= '+';
+        if (c >= 0 && c <= 79)
+        { m = (m << 6) + soap_base64i[c];
+          j++;
+        }
+      }
+      *t++ = (char)((m >> 16) & 0xFF);
+      *t++ = (char)((m >> 8) & 0xFF);
+      *t++ = (char)(m & 0xFF);
+      if (l < 3)
+      { if (n)
+	  *n += i;
+        return p;
+      }
+      l -= 3;
+    }
+    if (n)
+      *n += 3 * SOAP_BLKLEN;
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_puthttphdr(struct soap *soap, int status, size_t count)
+{ register const char *s;
+  register int err;
+  if (status == SOAP_FILE)
+    s = soap->http_content;
+  else if (status == SOAP_HTML)
+    s = "text/html; charset=utf-8";
+#ifndef WITH_LEANER
+  else if (soap->mode & SOAP_ENC_DIME)
+    s = "application/dime";
+#endif
+  else if (soap->version == 2)
+    s = "application/soap+xml; charset=utf-8";
+  else
+    s = "text/xml; charset=utf-8";
+#ifndef WITH_LEANER
+  if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start && soap->status != SOAP_GET)
+  { sprintf(soap->tmpbuf, "multipart/related; boundary=\"%s\"; type=%s; start=\"%s\"", soap->mime.boundary, s, soap->mime.start);
+    s = soap->tmpbuf;
+  }
+#endif
+  if ((err = soap->fposthdr(soap, "Content-Type", s)))
+    return err;
+#ifdef WITH_ZLIB
+  if (soap->omode & SOAP_ENC_ZLIB)
+  {
+#ifdef WITH_GZIP
+    err = soap->fposthdr(soap, "Content-Encoding", "gzip");
+#else
+    err = soap->fposthdr(soap, "Content-Encoding", "deflate");
+#endif
+    if (err)
+      return err;
+  }
+#endif
+  if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)
+    err = soap->fposthdr(soap, "Transfer-Encoding", "chunked");
+  else if (count > 0)
+  { sprintf(soap->tmpbuf, "%lu", (unsigned long)count);
+    err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf);
+  }
+  if (err)
+    return err;
+  return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close");
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static int
+http_get(struct soap *soap)
+{ return SOAP_GET_METHOD;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static int
+http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count)
+{ register const char *s;
+  register int err;
+  if (soap->status == SOAP_GET)
+  { s = "GET";
+    count = 0;
+  }
+  else
+    s = "POST";
+#ifdef PALM
+  if (!endpoint || (strncmp(endpoint, "http:", 5) && strncmp(endpoint, "https:", 6) && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8))
+#else
+  if (!endpoint || (strncmp(endpoint, "http:", 5) && strncmp(endpoint, "https:", 6) && strncmp(endpoint, "httpg:", 6)))
+#endif
+    return SOAP_OK;
+  if (soap->proxy_host && strncmp(endpoint, "https:", 6))
+    sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version);
+  else
+    sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, path, soap->http_version);
+  if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
+    return err;
+  if (port != 80)
+    sprintf(soap->tmpbuf, "%s:%d", host, port);
+  else
+    strcpy(soap->tmpbuf, host); 
+  if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf))
+   || (err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.7"))
+   || (err = soap_puthttphdr(soap, SOAP_OK, count)))
+    return err;
+#ifdef WITH_ZLIB
+#ifdef WITH_GZIP
+  if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate")))
+#else
+  if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate")))
+#endif
+    return err;
+#endif
+#ifndef WITH_LEAN
+  if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761)
+  { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd);
+    strcpy(soap->tmpbuf, "Basic ");
+    soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262));
+    if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf)))
+      return err;
+  }
+  if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
+  { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
+    strcpy(soap->tmpbuf, "Basic ");
+    soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262));
+    if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
+      return err;
+  }
+#endif
+#ifdef WITH_COOKIES
+#ifdef WITH_OPENSSL
+  if (soap_putcookies(soap, host, path, soap->ssl != NULL))
+    return soap->error;
+#else
+  if (soap_putcookies(soap, host, path, 0))
+    return soap->error;
+#endif
+#endif
+  if (action && soap->version == 1)
+  { sprintf(soap->tmpbuf, "\"%s\"", action);
+    if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf)))
+      return err;
+  }
+  return soap->fposthdr(soap, NULL, NULL);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static int
+http_send_header(struct soap *soap, const char *s)
+{ register const char *t;
+  do
+  { t = strchr(s, '\n'); /* disallow \n in HTTP headers */
+    if (!t)
+      t = s + strlen(s);
+    if (soap_send_raw(soap, s, t - s))
+      return soap->error;
+    s = t + 1;
+  } while (*t);
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static int
+http_post_header(struct soap *soap, const char *key, const char *val)
+{ if (key)
+  { if (http_send_header(soap, key))
+      return soap->error;
+    if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val)))
+      return soap->error;
+  }
+  return soap_send_raw(soap, "\r\n", 2);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static int
+http_response(struct soap *soap, int status, size_t count)
+{ register int err;
+/* WR[ */
+#ifdef WMW_RPM_IO
+  if (soap->rpmreqid)
+    httpOutputEnable(soap->rpmreqid);
+#endif  /* WMW_RPM_IO */
+/* ]WR */
+  if (!status || status == SOAP_HTML || status == SOAP_FILE)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "OK 200\n"));
+/* WR[ */
+#ifdef WMW_RPM_IO
+    if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
+#else
+/* ]WR */
+    if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */
+/* WR[ */
+#endif /* WMW_RPM_IO */
+/* ]WR */
+    { sprintf(soap->tmpbuf, "HTTP/%s 200 OK", soap->http_version);
+      if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
+        return err;
+    }
+    else if ((err = soap->fposthdr(soap, "Status", "200 OK")))
+      return err;
+  }
+  else if (status > 200 && status < 600)
+  { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status));
+    if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
+      return err;
+    if (status == 401)
+    { sprintf(soap->tmpbuf, "Basic realm=\"%s\"", soap->authrealm ? soap->authrealm : "gSOAP Web Service");
+      if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf)))
+        return err;
+    }
+    else if ((status >= 301 && status <= 303) || status == 307)
+    { if ((err = soap->fposthdr(soap, "Location", soap->endpoint)))
+        return err;
+    }
+  }
+  else
+  { const char *s = *soap_faultcode(soap);
+    if (soap->version == 2 && !strcmp(s, "SOAP-ENV:Sender"))
+      s = "400 Bad Request";
+    else
+      s = "500 Internal Server Error";
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status));
+/* WR[ */
+#ifdef WMW_RPM_IO
+    if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
+#else
+/* ]WR */
+    if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */
+/* WR[ */
+#endif /* WMW_RPM_IO */
+/* ]WR */
+    { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s);
+      if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
+        return err;
+    }
+    else if ((err = soap->fposthdr(soap, "Status", s)))
+      return err;
+  }
+  if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.7"))
+   || (err = soap_puthttphdr(soap, status, count)))
+    return err;
+#ifdef WITH_COOKIES
+  if (soap_putsetcookies(soap))
+    return soap->error;
+#endif
+  return soap->fposthdr(soap, NULL, NULL);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_response(struct soap *soap, int status)
+{ register size_t count;
+  if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */))
+   && (status == SOAP_HTML || status == SOAP_FILE))
+  { soap->omode &= ~SOAP_IO;
+    soap->omode |= SOAP_IO_STORE;
+  }
+  soap->status = status;
+  count = soap_count_attachments(soap);
+  if (soap_begin_send(soap))
+    return soap->error;
+  if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML))
+  { register int n = soap->mode;
+    soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
+    if ((n & SOAP_IO) != SOAP_IO_FLUSH)
+      soap->mode |= SOAP_IO_BUFFER;
+    if ((soap->error = soap->fresponse(soap, status, count)))
+      return soap->error;
+    if ((n & SOAP_IO) == SOAP_IO_CHUNK)
+    { if (soap_flush(soap))
+        return soap->error;
+    }
+    soap->mode = n;
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+static const char*
+soap_set_validation_fault(struct soap *soap, const char *s, const char *t)
+{ sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element <%s>", s, t?t:SOAP_STR_EOS, soap->tag);
+  return soap->msgbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_fault(struct soap *soap)
+{ const char **c = soap_faultcode(soap);
+  const char **s = soap_faultstring(soap);
+  if (!*c)
+  { if (soap->version == 2)
+      *c = "SOAP-ENV:Sender";
+    else
+      *c = "SOAP-ENV:Client";
+  }
+  if (*s)
+    return;
+  switch (soap->error)
+  {
+#ifndef WITH_LEAN
+    case SOAP_CLI_FAULT:
+      *s = "Client fault";
+      break;
+    case SOAP_SVR_FAULT:
+      *s = "Server fault";
+      break;
+    case SOAP_TAG_MISMATCH:
+      *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL);
+      break;
+    case SOAP_TAG_END:
+      *s = soap_set_validation_fault(soap, "incorrect end tag", NULL);
+      break;
+    case SOAP_TYPE:
+      *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type);
+      break;
+    case SOAP_SYNTAX_ERROR:
+      *s = "Well-formedness constraint violation";
+      break;
+    case SOAP_NO_TAG:
+      *s = "No XML element tag found";
+      break;
+    case SOAP_MUSTUNDERSTAND:
+      *c = "SOAP-ENV:MustUnderstand";
+      sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag);
+      *s = soap->msgbuf;
+      break;
+    case SOAP_VERSIONMISMATCH:
+      *c = "SOAP-ENV:VersionMismatch";
+      *s = "SOAP version mismatch or invalid SOAP message";
+      break;
+    case SOAP_DATAENCODINGUNKNOWN:
+      *c = "SOAP-ENV:DataEncodingUnknown";
+      *s = "Unsupported SOAP data encoding";
+      break;
+    case SOAP_NAMESPACE:
+      *s = soap_set_validation_fault(soap, "namespace mismatch", NULL);
+      break;
+    case SOAP_FATAL_ERROR:
+      *s = "Fatal error";
+      break;
+    case SOAP_NO_METHOD:
+      sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag);
+      *s = soap->msgbuf;
+      break;
+    case SOAP_GET_METHOD:
+      *s = "HTTP GET method not implemented";
+      break;
+    case SOAP_EOM:
+      *s = "Out of memory";
+      break;
+    case SOAP_IOB:
+      *s = "Array index out of bounds";
+      break;
+    case SOAP_NULL:
+      *s = soap_set_validation_fault(soap, "nil not allowed", NULL);
+      break;
+    case SOAP_MULTI_ID:
+      *s = soap_set_validation_fault(soap, "multiple definitions of id ", soap->id);
+      break;
+    case SOAP_MISSING_ID:
+      *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id);
+      break;
+    case SOAP_HREF:
+      *s = soap_set_validation_fault(soap, "incompatible object ref ", soap->id);
+      break;
+    case SOAP_FAULT:
+      break;
+    case SOAP_TCP_ERROR:
+      *s = tcp_error(soap);
+      break;
+    case SOAP_HTTP_ERROR:
+      *s = "HTTP error";
+      break;
+    case SOAP_SSL_ERROR:
+      *s = "SSL error";
+      break;
+    case SOAP_PLUGIN_ERROR:
+      *s = "Plugin registry error";
+      break;
+    case SOAP_DIME_MISMATCH:
+      *s = "DIME version/transmission error";
+      break;
+    case SOAP_DIME_END:
+      *s = "End of DIME error";
+      break;
+    case SOAP_DIME_ERROR:
+      *s = "DIME format error";
+      break;
+    case SOAP_MIME_ERROR:
+      *s = "MIME format error";
+      break;
+    case SOAP_ZLIB_ERROR:
+#ifdef WITH_ZLIB
+      sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream.msg?soap->d_stream.msg:"");
+      *s = soap->msgbuf;
+#else
+      *s = "Zlib not installed for required message (de)compression";
+#endif
+      break;
+    case SOAP_REQUIRED:
+      *s = soap_set_validation_fault(soap, "missing required attribute", NULL);
+      break;
+    case SOAP_PROHIBITED:
+      *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL);
+      break;
+    case SOAP_OCCURS:
+      *s = soap_set_validation_fault(soap, "a min/maxOccurs violation was detected", NULL);
+      break;
+    case SOAP_LENGTH:
+      *s = soap_set_validation_fault(soap, "content length violation", NULL);
+      break;
+#endif
+    case SOAP_EOF:
+      sprintf(soap->msgbuf, "End of file or no input: '%s'", soap_strerror(soap));
+      *s = soap->msgbuf;
+      break;
+    default:
+      if (soap->error > 200 && soap->error < 600)
+      { sprintf(soap->msgbuf, "HTTP Error: '%s'", http_error(soap, soap->error));
+        *s = soap->msgbuf;
+      }
+      else
+      { sprintf(soap->msgbuf, "Error code %d", soap->error);
+        *s = soap->msgbuf;
+      }
+    }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_send_fault(struct soap *soap)
+{ register int status = soap->error;
+  if (status == SOAP_STOP)
+    return status;
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error));
+  soap->keep_alive = 0; /* to terminate connection */
+  soap_set_fault(soap);
+  if ((status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) && (!soap->fpoll || soap->fpoll(soap) == SOAP_OK))
+  { soap->error = SOAP_OK;
+    soap_serializeheader(soap);
+    soap_serializefault(soap);
+    soap_begin_count(soap);
+    if (soap->mode & SOAP_IO_LENGTH)
+    { soap_envelope_begin_out(soap);
+      soap_putheader(soap);
+      soap_body_begin_out(soap);
+      soap_putfault(soap);
+      soap_body_end_out(soap);
+      soap_envelope_end_out(soap);
+    }
+    if (soap_response(soap, status)
+     || soap_envelope_begin_out(soap)
+     || soap_putheader(soap)
+     || soap_body_begin_out(soap)
+     || soap_putfault(soap)
+     || soap_body_end_out(soap)
+     || soap_envelope_end_out(soap))
+      return soap_closesock(soap);
+    soap_end_send(soap);
+  }
+  soap->error = status;
+  return soap_closesock(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_recv_fault(struct soap *soap)
+{ register int status = soap->error;
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Receiving SOAP Fault\n"));
+  soap->error = SOAP_OK;
+  if (soap_getfault(soap))
+  { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n"));
+    *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client");
+    soap->error = status;
+    soap_set_fault(soap);
+  }
+  else
+  { register const char *s = *soap_faultcode(soap);
+    if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver"))
+      status = SOAP_SVR_FAULT; 
+    else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender"))
+      status = SOAP_CLI_FAULT;
+    else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand"))
+      status = SOAP_MUSTUNDERSTAND;
+    else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch"))
+      status = SOAP_VERSIONMISMATCH;
+    else
+    { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Fault code %s\n", s));
+      status = SOAP_FAULT;
+    }
+    if (soap_body_end_in(soap)
+     || soap_envelope_end_in(soap)
+     || soap_end_recv(soap))
+      return soap_closesock(soap);
+    soap->error = status;
+  }
+  return soap_closesock(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static const char*
+soap_strerror(struct soap *soap)
+{ int err = soap->errnum;
+  if (!err)
+    err = soap_errno;
+  if (err)
+  {
+#ifndef UNDER_CE
+    return strerror(err);
+#else
+    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)&soap->werrorstr, sizeof(soap->werrorstr), NULL);
+    wcstombs(soap->errorstr, soap->werrorstr, sizeof(soap->errorstr));
+    return soap->errorstr;
+#endif
+  }
+  return "Operation interrupted or timed out";
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+static int
+soap_set_error(struct soap *soap, const char *faultcode, const char *faultstring, const char *faultdetail, int soaperror)
+{ *soap_faultcode(soap) = faultcode;
+  *soap_faultstring(soap) = faultstring;
+  if (faultdetail && *faultdetail)
+  { register const char **s = soap_faultdetail(soap);
+    if (s)
+      *s = faultdetail;
+  }
+  return soap->error = soaperror;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror)
+{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultstring, faultdetail, soaperror);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror)
+{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultstring, faultdetail, soaperror);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+static int
+soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultstring, const char *faultdetail)
+{ char *s = NULL, *t = NULL;
+  if (faultstring)
+    s = soap_strdup(soap, faultstring);
+  if (faultdetail)
+    t = soap_strdup(soap, faultdetail);
+  return soap_set_error(soap, faultcode, s, t, SOAP_FAULT);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetail)
+{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultstring, faultdetail);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetail)
+{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultstring, faultdetail);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_print_fault(struct soap *soap, FILE *fd)
+{ if (soap->error)
+  { const char **s;
+    if (!*soap_faultcode(soap))
+      soap_set_fault(soap);
+    fprintf(fd, "SOAP FAULT: %s\n\"%s\"\n", *soap_faultcode(soap), *soap_faultstring(soap));
+    s = soap_faultdetail(soap);
+    if (s && *s)
+      fprintf(fd, "Detail: %s\n", *s);
+  }
+}
+#endif
+ 
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_print_fault_location(struct soap *soap, FILE *fd)
+{ 
+#ifndef WITH_LEAN
+  int c;
+  if (soap->error && soap->buflen > 0)
+  { if (soap->bufidx == 0)
+      soap->bufidx = 1;
+    c = soap->buf[soap->bufidx - 1];
+    soap->buf[soap->bufidx - 1] = '\0';
+    if (soap->buflen - soap->bufidx > 1024)
+      soap->buf[soap->bufidx + 1024] = '\0';
+    else
+      soap->buf[soap->buflen - 1] = '\0';
+    fprintf(fd, "%s%c\n** HERE **\n", soap->buf, c);
+    if (soap->bufidx < soap->buflen)
+      fprintf(fd, "%s\n", soap->buf + soap->bufidx);
+  }
+#endif
+}
+#endif
+ 
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg)
+{ register struct soap_plugin *p;
+  register int r;
+  if (!(p = (struct soap_plugin*)SOAP_MALLOC(sizeof(struct soap_plugin))))
+    return soap->error = SOAP_EOM;
+  p->id = NULL;
+  p->data = NULL;
+  p->fcopy = NULL;
+  p->fdelete = NULL;
+  r = fcreate(soap, p, arg);
+  if (!r && p->fdelete)
+  { p->next = soap->plugins;
+    soap->plugins = p;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id));
+    return SOAP_OK;
+  }
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id?p->id:"?", r));
+  SOAP_FREE(p);
+  return r;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static void *
+fplugin(struct soap *soap, const char *id)
+{ register struct soap_plugin *p;
+  for (p = soap->plugins; p; p = p->next)
+    if (p->id == id || !strcmp(p->id, id))
+      return p->data;
+  return NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void *
+SOAP_FMAC2
+soap_lookup_plugin(struct soap *soap, const char *id)
+{ return soap->fplugin(soap, id);
+}
+#endif
+
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/stdsoap2.h
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/stdsoap2.h	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/stdsoap2.h	(revision 21994)
@@ -0,0 +1,1764 @@
+/*
+
+stdsoap2.h 2.7.0d
+
+gSOAP runtime environment.
+
+gSOAP XML Web services tools
+Copyright (C) 2000-2004, Robert van Engelen, Genivia, Inc., All Rights Reserved.
+
+Contributors:
+
+Wind River Systems, Inc., for the following additions (marked WR[...]) :
+  - vxWorks compatible
+  - Support for IPv6.
+
+--------------------------------------------------------------------------------
+gSOAP public license.
+
+The contents of this file are subject to the gSOAP Public License Version 1.3
+(the "License"); you may not use this file except in compliance with the
+License. You may obtain a copy of the License at
+http://www.cs.fsu.edu/~engelen/soaplicense.html
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+for the specific language governing rights and limitations under the License.
+
+The Initial Developer of the Original Code is Robert A. van Engelen.
+Copyright (C) 2000-2004, Robert van Engelen, Genivia, Inc., All Rights Reserved.
+--------------------------------------------------------------------------------
+GPL license.
+
+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.
+
+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
+
+Author contact information:
+engelen@genivia.com / engelen@acm.org
+--------------------------------------------------------------------------------
+*/
+
+#ifdef WITH_SOAPDEFS_H
+# include "soapdefs.h"		/* include user-defined stuff */
+#endif
+
+#ifndef _THREAD_SAFE
+# define _THREAD_SAFE
+#endif
+
+#ifndef OPENSERVER
+# ifndef _REENTRANT
+#  define _REENTRANT
+# endif
+#endif
+
+#ifndef SOAP_BEGIN_NAMESPACE
+# define SOAP_BEGIN_NAMESPACE(name)
+#endif
+
+#ifndef SOAP_END_NAMESPACE
+# define SOAP_END_NAMESPACE(name)
+#endif
+
+#ifndef SOAP_FMAC1	/* stdsoap2.h declaration macro */
+# define SOAP_FMAC1
+#endif
+
+#ifndef SOAP_FMAC2	/* stdsoap2.h declaration macro */
+# define SOAP_FMAC2
+#endif
+
+#ifndef SOAP_FMAC3	/* (de)serializer declaration macro */
+# define SOAP_FMAC3
+#endif
+
+#ifndef SOAP_FMAC4	/* (de)serializer declaration macro */
+# define SOAP_FMAC4
+#endif
+
+#ifndef SOAP_FMAC5	/* stub/skeleton declaration macro */
+# define SOAP_FMAC5
+#endif
+
+#ifndef SOAP_FMAC6	/* stub/skeleton declaration macro */
+# define SOAP_FMAC6
+#endif
+
+#ifndef SOAP_CMAC	/* class declaration macro */
+# define SOAP_CMAC
+#endif
+
+#ifndef SOAP_NMAC	/* namespace table declaration macro */
+# define SOAP_NMAC
+#endif
+
+#ifndef SOAP_SOURCE_STAMP
+# define SOAP_SOURCE_STAMP(str)
+#endif
+
+#ifdef WITH_LEANER
+# ifndef WITH_LEAN
+#  define WITH_LEAN
+# endif
+#endif
+
+#ifdef WITH_LEAN
+# ifdef WITH_COOKIES
+#  error "Cannot build WITH_LEAN code WITH_COOKIES enabled"
+# endif
+#endif
+
+#ifndef STDSOAP_H
+#define STDSOAP_H
+
+#if defined(__vxworks) || defined(__VXWORKS__)
+# define VXWORKS
+#endif
+
+#ifdef _WIN32
+# ifndef WIN32
+#  define WIN32
+# endif
+#endif
+
+#ifdef UNDER_CE
+# ifndef WIN32
+#  define WIN32
+# endif
+#endif
+
+#ifdef __BORLANDC__
+# ifdef __WIN32__
+#  ifndef WIN32
+#   define WIN32
+#  endif
+# endif
+#endif
+
+#ifdef __CYGWIN__
+# ifndef CYGWIN
+#  define CYGWIN
+# endif
+#endif
+
+#ifdef __SYMBIAN32__ 
+# define SYMBIAN
+# undef WIN32
+#endif
+
+#if defined(__palmos__) || defined(PALM_GCC) || defined(__PALMOS_TRAPS__)
+# define PALM
+#endif
+
+#ifdef __hpux
+# define HP_UX
+#endif
+
+#ifdef __alpha
+# define TRU64 
+#endif
+
+#ifdef __MVS__
+# define OS390
+#endif
+
+#ifdef _AIX
+# define __socklen_t_defined
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#else
+# if defined(UNDER_CE)
+#  define WITH_LEAN
+#  define HAVE_SSCANF
+# elif defined(WIN32)
+#  define HAVE_STRRCHR
+#  define HAVE_STRTOD
+#  define HAVE_SSCANF
+#  define HAVE_STRTOL
+#  define HAVE_STRTOUL
+#  define HAVE_SYS_TIMEB_H
+#  define HAVE_FTIME
+#  define HAVE_WCTOMB
+#  define HAVE_MBTOWC
+# elif defined(CYGWIN)
+#  define HAVE_STRRCHR
+#  define HAVE_STRTOD
+#  define HAVE_SSCANF
+#  define HAVE_STRTOL
+#  define HAVE_STRTOUL
+#  define HAVE_SYS_TIMEB_H
+#  define HAVE_FTIME
+#  define HAVE_RAND_R
+#  define HAVE_GMTIME_R
+#  define HAVE_LOCALTIME_R
+#  define HAVE_WCTOMB
+#  define HAVE_MBTOWC
+# elif defined(__APPLE__)
+#  define HAVE_STRRCHR
+#  define HAVE_STRTOD
+#  define HAVE_SSCANF
+#  define HAVE_STRTOL
+#  define HAVE_STRTOUL
+#  define HAVE_RAND_R
+#  define HAVE_GMTIME_R
+#  define HAVE_LOCALTIME_R
+#  define HAVE_TIMEGM
+#  define HAVE_WCTOMB
+#  define HAVE_MBTOWC
+# elif defined(_AIXVERSION_431)
+#  define HAVE_STRRCHR
+#  define HAVE_STRTOD
+#  define HAVE_SSCANF
+#  define HAVE_STRTOL
+#  define HAVE_STRTOUL
+#  define HAVE_SYS_TIMEB_H
+#  define HAVE_FTIME
+#  define HAVE_RAND_R
+#  define HAVE_GMTIME_R
+#  define HAVE_LOCALTIME_R
+#  define HAVE_WCTOMB
+#  define HAVE_MBTOWC
+# elif defined(HP_UX)
+#  define HAVE_STRRCHR
+#  define HAVE_STRTOD
+#  define HAVE_SSCANF
+#  define HAVE_STRTOL
+#  define HAVE_STRTOUL
+#  define HAVE_SYS_TIMEB_H
+#  define HAVE_FTIME
+#  define HAVE_RAND_R
+#  define HAVE_GMTIME_R
+#  define HAVE_LOCALTIME_R
+#  define HAVE_WCTOMB
+#  define HAVE_MBTOWC
+# elif defined(FREEBSD)
+#  define HAVE_STRRCHR
+#  define HAVE_STRTOD
+#  define HAVE_SSCANF
+#  define HAVE_STRTOL
+#  define HAVE_STRTOUL
+#  define HAVE_GETTIMEOFDAY
+#  define HAVE_RAND_R
+#  define HAVE_GMTIME_R
+#  define HAVE_LOCALTIME_R
+#  define HAVE_WCTOMB
+#  define HAVE_MBTOWC
+# elif defined(__VMS)
+#  define HAVE_STRRCHR
+#  define HAVE_STRTOD
+#  define HAVE_SSCANF
+#  define HAVE_STRTOL
+#  define HAVE_STRTOUL
+#  define HAVE_SYS_TIMEB_H
+#  define HAVE_FTIME
+#  define HAVE_RAND_R
+#  define HAVE_GMTIME_R
+#  define HAVE_LOCALTIME_R
+#  define HAVE_WCTOMB
+#  define HAVE_MBTOWC
+# elif defined(__GLIBC__)
+#  define HAVE_STRRCHR
+#  define HAVE_STRTOD
+#  define HAVE_SSCANF
+#  define HAVE_STRTOL
+#  define HAVE_STRTOUL
+#  define HAVE_SYS_TIMEB_H
+#  define HAVE_FTIME
+#  define HAVE_RAND_R
+#  define HAVE_GMTIME_R
+#  define HAVE_LOCALTIME_R
+#  define HAVE_TIMEGM
+#  define HAVE_WCTOMB
+#  define HAVE_MBTOWC
+#  define HAVE_ISNAN
+# elif defined(TRU64)
+#  define HAVE_STRRCHR
+#  define HAVE_STRTOD
+#  define HAVE_SSCANF
+#  define HAVE_STRTOL
+#  define HAVE_STRTOUL
+#  define HAVE_GETTIMEOFDAY
+#  define HAVE_SYS_TIMEB_H
+#  define HAVE_RAND_R
+#  define HAVE_GMTIME_R
+#  define HAVE_LOCALTIME_R
+#  define __USE_STD_IOSTREAM
+#  define HAVE_WCTOMB
+#  define HAVE_MBTOWC
+# elif defined(MAC_CARBON)
+#  define HAVE_STRRCHR
+#  define HAVE_STRTOD
+#  define HAVE_SSCANF
+#  define HAVE_STRTOL
+#  define HAVE_STRTOUL
+#  define HAVE_FTIME
+#  define HAVE_RAND_R
+#  define HAVE_GETHOSTBYNAME_R
+#  define HAVE_GMTIME_R
+#  define HAVE_LOCALTIME_R
+#  define HAVE_WCTOMB
+#  define HAVE_MBTOWC
+# elif defined(PALM)
+#  define WITH_LEAN
+#  define HAVE_STRTOD   /* strtod() is defined in palmFunctions.h */
+#  include <stdlib.h>	/* Needs to be included before unix headers */
+#  include <sys_types.h>
+#  define IGNORE_STDIO_STUBS
+#  include <StdIOPalm.h>
+#  define O_NONBLOCK FNONBIO
+#  include <sys_socket.h>
+#  include <time.h>
+#  include "palmFunctions.h"
+# elif defined(SYMBIAN)
+#  define WITH_LEAN
+#  define WITH_NONAMESPACES
+#  define HAVE_STRTOD	/* use STRTOD since sscanf doesn't seem to work */
+#  include <sys/ioctl.h>
+# elif defined(VXWORKS)
+#  define HAVE_STRRCHR
+#  define HAVE_STRTOD
+#  define HAVE_SSCANF
+#  define HAVE_STRTOL
+#  define HAVE_STRTOUL
+#  define HAVE_RAND_R
+#  define HAVE_PGMTIME_R
+#  define HAVE_PLOCALTIME_R
+#  define HAVE_MKTIME
+# elif defined(OS390)
+#  define HAVE_STRRCHR
+#  define HAVE_STRTOD
+#  define HAVE_SSCANF
+#  define HAVE_STRTOL
+#  define HAVE_STRTOUL
+#  define HAVE_SYS_TIMEB_H
+#  define HAVE_FTIME
+#  define HAVE_RAND_R
+#  define HAVE_GMTIME_R
+#  define HAVE_LOCALTIME_R
+#  define HAVE_WCTOMB
+#  define HAVE_MB
+# else
+/* Default asumptions on supported functions */
+#  define HAVE_STRRCHR
+#  define HAVE_STRTOD
+#  define HAVE_SSCANF
+#  define HAVE_STRTOL
+#  define HAVE_STRTOUL
+#  define HAVE_SYS_TIMEB_H
+#  define HAVE_FTIME
+#  define HAVE_RAND_R
+#  define HAVE_GETHOSTBYNAME_R
+#  define HAVE_GMTIME_R
+#  define HAVE_LOCALTIME_R
+#  define HAVE_WCTOMB
+#  define HAVE_MBTOWC
+# endif
+#endif
+
+#if defined(TRU64)
+# define SOAP_LONG_FORMAT "%ld"
+# define SOAP_ULONG_FORMAT "%lu"
+#elif defined(WIN32)
+# define SOAP_LONG_FORMAT "%I64d"
+# define SOAP_ULONG_FORMAT "%I64u"
+#endif
+
+#ifndef SOAP_LONG_FORMAT
+# define SOAP_LONG_FORMAT "%lld"	/* printf format for 64 bit ints */
+#endif
+
+#ifndef SOAP_ULONG_FORMAT
+# define SOAP_ULONG_FORMAT "%llu"	/* printf format for unsigned 64 bit ints */
+#endif
+
+#ifndef SOAP_MALLOC			/* use libc malloc */
+# define SOAP_MALLOC(n) malloc(n)
+#endif
+
+#ifndef SOAP_FREE			/* use libc free */
+# define SOAP_FREE(p) free(p)
+#endif
+
+#include <stdlib.h>
+
+#ifndef PALM
+# include <stdio.h>
+# include <string.h>
+#endif
+
+#include <ctype.h>
+#include <limits.h>
+
+#if defined(__cplusplus) && !defined(WITH_LEAN)
+# include <string>
+# include <iostream>
+  using namespace std;
+#endif
+
+#ifndef UNDER_CE
+# ifndef PALM
+#  include <errno.h>
+#  ifndef MAC_CARBON
+#   include <sys/types.h>
+#  endif
+#  ifndef WITH_LEAN
+#   ifdef HAVE_SYS_TIMEB_H
+#    include <sys/timeb.h>		/* for ftime() */
+#   endif
+#   include <time.h>
+#  endif
+# endif
+#endif
+
+#ifdef OPENSERVER
+# include <sys/socket.h>
+# include <sys/stream.h>
+# include <sys/protosw.h>
+  extern int h_errno;
+#endif
+
+#ifndef MAC_CARBON
+# ifndef WIN32
+#  ifndef PALM
+#   include <sys/socket.h>
+#   ifdef VXWORKS
+#    include <sockLib.h>
+#   endif
+#   ifndef VXWORKS
+#    ifndef SYMBIAN
+#     include <strings.h>
+#    endif
+#   endif
+#   ifdef SUN_OS
+#    include <sys/stream.h>		/* SUN */
+#    include <sys/socketvar.h>		/* SUN < 2.8 (?) */
+#   endif
+#   ifdef VXWORKS
+#    include <sys/times.h>
+#   else
+#    include <sys/time.h>
+#   endif
+#   include <netinet/in.h>
+#   ifdef OS390
+#    include <netinet/tcp_var.h>
+#   else
+#    include <netinet/tcp.h>          /* TCP_NODELAY */
+#   endif
+#   include <arpa/inet.h>
+#  endif
+# endif
+#endif
+
+#ifdef WITH_FASTCGI
+# include <fcgi_stdio.h>
+#endif
+
+#ifdef WITH_OPENSSL
+# define OPENSSL_NO_KRB5
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+# include <openssl/rand.h>
+# ifndef ALLOW_OLD_VERSIONS
+#  if (OPENSSL_VERSION_NUMBER < 0x00905100L)
+#   error "Must use OpenSSL 0.9.6 or later"
+#  endif
+# endif
+#endif
+
+#ifdef WITH_GZIP
+# ifndef WITH_ZLIB
+#  define WITH_ZLIB
+# endif
+#endif
+
+#ifdef WITH_CASEINSENSITIVETAGS
+# define SOAP_STRCMP soap_tag_cmp	/* case insensitve XML element/attribute names */
+#else
+# define SOAP_STRCMP strcmp		/* case sensitive XML element/attribute names */
+#endif
+
+#ifdef WITH_ZLIB
+# include <zlib.h>
+#endif
+
+#ifndef PALM
+# include <math.h>	/* for isnan() */
+#endif
+
+/* #define DEBUG */ /* Uncomment to debug sending (in file SENT.log) receiving (in file RECV.log) and messages (in file TEST.log) */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define soap_get0(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx])
+#define soap_get1(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx++])
+#define soap_revget1(soap) ((soap)->bufidx--)
+#define soap_unget(soap, c) ((soap)->ahead = c)
+#define soap_register_plugin(soap, plugin) soap_register_plugin_arg(soap, plugin, NULL)
+#define soap_imode(soap, n) ((soap)->mode = (soap)->imode = (n))
+#define soap_set_imode(soap, n) ((soap)->mode = (soap)->imode |= (n))
+#define soap_clr_imode(soap, n) ((soap)->mode = (soap)->imode &= ~(n))
+#define soap_omode(soap, n) ((soap)->mode = (soap)->omode = (n))
+#define soap_set_omode(soap, n) ((soap)->mode = (soap)->omode |= (n))
+#define soap_clr_omode(soap, n) ((soap)->mode = (soap)->omode &= ~(n))
+#define soap_destroy(soap) soap_delete((soap), NULL)
+
+#ifdef WIN32
+# ifndef UNDER_CE
+#  include <io.h>
+#  include <fcntl.h>
+# endif
+# include <winsock.h>
+/* # include <winsock2.h> */ /* Alternative: use winsock2 (not available with eVC) */
+/* WR[ */
+# ifdef WITH_IPV6
+#  include <ws2tcpip.h>
+#  include <wspiapi.h>
+# endif
+#else
+# ifdef VXWORKS
+#  include <hostLib.h>
+#  include <ioctl.h>
+#  include <ioLib.h>
+# endif
+/* ]WR */
+# ifndef MAC_CARBON
+#  ifndef PALM
+#   include <netdb.h>
+#   include <netinet/in.h>
+#   include <unistd.h>
+#   include <fcntl.h>
+#  endif
+# endif
+#endif
+
+#ifdef WIN32
+# define SOAP_SOCKET SOCKET
+#else
+# define SOAP_SOCKET int
+# define closesocket(n) close(n)
+#endif
+
+#define soap_valid_socket(n) ((n) >= 0)
+#define SOAP_INVALID_SOCKET (-1)
+
+#if defined(SYMBIAN)
+# define LONG64 long
+# define ULONG64 unsigned LONG64
+#elif !defined(WIN32)
+# define LONG64 long long
+# define ULONG64 unsigned LONG64
+#elif defined(UNDER_CE)
+# define LONG64 __int64
+# define ULONG64 unsigned LONG64
+#elif defined(__BORLANDC__)
+# define LONG64 __int64
+# define ULONG64 unsigned LONG64
+#endif
+
+#if defined(WIN32)
+# define soap_int32 __int32
+#elif defined(SYMBIAN)
+# define soap_int32 long
+#elif defined(PALM)
+# define soap_int32 Int32
+#else
+# define soap_int32 int32_t
+#endif
+
+/* UCS-4 requires 32 bits (0-7FFFFFFF, the sign bit is used by gSOAP to distinguish XML entities) */
+typedef soap_int32 soap_wchar;
+
+#ifdef WIN32
+# define SOAP_EINTR WSAEINTR
+# define SOAP_EAGAIN WSAEWOULDBLOCK
+# define SOAP_EWOULDBLOCK WSAEWOULDBLOCK
+# define SOAP_EINPROGRESS WSAEINPROGRESS
+#else
+# define SOAP_EINTR EINTR
+# define SOAP_EAGAIN EAGAIN
+# ifdef SYMBIAN
+#  define SOAP_EWOULDBLOCK 9898
+#  define SOAP_EINPROGRESS 9899
+# else
+#  define SOAP_EWOULDBLOCK EWOULDBLOCK
+#  define SOAP_EINPROGRESS EINPROGRESS
+# endif
+#endif
+
+#ifdef WIN32
+# ifdef UNDER_CE
+#  define soap_errno GetLastError()
+#  define soap_socket_errno GetLastError()
+# else
+#  define soap_errno GetLastError()
+#  define soap_socket_errno WSAGetLastError()
+# endif
+#else
+# define soap_errno errno
+# define soap_socket_errno errno
+#endif
+
+#ifndef SOAP_BUFLEN
+# ifndef WITH_LEAN
+#  define SOAP_BUFLEN  (32768) /* buffer length for socket packets, also used by gethostbyname_r so don't make this too small */
+# else
+#  define SOAP_BUFLEN   (2048)
+# endif
+#endif
+#ifndef SOAP_LABLEN
+# ifndef WITH_LEAN
+#  define SOAP_LABLEN  (256) /* initial look-aside buffer length */
+# else
+#  define SOAP_LABLEN   (64)
+# endif
+#endif
+#ifndef SOAP_PTRHASH
+# ifndef WITH_LEAN
+#  define SOAP_PTRHASH  (1024) /* size of pointer analysis hash table (must be power of 2) */
+# else
+#  define SOAP_PTRHASH    (16)
+# endif
+#endif
+#ifndef SOAP_IDHASH
+# ifndef WITH_LEAN
+#  define SOAP_IDHASH   (1999) /* prime size of hash table for parsed id/ref */
+# else
+#  define SOAP_IDHASH    (199)
+# endif
+#endif
+#ifndef SOAP_BLKLEN
+# define SOAP_BLKLEN     (256) /* size of blocks to collect long strings and XML attributes */
+#endif
+#ifndef SOAP_TAGLEN
+# define SOAP_TAGLEN     (256) /* maximum length of XML element tag/attribute name + 1 */
+#endif
+#ifndef SOAP_HDRLEN
+# ifndef WITH_LEAN
+#  define SOAP_HDRLEN   (8192) /* maximum length of HTTP header line (must be >4096 to read cookies) */
+# else
+#  define SOAP_HDRLEN   (1024)
+# endif
+#endif
+#ifndef SOAP_MAXDIMS
+# define SOAP_MAXDIMS	 (16) /* maximum array dimensions (array nestings) must be less than 64 to protect soap->tmpbuf */
+#endif
+
+#ifndef SOAP_MAXLOGS
+# define SOAP_MAXLOGS	  (3) /* max number of debug logs per struct soap environment */
+# define SOAP_INDEX_RECV  (0)
+# define SOAP_INDEX_SENT  (1)
+# define SOAP_INDEX_TEST  (2)
+#endif
+
+#ifndef SOAP_MAXKEEPALIVE
+# define SOAP_MAXKEEPALIVE (100) /* max iterations to keep server connection alive */
+#endif
+
+#ifndef SOAP_MAXARRAYSIZE
+# define SOAP_MAXARRAYSIZE (100000) /* "trusted" max size of inbound SOAP array for compound array allocation */
+#endif
+
+#ifdef VXWORKS
+# ifdef __INCmathh 
+#  include <private/mathP.h>
+#  ifndef HAVE_ISNAN
+#   define HAVE_ISNAN
+#  endif
+#  define soap_isnan(num) isNan(num)
+# endif
+#endif
+
+#ifdef WIN32 
+# include <float.h>
+# ifndef HAVE_ISNAN
+#  define HAVE_ISNAN
+# endif
+# define soap_isnan(num) _isnan(num)
+#endif
+
+#ifdef SUN_OS
+# define soap_isnan(n) isnan(n)
+#endif
+
+#if !defined(HAVE_ISNAN) && (defined(_MATH_H) || defined(_MATH_INCLUDED))
+# define HAVE_ISNAN
+#endif
+
+#ifndef soap_isnan
+# ifdef HAVE_ISNAN
+#  define soap_isnan(n) isnan(n)
+# else
+#  define soap_isnan(_) (0)
+# endif
+#endif
+
+extern const struct soap_double_nan { unsigned int n1, n2; } soap_double_nan;
+
+#ifdef VXWORKS
+# ifndef FLT_MAX
+#  define FLT_MAX _ARCH_FLT_MAX
+# endif
+# ifndef DBL_MAX
+#  define DBL_MAX _ARCH_DBL_MAX
+# endif
+#endif
+
+#ifndef FLT_NAN
+# ifdef HAVE_ISNAN
+#  define FLT_NAN (*(float*)&soap_double_nan)
+# else
+#  define FLT_NAN (0.0)
+# endif
+#endif
+
+#ifndef FLT_PINFTY
+# ifdef FLT_MAX
+#  define FLT_PINFTY FLT_MAX
+# else
+#  ifdef HUGE_VAL
+#    define FLT_PINFTY (float)HUGE_VAL
+#  else
+#   ifdef FLOAT_MAX
+#    define FLT_PINFTY FLOAT_MAX
+#   else
+#    define FLT_PINFTY (3.40282347e+38)
+#   endif
+#  endif
+# endif
+#endif
+
+#ifndef FLT_NINFTY
+# define FLT_NINFTY (-FLT_PINFTY)
+#endif
+
+#ifndef DBL_NAN
+# ifdef HAVE_ISNAN
+#  define DBL_NAN (*(double*)&soap_double_nan)
+# else
+#  define DBL_NAN (0.0)
+# endif
+#endif
+
+#ifndef DBL_PINFTY
+# ifdef DBL_MAX
+#  define DBL_PINFTY DBL_MAX
+# else
+#  ifdef HUGE_VAL
+#   define DBL_PINFTY (double)HUGE_VAL
+#  else
+#   ifdef DOUBLE_MAX
+#    define DBL_PINFTY DOUBLE_MAX
+#   else
+#    define DBL_PINFTY (1.7976931348623157e+308)
+#   endif
+#  endif
+# endif
+#endif
+
+#ifndef DBL_NINFTY
+# define DBL_NINFTY (-DBL_PINFTY)
+#endif
+
+#define soap_ispinfd(n) ((n) >= DBL_PINFTY)
+#define soap_ispinff(n) ((n) >= FLT_PINFTY)
+#define soap_isninfd(n) ((n) <= DBL_NINFTY)
+#define soap_isninff(n) ((n) <= FLT_NINFTY)
+
+/* gSOAP error codes */
+
+#define SOAP_EOF			EOF
+#define SOAP_ERR			EOF
+#define SOAP_OK				0
+#define SOAP_CLI_FAULT			1
+#define SOAP_SVR_FAULT			2
+#define SOAP_TAG_MISMATCH		3
+#define SOAP_TYPE			4
+#define SOAP_SYNTAX_ERROR		5
+#define SOAP_NO_TAG			6
+#define SOAP_IOB			7
+#define SOAP_MUSTUNDERSTAND		8
+#define SOAP_NAMESPACE			9
+/* #define SOAP_OBJ_MISMATCH		10	obsolete */
+#define SOAP_TAG_END			10
+#define SOAP_FATAL_ERROR		11
+#define SOAP_FAULT			12
+#define SOAP_NO_METHOD			13
+#define SOAP_GET_METHOD			14
+#define SOAP_EOM			15
+#define SOAP_NULL			16
+#define SOAP_MULTI_ID			17
+#define SOAP_MISSING_ID			18
+#define SOAP_HREF			19
+#define SOAP_TCP_ERROR			20
+#define SOAP_HTTP_ERROR			21
+#define SOAP_SSL_ERROR			22
+#define SOAP_ZLIB_ERROR			23
+#define SOAP_DIME_ERROR			24
+#define SOAP_DIME_HREF			25
+#define SOAP_DIME_MISMATCH		26
+#define SOAP_DIME_END			27
+#define SOAP_MIME_ERROR			28
+#define SOAP_VERSIONMISMATCH		29
+#define SOAP_PLUGIN_ERROR		30
+#define SOAP_DATAENCODINGUNKNOWN	31
+#define SOAP_REQUIRED			32
+#define SOAP_PROHIBITED			33
+#define SOAP_OCCURS			34
+#define SOAP_LENGTH			35
+
+#define soap_xml_error_check(e) ((e) == SOAP_TAG_MISMATCH || (e) == SOAP_TAG_END || (e) == SOAP_SYNTAX_ERROR || (e) == SOAP_NAMESPACE || (e) == SOAP_MULTI_ID || (e) == SOAP_MISSING_ID || (e) == SOAP_REQUIRED || (e) == SOAP_PROHIBITED || (e) == SOAP_OCCURS || (e) == SOAP_LENGTH || (e) == SOAP_NULL || (e) == SOAP_HREF)
+#define soap_soap_error_check(e) ((e) == SOAP_CLI_FAULT || (e) == SOAP_SVR_FAULT || (e) == SOAP_VERSIONMISMATCH || (e) == SOAP_MUSTUNDERSTAND || (e) == SOAP_FAULT || (e) == SOAP_NO_METHOD)
+#define soap_tcp_error_check(e) ((e) == SOAP_EOF || (e) == SOAP_TCP_ERROR)
+#define soap_ssl_error_check(e) ((e) == SOAP_SSL_ERROR)
+#define soap_zlib_error_check(e) ((e) == SOAP_ZLIB_ERROR)
+#define soap_mime_error_check(e) ((e) == SOAP_MIME_ERROR)
+#define soap_dime_error_check(e) ((e) == SOAP_DIME_ERROR || (e) == SOAP_DIME_MISMATCH)
+#define soap_http_error_check(e) ((e) == SOAP_HTTP_ERROR || (e) == SOAP_GET_METHOD || ((e) >= 100 && (e) < 600))
+
+/* gSOAP HTTP response status codes 100 to 600 are reserved */
+
+/* Special gSOAP HTTP response status codes */
+
+#define SOAP_STOP		1000	/* No HTTP response */
+#define SOAP_HTML		1001	/* Custom HTML response */
+#define SOAP_FILE		1002	/* Custom file-based response */
+
+/* gSOAP HTTP request status codes */
+
+#define SOAP_POST		1003
+#define SOAP_GET		1104
+
+/* gSOAP DIME */
+
+#define SOAP_DIME_CF		0x01
+#define SOAP_DIME_ME		0x02
+#define SOAP_DIME_MB		0x04
+#define SOAP_DIME_VERSION	0x08 /* DIME version 1 */
+#define SOAP_DIME_MEDIA		0x10
+#define SOAP_DIME_ABSURI	0x20
+
+/* gSOAP ZLIB */
+
+#define SOAP_ZLIB_NONE		0x00
+#define SOAP_ZLIB_DEFLATE	0x01
+#define SOAP_ZLIB_INFLATE	0x02
+#define SOAP_ZLIB_GZIP		0x02
+
+/* gSOAP transport, connection, and content encoding modes */
+
+typedef soap_int32 soap_mode;
+
+#define SOAP_IO			0x00000003	/* IO mask */
+#define SOAP_IO_FLUSH		0x00000000	/* flush output immediately, no buffering */
+#define SOAP_IO_BUFFER		0x00000001	/* buffer output in packets of size SOAP_BUFLEN */
+#define SOAP_IO_STORE		0x00000002	/* store entire output to determine length for transport */
+#define SOAP_IO_CHUNK		0x00000003	/* use HTTP chunked transfer AND buffer packets */
+
+#define SOAP_IO_LENGTH		0x00000004
+#define SOAP_IO_KEEPALIVE	0x00000008
+
+#define SOAP_ENC_LATIN		0x00800010	/* iso-8859-1 encoding */
+#define SOAP_ENC_XML		0x00000020	/* plain XML encoding, no HTTP header */
+#define SOAP_ENC_DIME		0x00000040
+#define SOAP_ENC_MIME		0x00000080
+#define SOAP_ENC_ZLIB		0x00000100
+#define SOAP_ENC_SSL		0x00000200
+
+#define SOAP_XML_STRICT		0x00001000	/* strict validation */
+#define SOAP_XML_CANONICAL	0x00002000	/* C14N canonical XML */
+#define SOAP_XML_TREE		0x00004000
+#define SOAP_XML_GRAPH		0x00008000
+#define SOAP_XML_NIL		0x00010000
+#define SOAP_XML_DOM		0x00020000
+#define SOAP_XML_SEC		0x00040000	/* reserved for WS security */
+
+#define SOAP_C_NOIOB		0x00100000
+#define SOAP_C_UTFSTRING	0x00200000
+#define SOAP_C_MBSTRING		0x00400000
+
+#define SOAP_DOM_TREE		0x01000000
+#define SOAP_DOM_NODE		0x02000000
+
+#define SOAP_IO_DEFAULT		SOAP_IO_FLUSH
+
+/* SSL client/server authentication settings */
+
+#define SOAP_SSL_NO_AUTHENTICATION		0x00	/* for testing purposes */
+#define SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION	0x01	/* client requires server to authenticate */
+#define SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION	0x02	/* server requires client to authenticate */
+
+#define SOAP_SSL_DEFAULT			SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION
+
+/* */
+
+#define SOAP_BEGIN		0
+#define SOAP_IN_ENVELOPE	2
+#define SOAP_IN_HEADER		3
+#define SOAP_END_HEADER		4
+#define SOAP_IN_BODY		5
+#define SOAP_END_BODY		6
+#define SOAP_END_ENVELOPE	7
+#define SOAP_END		8
+
+/* DEBUG macros */
+
+#ifndef WITH_LEAN
+# ifdef DEBUG
+#  ifndef SOAP_DEBUG
+#   define SOAP_DEBUG
+#  endif
+# endif
+#endif
+
+#ifdef SOAP_DEBUG
+# ifndef SOAP_MESSAGE
+#  define SOAP_MESSAGE fprintf
+# endif
+# ifndef DBGLOG
+#  define DBGLOG(DBGFILE, CMD) \
+{ if (soap)\
+  { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\
+      soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\
+    if (soap->fdebug[SOAP_INDEX_##DBGFILE])\
+    { FILE *fdebug = soap->fdebug[SOAP_INDEX_##DBGFILE];\
+      CMD;\
+      fflush(fdebug);\
+    }\
+  }\
+}
+# endif
+# ifndef DBGMSG
+#  define DBGMSG(DBGFILE, MSG, LEN) \
+{ if (soap)\
+  { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\
+      soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\
+    if (soap->fdebug[SOAP_INDEX_##DBGFILE])\
+    { fwrite((MSG), 1, (LEN), soap->fdebug[SOAP_INDEX_##DBGFILE]);\
+      fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\
+    }\
+  }\
+}
+# endif
+#else
+# define DBGLOG(DBGFILE, CMD)
+# define DBGMSG(DBGFILE, MSG, LEN)
+#endif
+
+struct Namespace
+{ const char *id;
+  const char *ns;
+  const char *in;
+  char *out;
+};
+
+struct soap_nlist
+{ struct soap_nlist *next;
+  unsigned int level;
+  short index; /* corresponding entry in ns mapping table */
+  char *ns; /* only set when parsed ns URI is not in the ns mapping table */
+  char id[1]; /* the actual string value flows into the allocated region below this struct */
+};
+
+struct soap_blist
+{ struct soap_blist *next;
+  char *ptr;
+  size_t size;
+};
+
+struct soap_array
+{ void *__ptr;
+  int __size;
+};
+
+/* pointer serialization management */
+struct soap_plist
+{ struct soap_plist *next;
+  const void *ptr;
+  const struct soap_array *array;
+  int type;
+  int id;
+  char mark1;
+  char mark2;
+};
+
+/* class allocation list */
+struct soap_clist
+{ struct soap_clist *next;
+  void *ptr;
+  int type;
+  int size;
+  void (*fdelete)(struct soap_clist*);
+};
+
+struct soap_attribute
+{ struct soap_attribute *next;
+  char *value;
+  size_t size;
+  char *ns;
+  short visible;
+  char name[1]; /* the actual name string flows into the allocated region below this struct */
+};
+
+struct soap_cookie
+{ struct soap_cookie *next;
+  char *name;
+  char *value;
+  char *domain;
+  char *path;
+  long expire;		/* client-side: local time to expire; server-side: seconds to expire */
+  unsigned int version;
+  short secure;
+  short session;	/* server-side */
+  short env;		/* server-side: got cookie from client */
+  short modified;	/* server-side: client cookie was modified */
+};
+
+#ifdef __cplusplus
+SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*);
+class soap_multipart_iterator
+{ public:
+  struct soap_multipart *content;
+  bool operator==(const soap_multipart_iterator& iter) const
+    { return content == iter.content; }
+  bool operator!=(const soap_multipart_iterator& iter) const
+    { return content != iter.content; }
+  struct soap_multipart &operator*() const
+    { return *content; }
+  soap_multipart_iterator &operator++()
+    { content = soap_next_multipart(content); return *this; }
+  soap_multipart_iterator() : content(NULL)
+    { }
+  soap_multipart_iterator(struct soap_multipart *p) : content(p)
+    { }
+};
+#endif
+
+struct soap_dime
+{ size_t count;
+  size_t size;
+  size_t chunksize;
+  size_t buflen;
+  char flags;
+  char *ptr;
+  const char *id;
+  const char *type;
+  const char *options;
+  struct soap_multipart *list;		/* list of DIME attachments received */
+  struct soap_multipart *first, *last;	/* temporary in/out queue */
+#ifdef __cplusplus
+  soap_multipart_iterator begin()
+    { soap_multipart_iterator iter(list); return iter; };
+  soap_multipart_iterator end()
+    { soap_multipart_iterator iter(NULL); return iter; };
+#endif
+};
+
+struct soap_mime
+{ char *boundary;			/* MIME boundary */
+  const char *start;			/* MIME start ID */
+  struct soap_multipart *list;		/* list of DIME attachments received */
+  struct soap_multipart *first, *last;	/* temporary in/out queue */
+#ifdef __cplusplus
+  soap_multipart_iterator begin()
+    { soap_multipart_iterator iter(list); return iter; };
+  soap_multipart_iterator end()
+    { soap_multipart_iterator iter(NULL); return iter; };
+#endif
+};
+
+/* RFC2045 MIME content transfer encodings */
+enum soap_mime_encoding
+{ SOAP_MIME_NONE,
+  SOAP_MIME_7BIT,
+  SOAP_MIME_8BIT,
+  SOAP_MIME_BINARY,
+  SOAP_MIME_QUOTED_PRINTABLE,
+  SOAP_MIME_BASE64,
+  SOAP_MIME_IETF_TOKEN,
+  SOAP_MIME_X_TOKEN
+};
+
+/* DIME/MIME multipart list */
+struct soap_multipart
+{ struct soap_multipart *next;
+  char *ptr;				/* points to raw data content */
+  size_t size;				/* size of data content */
+  const char *id;			/* DIME/MIME content ID */
+  const char *type;			/* DIME/MIME type (MIME type format) */
+  const char *options;			/* DIME options */
+  enum soap_mime_encoding encoding;	/* MIME Content-Transfer-Encoding */
+  const char *location;			/* MIME Content-Location (optional) */
+  const char *description;		/* MIME Content-Description (optional) */
+#ifdef __cplusplus
+  typedef soap_multipart_iterator iterator;
+#endif
+};
+
+struct soap_dom_attribute
+{ struct soap_dom_attribute *next;
+  const char *nstr;
+  char *name;
+  char *data;
+  wchar_t *wide;
+  struct soap *soap;
+#ifdef __cplusplus
+  struct soap_dom_attribute &set(const char *nstr, const char *name);	// set namespace and name
+  struct soap_dom_attribute &set(const char *data);		// set data
+  void unlink();
+  soap_dom_attribute();
+  soap_dom_attribute(struct soap *soap);
+  soap_dom_attribute(struct soap *soap, const char *nstr, const char *name, const char *data);
+  ~soap_dom_attribute();
+#endif
+};
+
+#ifdef __cplusplus
+class soap_dom_iterator
+{ public:
+  struct soap_dom_element *elt;
+  const char *nstr;
+  const char *name;
+  int type;
+  bool operator==(const soap_dom_iterator&) const;
+  bool operator!=(const soap_dom_iterator&) const;
+  struct soap_dom_element &operator*() const;
+  soap_dom_iterator &operator++();
+  soap_dom_iterator();
+  soap_dom_iterator(struct soap_dom_element*);
+  ~soap_dom_iterator();
+};
+#endif
+
+struct soap_dom_element
+{ struct soap_dom_element *next;	/* next sibling */
+  struct soap_dom_element *prnt;	/* parent */
+  struct soap_dom_element *elts;	/* first child element */
+  struct soap_dom_attribute *atts;	/* first child attribute */
+  const char *nstr;			/* namespace string */
+  char *name;				/* element tag name */
+  char *data;				/* element content data (with SOAP_C_UTFSTRING flag set) */
+  wchar_t *wide;			/* element content data */
+  int type;				/* optional: serialized C/C++ data type */
+  void *node;				/* optional: pointer to serialized C/C++ data */
+  struct soap *soap;
+#ifdef __cplusplus
+  typedef soap_dom_iterator iterator;
+  struct soap_dom_element &set(const char *nstr, const char *name);
+  struct soap_dom_element &set(const char *data);
+  struct soap_dom_element &set(void *node, int type);
+  struct soap_dom_element &add(struct soap_dom_element*);
+  struct soap_dom_element &add(struct soap_dom_element&);
+  struct soap_dom_element &add(struct soap_dom_attribute*);
+  struct soap_dom_element &add(struct soap_dom_attribute&);
+  soap_dom_iterator begin();
+  soap_dom_iterator end();
+  soap_dom_iterator find(const char *nstr, const char *name);
+  soap_dom_iterator find(int type);
+  void unlink();
+  soap_dom_element();
+  soap_dom_element(struct soap *soap);
+  soap_dom_element(struct soap *soap, const char *nstr, const char *name);
+  soap_dom_element(struct soap *soap, const char *nstr, const char *name, const char *data);
+  soap_dom_element(struct soap *soap, const char *nstr, const char *name, void *node, int type);
+  ~soap_dom_element();
+#endif
+};
+
+#if defined(__cplusplus) && !defined(WITH_LEAN)
+}
+extern ostream &operator<<(ostream&, const struct soap_dom_element&);
+extern istream &operator>>(istream&, struct soap_dom_element&);
+extern "C" {
+#endif
+
+struct soap
+{ short version;		/* 1 = SOAP1.1 and 2 = SOAP1.2 (set automatically from namespace URI in nsmap table) */
+  short copy;			/* 1 = copy of another soap struct */
+  soap_mode mode;
+  soap_mode imode;
+  soap_mode omode;
+  const char *float_format;	/* points to user-definable format string for floats (<1024 chars) */
+  const char *double_format;	/* points to user-definable format string for doubles (<1024 chars) */
+  const char *dime_id_format;	/* points to user-definable format string for integer DIME id (<SOAP_TAGLEN chars) */
+  const char *http_version;	/* default = "1.0" */
+  const char *http_content;	/* optional custom response content type (with SOAP_FILE) */
+  const char *encodingStyle;	/* default = NULL which means that SOAP encoding is used */
+  const char *actor;
+  int recv_timeout;		/* when > 0, gives socket recv timeout in seconds, < 0 in usec */
+  int send_timeout;		/* when > 0, gives socket send timeout in seconds, < 0 in usec */
+  int connect_timeout;		/* when > 0, gives socket connect() timeout in seconds, < 0 in usec */
+  int accept_timeout;		/* when > 0, gives socket accept() timeout in seconds, < 0 in usec */
+  int socket_flags;		/* socket recv() and send() flags, e.g. set to MSG_NOSIGNAL to disable sigpipe */
+  int connect_flags;		/* connect() SOL_SOCKET sockopt flags, e.g. set to SO_DEBUG to debug socket */
+  int bind_flags;		/* bind() SOL_SOCKET sockopt flags, e.g. set to SO_REUSEADDR to enable reuse */
+  int accept_flags;		/* accept() SOL_SOCKET sockopt flags */
+  const struct Namespace *namespaces;	/* Pointer to global namespace mapping table */
+  struct Namespace *local_namespaces;	/* Local namespace mapping table */
+  struct soap_nlist *nlist;	/* namespace stack */
+  struct soap_blist *blist;	/* block allocation stack */
+  struct soap_clist *clist;	/* class instance allocation list */
+  void *alist;			/* memory allocation list */
+  struct soap_ilist *iht[SOAP_IDHASH];
+  struct soap_plist *pht[SOAP_PTRHASH];
+  struct SOAP_ENV__Header *header;
+  struct SOAP_ENV__Fault *fault;
+  void *user;			/* to pass user-defined data */
+  struct soap_plugin *plugins;	/* linked list of plug-in data */
+  char *userid;			/* HTTP Basic authorization userid */
+  char *passwd;			/* HTTP Basic authorization passwd */
+  int (*fpost)(struct soap*, const char*, const char*, int, const char*, const char*, size_t);
+  int (*fget)(struct soap*);
+  int (*fposthdr)(struct soap*, const char*, const char*);
+  int (*fresponse)(struct soap*, int, size_t);
+  int (*fparse)(struct soap*);
+  int (*fparsehdr)(struct soap*, const char*, const char*);
+  int (*fresolve)(struct soap*, const char*, struct in_addr* inaddr);
+  int (*fconnect)(struct soap*, const char*, const char*, int);
+  int (*fdisconnect)(struct soap*);
+  int (*fclosesocket)(struct soap*, SOAP_SOCKET);
+  int (*fshutdownsocket)(struct soap*, SOAP_SOCKET, int);
+  int (*fopen)(struct soap*, const char*, const char*, int);
+  int (*faccept)(struct soap*, int, struct sockaddr*, int *n);
+  int (*fclose)(struct soap*);
+  int (*fsend)(struct soap*, const char*, size_t);
+  size_t (*frecv)(struct soap*, char*, size_t);
+  int (*fpoll)(struct soap*);
+  int (*fprepareinit)(struct soap*);
+  int (*fpreparesend)(struct soap*, const char*, size_t);
+  int (*fpreparerecv)(struct soap*, const char*, size_t);
+  int (*fignore)(struct soap*, const char*);
+  int (*fserveloop)(struct soap*);
+  void *(*fplugin)(struct soap*, const char*);
+  void *(*fdimereadopen)(struct soap*, void*, const char*, const char*, const char*);
+  void *(*fdimewriteopen)(struct soap*, const char*, const char*, const char*);
+  void (*fdimereadclose)(struct soap*, void*);
+  void (*fdimewriteclose)(struct soap*, void*);
+  size_t (*fdimeread)(struct soap*, void*, char*, size_t);
+  int (*fdimewrite)(struct soap*, void*, const char*, size_t);
+  int master;
+  int socket;
+#if defined(__cplusplus) && !defined(WITH_LEAN)
+  ostream *os;
+  istream *is;
+#else
+  void *os;	/* preserve alignment */
+  void *is;	/* preserve alignment */
+#endif
+#ifndef UNDER_CE
+  int sendfd;
+  int recvfd;
+#else
+  FILE *sendfd;
+  FILE *recvfd;
+  char errorstr[256];
+  wchar_t werrorstr[256];
+#endif
+  size_t bufidx;
+  size_t buflen;
+  soap_wchar ahead;
+  short cdata;
+  short body;
+  unsigned int level;
+  size_t count;		/* message length counter */
+  size_t length;	/* message length as set by HTTP header */
+  char *labbuf;		/* look-aside buffer */
+  size_t lablen;	/* look-aside buffer allocated length */
+  size_t labidx;	/* look-aside buffer index to available part */
+  char buf[SOAP_BUFLEN];/* send and receive buffer */
+  char tmpbuf[1024];	/* output buffer for HTTP headers, simpleType values, attribute names, and DIME >=1024 bytes */
+  char msgbuf[1024];	/* output buffer for (error) messages <=1024 bytes */
+  char tag[SOAP_TAGLEN];
+  char id[SOAP_TAGLEN];
+  char href[SOAP_TAGLEN];
+  char type[SOAP_TAGLEN];
+  char arrayType[SOAP_TAGLEN];
+  char arraySize[SOAP_TAGLEN];
+  char arrayOffset[SOAP_TAGLEN];
+  short other;
+  short root;
+  short position;
+  int positions[SOAP_MAXDIMS];
+  struct soap_attribute *attributes;	/* attribute list */
+  short encoding;
+  short mustUnderstand;
+  short null;
+  short ns;
+  short part;
+  short alloced;
+  short peeked;
+  short keep_alive;
+  size_t chunksize;
+  size_t chunkbuflen;
+  char endpoint[SOAP_TAGLEN];
+  char path[SOAP_TAGLEN];
+  char host[SOAP_TAGLEN];
+  char *action;
+  char *authrealm;		/* HTTP authentication realm */
+  char *prolog;			/* XML declaration prolog */
+  int port;
+  unsigned int max_keep_alive;
+  const char *proxy_host;	/* Proxy Server host name */
+  int proxy_port;		/* Proxy Server port (default = 8080) */
+  const char *proxy_userid;	/* Proxy Authorization user name */
+  const char *proxy_passwd;	/* Proxy Authorization password */
+  int status;			/* -1 when request, else error code to be returned by server */
+  int error;
+  int errmode;
+  int errnum;
+  unsigned long idnum;
+  unsigned long ip;
+  struct soap_dime dime;
+  struct soap_mime mime;
+  struct soap_dom_element *dom;
+#if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
+  const char *logfile[SOAP_MAXLOGS];
+  FILE *fdebug[SOAP_MAXLOGS];
+#endif
+#ifndef WITH_LEAN
+  struct soap_cookie *cookies;
+  const char *cookie_domain;
+  const char *cookie_path;
+  int cookie_max;
+#endif
+#ifdef WITH_OPENSSL
+  int (*fsslauth)(struct soap*);
+  int (*fsslverify)(int, X509_STORE_CTX*);
+  BIO *bio;
+  SSL *ssl;
+  SSL_CTX *ctx;
+  short require_server_auth;
+  short require_client_auth;
+  short rsa;			/* when set, use RSA instead of DH */
+  const char *keyfile;
+  const char *password;
+  const char *dhfile;
+  const char *cafile;
+  const char *capath;
+  const char *randfile;
+  SSL_SESSION *session;
+  char session_host[SOAP_TAGLEN];
+  int session_port;
+#endif
+#ifdef WITH_ZLIB
+  short zlib_state;		/* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_INFLATE */
+  short zlib_in;		/* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */
+  short zlib_out;		/* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */
+  z_stream d_stream;		/* decompression stream */
+  char z_buf[SOAP_BUFLEN];	/* buffer */
+  size_t z_buflen;
+  unsigned short z_level;	/* compression level to be used (0=none, 1=fast to 9=best) */
+  uLong z_crc;			/* internal gzip crc */
+  float z_ratio_in;		/* detected compression ratio compressed_length/length of inbound message */
+  float z_ratio_out;		/* detected compression ratio compressed_length/length of outbound message */
+#endif
+/* WR[ */
+#ifdef WMW_RPM_IO
+  void *rpmreqid;
+#endif /* WMW_RPM_IO */
+/* ]WR */
+};
+
+struct soap_code_map
+{ long code;
+  const char *string;
+};
+
+/* forwarding list */
+struct soap_flist
+{ struct soap_flist *next;
+  int type;
+  void *ptr;
+  unsigned int level;
+  void (*fcopy)(struct soap*, int, int, void*, const void*, size_t);
+};
+
+/* id-ref forwarding list */
+struct soap_ilist
+{ struct soap_ilist *next;
+  int type;
+  size_t size;
+  void *link;
+  void *copy;
+  struct soap_flist *flist;
+  void *ptr;
+  unsigned int level;
+  char id[1]; /* the actual id string value flows into the allocated region below this struct */
+};
+
+struct soap_plugin
+{ struct soap_plugin *next;
+  const char *id;
+  void *data;
+  int (*fcopy)(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src);
+  void (*fdelete)(struct soap *soap, struct soap_plugin *p); /* should delete fields of plugin only and not free(p) */
+};
+
+#ifndef WITH_NONAMESPACES
+extern SOAP_NMAC struct Namespace namespaces[];
+#endif
+
+#ifdef HAVE_STRRCHR
+# define soap_strrchr(s, t) strrchr(s, t)
+#else
+ SOAP_FMAC1 char* SOAP_FMAC2 soap_strrchr(const char *s, int t);
+#endif
+
+#ifdef HAVE_STRTOL
+# define soap_strtol(s, t, b) strtol(s, t, b)
+#else
+ SOAP_FMAC1 long SOAP_FMAC2 soap_strtol(const char *s, char **t, int b);
+#endif
+
+#ifdef HAVE_STRTOUL
+# define soap_strtoul(s, t, b) strtoul(s, t, b)
+#else
+ SOAP_FMAC1 unsigned long SOAP_FMAC2 soap_strtoul(const char *s, char **t, int b);
+#endif
+
+SOAP_FMAC1 void SOAP_FMAC2 soap_fault(struct soap*);
+SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultcode(struct soap*);
+SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultstring(struct soap*);
+SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultdetail(struct soap*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_serializeheader(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_putheader(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_getheader(struct soap*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_serializefault(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_putfault(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_getfault(struct soap*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_poll(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_connect_command(struct soap*, int, const char*, const char*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_connect(struct soap*, const char*, const char*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_bind(struct soap*, const char*, int, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_accept(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_accept(struct soap*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_server_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*, const char*, const char*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_client_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_puthttphdr(struct soap*, int status, size_t count);
+
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_get_header_attribute(struct soap*, const char*, const char*);
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_key(char*, size_t, const char*);
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_val(char*, size_t, const char*);
+
+SOAP_FMAC1 size_t SOAP_FMAC2 soap_hash(const char*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_set_endpoint(struct soap*, const char*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_flush_raw(struct soap*, const char*, size_t);
+SOAP_FMAC1 int SOAP_FMAC2 soap_flush(struct soap*);
+SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_get(struct soap*);
+SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getchar(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_tag_cmp(const char*, const char*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_set_fault(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault(struct soap*, const char*, const char*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault(struct soap*, const char*, const char*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_set_sender_error(struct soap*, const char*, const char*, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_set_receiver_error(struct soap*, const char*, const char*, int);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_send_raw(struct soap*, const char*, size_t);
+SOAP_FMAC1 int SOAP_FMAC2 soap_recv_raw(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_recv(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_send(struct soap*, const char*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_send2(struct soap*, const char*, const char*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_send3(struct soap*, const char*, const char*, const char*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_pututf8(struct soap*, unsigned long);
+SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getutf8(struct soap*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_putbase64(struct soap*, const unsigned char*, int);
+SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_getbase64(struct soap*, int*, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_puthex(struct soap*, const unsigned char*, int);
+SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_gethex(struct soap*, int*);
+
+
+SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_lookup(struct soap*, const char*);
+SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_enter(struct soap*, const char*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_resolve(struct soap*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup_id(struct soap*, void *p, int t, struct soap_plist**);
+SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup(struct soap*, const void *p, int t, struct soap_plist**);
+SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_enter(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**);
+SOAP_FMAC1 int SOAP_FMAC2 soap_array_pointer_lookup(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type);
+
+SOAP_FMAC1 void SOAP_FMAC2 soap_begin_count(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_begin_send(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_end_send(struct soap*);
+
+SOAP_FMAC1 void SOAP_FMAC2 soap_embedded(struct soap*, const void *p, int t);
+SOAP_FMAC1 int SOAP_FMAC2 soap_reference(struct soap*, const void *p, int t);
+SOAP_FMAC1 int SOAP_FMAC2 soap_array_reference(struct soap*, const void *p, const struct soap_array *a, int n, int t);
+SOAP_FMAC1 int SOAP_FMAC2 soap_embedded_id(struct soap*, int id, const void *p, int t);
+SOAP_FMAC1 int SOAP_FMAC2 soap_is_embedded(struct soap*, struct soap_plist*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_is_single(struct soap*, struct soap_plist*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_set_embedded(struct soap*, struct soap_plist*);
+
+SOAP_FMAC1 const struct soap_code_map* SOAP_FMAC2 soap_code(const struct soap_code_map*, const char *str);
+SOAP_FMAC1 long SOAP_FMAC2 soap_int_code(const struct soap_code_map*, const char *str, long other);
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_str_code(const struct soap_code_map*, long code);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_getline(struct soap*, char*, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_begin_recv(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_end_recv(struct soap*);
+
+SOAP_FMAC1 void* SOAP_FMAC2 soap_malloc(struct soap*, size_t);
+SOAP_FMAC1 void SOAP_FMAC2 soap_dealloc(struct soap*, void*);
+SOAP_FMAC1 struct soap_clist * SOAP_FMAC2 soap_link(struct soap*, void*, int, int, void (*fdelete)(struct soap_clist*));
+SOAP_FMAC1 void SOAP_FMAC2 soap_unlink(struct soap*, const void*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_free(struct soap*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_lookup_type(struct soap*, const char *id);
+
+SOAP_FMAC1 void* SOAP_FMAC2 soap_id_lookup(struct soap*, const char *id, void **p, int t, size_t n, unsigned int k);
+SOAP_FMAC1 void* SOAP_FMAC2 soap_id_forward(struct soap*, const char *id, void *p, int st, int tt, size_t n, unsigned int k, void(*fcopy)(struct soap*, int, int, void*, const void*, size_t));
+SOAP_FMAC1 void* SOAP_FMAC2 soap_id_enter(struct soap*, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*));
+SOAP_FMAC1 void SOAP_FMAC2 soap_fcopy(struct soap *soap, int st, int tt, void *p, const void *q, size_t n);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_size(const int *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_getoffsets(const char *, const int *, int *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_getsize(const char *, const char *, int *);
+SOAP_FMAC1 int SOAP_FMAC2 soap_getsizes(const char *, int *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_getposition(const char *, int *);
+
+SOAP_FMAC1 char* SOAP_FMAC2 soap_putsize(struct soap*, const char *, int);
+SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizesoffsets(struct soap*, const char *, const int *, const int *, int);
+SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizes(struct soap*, const char *, const int *, int);
+SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffset(struct soap*, int);
+SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffsets(struct soap*, const int *, int);
+ 
+SOAP_FMAC1 int SOAP_FMAC2 soap_closesock(struct soap*);
+
+SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new(void);
+SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new1(int);
+SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new2(int, int);
+SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy(struct soap*);
+SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy_context(struct soap*,struct soap*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_init(struct soap*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_init1(struct soap*, int);
+SOAP_FMAC1 void SOAP_FMAC2 soap_init2(struct soap*, int, int);
+SOAP_FMAC1 void SOAP_FMAC2 soap_done(struct soap*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_cleanup(struct soap*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_begin(struct soap*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_end(struct soap*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_delete(struct soap*, void*);
+
+#ifdef SOAP_DEBUG
+SOAP_FMAC1 void SOAP_FMAC2 soap_set_recv_logfile(struct soap*, const char*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_set_sent_logfile(struct soap*, const char*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_set_test_logfile(struct soap*, const char*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_close_logfiles(struct soap*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_open_logfile(struct soap*, int);
+#endif
+
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_value(struct soap*);
+
+SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_advance(struct soap*);
+SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_skip(struct soap*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_match_tag(struct soap*, const char*, const char *);
+SOAP_FMAC1 int SOAP_FMAC2 soap_match_array(struct soap*, const char*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_element(struct soap*, const char*, int, const char*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_out(struct soap*, const char *tag, int id, const char *type);
+SOAP_FMAC1 int SOAP_FMAC2 soap_array_begin_out(struct soap*, const char *tag, int id, const char *type, const char *offset);
+SOAP_FMAC1 int SOAP_FMAC2 soap_element_ref(struct soap*, const char *tag, int id, int href);
+SOAP_FMAC1 int SOAP_FMAC2 soap_element_href(struct soap*, const char *tag, int id, const char *ref, const char *val);
+SOAP_FMAC1 int SOAP_FMAC2 soap_element_null(struct soap*, const char *tag, int id, const char *type);
+SOAP_FMAC1 int SOAP_FMAC2 soap_element_id(struct soap*, const char *tag, int id, const void *p, const struct soap_array *a, int d, const char *type, int n);
+SOAP_FMAC1 int SOAP_FMAC2 soap_element_result(struct soap*, const char *tag);
+SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_out(struct soap*, const char *tag);
+SOAP_FMAC1 int SOAP_FMAC2 soap_element_start_end_out(struct soap*, const char *tag);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_attribute(struct soap*, const char*, const char*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_in(struct soap*, const char *tag, int nillable);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_in(struct soap*, const char *tag);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_peek_element(struct soap*);
+
+SOAP_FMAC1 void SOAP_FMAC2 soap_retry(struct soap*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_revert(struct soap*);
+
+SOAP_FMAC1 char* SOAP_FMAC2 soap_strdup(struct soap*, const char*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_string_out(struct soap*, const char *s, int flag);
+SOAP_FMAC1 char* SOAP_FMAC2 soap_string_in(struct soap*, int, long, long);
+SOAP_FMAC1 int SOAP_FMAC2 soap_wstring_out(struct soap*, const wchar_t *s, int flag);
+SOAP_FMAC1 wchar_t* SOAP_FMAC2 soap_wstring_in(struct soap*, int, long, long);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_match_namespace(struct soap*, const char *, const char*, int n1, int n2);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_set_namespaces(struct soap*, struct Namespace*);
+
+SOAP_FMAC1 void SOAP_FMAC2 soap_pop_namespace(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_push_namespace(struct soap*, const char *,const char *);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_new_block(struct soap*);
+SOAP_FMAC1 void* SOAP_FMAC2 soap_push_block(struct soap*, size_t);
+SOAP_FMAC1 void SOAP_FMAC2 soap_pop_block(struct soap*);
+SOAP_FMAC1 size_t SOAP_FMAC2 soap_size_block(struct soap*, size_t);
+SOAP_FMAC1 char* SOAP_FMAC2 soap_first_block(struct soap*);
+SOAP_FMAC1 char* SOAP_FMAC2 soap_next_block(struct soap*);
+SOAP_FMAC1 size_t SOAP_FMAC2 soap_block_size(struct soap*);
+SOAP_FMAC1 char* SOAP_FMAC2 soap_save_block(struct soap*, char*, int);
+SOAP_FMAC1 void SOAP_FMAC2 soap_end_block(struct soap*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_out(struct soap*);
+SOAP_FMAC1 int soap_envelope_end_out(struct soap*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_in(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_end_in(struct soap*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_out(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_out(struct soap*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_in(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_in(struct soap*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_recv_header(struct soap*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_response(struct soap*, int);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_send_fault(struct soap*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_recv_fault(struct soap*);
+
+SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault(struct soap*, FILE*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault_location(struct soap*, FILE*);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_s2byte(struct soap*, const char*, char*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_s2short(struct soap*, const char*, short*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_s2int(struct soap*, const char*, int*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_s2long(struct soap*, const char*, long*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_s2LONG64(struct soap*, const char*, LONG64*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_s2float(struct soap*, const char*, float*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_s2double(struct soap*, const char*, double*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedByte(struct soap*, const char*, unsigned char*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedShort(struct soap*, const char*, unsigned short*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedInt(struct soap*, const char*, unsigned int*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedLong(struct soap*, const char*, unsigned long*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_s2ULONG64(struct soap*, const char*, ULONG64*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_s2dateTime(struct soap*, const char*, time_t*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_s2string(struct soap*, const char*, char**);
+SOAP_FMAC1 int SOAP_FMAC2 soap_s2QName(struct soap*, const char*, char**);
+
+SOAP_FMAC1 char* SOAP_FMAC2 soap_s2base64(struct soap*, const unsigned char*, char*, size_t);
+
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_byte2s(struct soap*, char);
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_short2s(struct soap*, short);
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_int2s(struct soap*, int);
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_long2s(struct soap*, long);
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_LONG642s(struct soap*, LONG64);
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_float2s(struct soap*, float);
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_double2s(struct soap*, double);
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedByte2s(struct soap*, unsigned char);
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedShort2s(struct soap*, unsigned short);
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedInt2s(struct soap*, unsigned int);
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedLong2s(struct soap*, unsigned long);
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_ULONG642s(struct soap*, ULONG64);
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_dateTime2s(struct soap*, time_t);
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_QName2s(struct soap*, const char*);
+
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_base642s(struct soap*, const char*, char*, size_t, size_t*);
+
+SOAP_FMAC1 int* SOAP_FMAC2 soap_inint(struct soap*, const char *tag, int *p, const char *, int);
+SOAP_FMAC1 char* SOAP_FMAC2 soap_inbyte(struct soap*, const char *tag, char *p, const char *, int);
+SOAP_FMAC1 long* SOAP_FMAC2 soap_inlong(struct soap*, const char *tag, long *p, const char *, int);
+SOAP_FMAC1 LONG64* SOAP_FMAC2 soap_inLONG64(struct soap*, const char *tag, LONG64 *p, const char *, int);
+SOAP_FMAC1 short* SOAP_FMAC2 soap_inshort(struct soap*, const char *tag, short *p, const char *, int);
+SOAP_FMAC1 float* SOAP_FMAC2 soap_infloat(struct soap*, const char *tag, float *p, const char *, int);
+SOAP_FMAC1 double* SOAP_FMAC2 soap_indouble(struct soap*, const char *tag, double *p, const char *, int);
+SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_inunsignedByte(struct soap*, const char *tag, unsigned char *p, const char *, int);
+SOAP_FMAC1 unsigned short* SOAP_FMAC2 soap_inunsignedShort(struct soap*, const char *tag, unsigned short *p, const char *, int);
+SOAP_FMAC1 unsigned int* SOAP_FMAC2 soap_inunsignedInt(struct soap*, const char *tag, unsigned int *p, const char *, int);
+SOAP_FMAC1 unsigned long* SOAP_FMAC2 soap_inunsignedLong(struct soap*, const char *tag, unsigned long *p, const char *, int);
+SOAP_FMAC1 ULONG64* SOAP_FMAC2 soap_inULONG64(struct soap*, const char *tag, ULONG64 *p, const char *, int);
+SOAP_FMAC1 time_t* SOAP_FMAC2 soap_indateTime(struct soap*, const char *tag, time_t *p, const char *, int);
+SOAP_FMAC1 char** SOAP_FMAC2 soap_instring(struct soap*, const char *tag, char **p, const char *, int, int, long, long);
+SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwstring(struct soap*, const char *tag, wchar_t **p, const char *, int, long, long);
+SOAP_FMAC1 char** SOAP_FMAC2 soap_inliteral(struct soap*, const char *tag, char **p);
+SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwliteral(struct soap*, const char *tag, wchar_t **p);
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_outbyte(struct soap*, const char *tag, int id, const char *p, const char *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_outshort(struct soap*, const char *tag, int id, const short *p, const char *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_outint(struct soap*, const char *tag, int id, const int *p, const char *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_outlong(struct soap*, const char *tag, int id, const long *p, const char *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_outLONG64(struct soap*, const char *tag, int id, const LONG64 *p, const char *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_outfloat(struct soap*, const char *tag, int id, const float *p, const char *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_outdouble(struct soap*, const char *tag, int id, const double *p, const char *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedByte(struct soap*, const char *tag, int id, const unsigned char *p, const char *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedShort(struct soap*, const char *tag, int id, const unsigned short *p, const char *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedInt(struct soap*, const char *tag, int id, const unsigned int *p, const char *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedLong(struct soap*, const char *tag, int id, const unsigned long *p, const char *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_outULONG64(struct soap*, const char *tag, int id, const ULONG64 *p, const char *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_outdateTime(struct soap*, const char *tag, int id, const time_t *p, const char *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_outstring(struct soap*, const char *tag, int id, char *const*p, const char *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_outwstring(struct soap*, const char *tag, int id, wchar_t *const*p, const char *, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_outliteral(struct soap*, const char *tag, char *const*p);
+SOAP_FMAC1 int SOAP_FMAC2 soap_outwliteral(struct soap*, const char *tag, wchar_t *const*p);
+
+#ifndef WITH_LEANER
+SOAP_FMAC1 int SOAP_FMAC2 soap_element_dime(struct soap *, const char*, int, const void*, const struct soap_array*, const char*, const char*, const char*, int, const char*, int);
+SOAP_FMAC1 int SOAP_FMAC2 soap_move(struct soap*, long);
+SOAP_FMAC1 size_t SOAP_FMAC2 soap_tell(struct soap*);
+SOAP_FMAC1 char* SOAP_FMAC2 soap_dime_option(struct soap*, unsigned short, const char*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_getdimehdr(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_getdime(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_putdimehdr(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_putdime(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_getmimehdr(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_getmime(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_putmimehdr(struct soap*, struct soap_multipart*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_putmime(struct soap*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_set_dime(struct soap*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_set_mime(struct soap*, const char *boundary, const char *start);
+SOAP_FMAC1 void SOAP_FMAC2 soap_clr_dime(struct soap*);
+SOAP_FMAC1 void SOAP_FMAC2 soap_clr_mime(struct soap*);
+SOAP_FMAC1 int SOAP_FMAC2 soap_set_dime_attachment(struct soap*, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option);
+SOAP_FMAC1 int SOAP_FMAC2 soap_set_mime_attachment(struct soap*, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description);
+SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*);
+#endif
+
+SOAP_FMAC1 int SOAP_FMAC2 soap_register_plugin_arg(struct soap*, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void*);
+SOAP_FMAC1 void* SOAP_FMAC2 soap_lookup_plugin(struct soap*, const char*);
+
+SOAP_FMAC1 const char* SOAP_FMAC2 soap_attr_value(struct soap *soap, const char *name, int flag);
+SOAP_FMAC1 int SOAP_FMAC2 soap_set_attr(struct soap *soap, const char *name, const char *value);
+SOAP_FMAC1 void SOAP_FMAC2 soap_clr_attr(struct soap *soap);
+
+#ifdef WITH_COOKIES
+SOAP_FMAC1 size_t SOAP_FMAC2 soap_encode_cookie(const char*, char*, size_t);
+SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_set_cookie(struct soap*, const char*, const char*, const char*, const char*);
+SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_cookie(struct soap*, const char*, const char*, const char*);
+SOAP_FMAC1 extern char* SOAP_FMAC2 soap_cookie_value(struct soap*, const char*, const char*, const char*);
+SOAP_FMAC1 extern long SOAP_FMAC2 soap_cookie_expire(struct soap*, const char*, const char*, const char*);
+SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_expire(struct soap*, const char*, long, const char*, const char*);
+SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_session(struct soap*, const char*, const char*, const char*);
+SOAP_FMAC1 extern int SOAP_FMAC2 soap_clr_cookie_session(struct soap*, const char*, const char*, const char*);
+SOAP_FMAC1 extern void SOAP_FMAC2 soap_clr_cookie(struct soap*, const char*, const char*, const char*);
+SOAP_FMAC1 extern int SOAP_FMAC2 soap_getenv_cookies(struct soap*);
+SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_copy_cookies(struct soap*);
+SOAP_FMAC1 extern void SOAP_FMAC2 soap_free_cookies(struct soap*);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/xmalloc.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/xmalloc.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/xmalloc.c	(revision 21994)
@@ -0,0 +1,44 @@
+/*
+ * xmalloc.c - malloc that can't fail
+ *
+ * Copyright (C) 2003-2005  Joshua Hoblitt, 2003  Robert Lupton
+ *
+ * $Id: xmalloc.c,v 1.3 2005-07-30 02:45:31 jhoblitt Exp $
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "xmalloc.h"
+
+/*****************************************************************************/
+/*
+ * Wrappers for malloc/free.  xmalloc cannot fail.
+ */
+void * xmalloc(size_t n)
+{
+   void *ptr = malloc(n);
+    
+   if (ptr == NULL) {
+      perror("malloc");
+      exit(EXIT_FAILURE);
+   }
+ 
+   return(ptr);
+}
+
+void * xrealloc(void *ptr, size_t size)
+{
+    void *newptr = realloc(ptr, size);
+
+    if (!newptr) {
+        perror("realloc");
+        exit(EXIT_FAILURE);
+    } 
+
+    return(newptr);
+}
+ 
+void xfree(void *ptr)
+{
+   free(ptr);
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/xmalloc.h
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/xmalloc.h	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/src/xmalloc.h	(revision 21994)
@@ -0,0 +1,18 @@
+/*
+ * xmalloc.h - malloc that can't fail
+ *
+ * Copyright (C) 2003-2005  Joshua Hoblitt, 2003  Robert Lupton
+ *
+ * $Id: xmalloc.h,v 1.4 2005-07-30 02:45:31 jhoblitt Exp $
+ */
+
+#ifndef XMALLOC_H
+#define XMALLOC_H 1
+
+void * xmalloc(size_t n);
+
+void * xrealloc(void *ptr, size_t size);
+ 
+void xfree(void *ptr);
+
+#endif // XMALLOC_H
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/.cvsignore	(revision 21994)
@@ -0,0 +1,3 @@
+.deps
+Makefile
+Makefile.in
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/Makefile.am	(revision 21994)
@@ -0,0 +1,13 @@
+SUBDIRS = tap
+
+TESTS = tests
+
+AM_CPPFLAGS = \
+    -I$(top_srcdir)/tests/tap/src \
+    -I$(top_srcdir)/src
+
+AM_LDFLAGS = \
+    $(top_builddir)/tests/tap/src/libtap.la \
+    $(top_builddir)/src/libnebclient.la
+
+check_PROGRAMS = tests
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/.cvsignore	(revision 21994)
@@ -0,0 +1,13 @@
+.in
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+config.log
+config.status
+configure
+libtool
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/INSTALL
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/INSTALL	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/INSTALL	(revision 21994)
@@ -0,0 +1,8 @@
+Quick Installation
+
+    ./configure
+    make
+    make check
+    make install
+
+Run "configure --help" for additional options.
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/LICENSE
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/LICENSE	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/LICENSE	(revision 21994)
@@ -0,0 +1,23 @@
+Copyright (c) 2004 Nik Clayton
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/Makefile.am	(revision 21994)
@@ -0,0 +1,5 @@
+SUBDIRS  = src
+#SUBDIRS += tests
+
+prove:
+	prove -v -r
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/README
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/README	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/README	(revision 21994)
@@ -0,0 +1,11 @@
+NAME
+     tap -- write tests that implement the Test Anything Protocol
+
+SYNOPSIS
+     #include <tap.h>
+
+DESCRIPTION
+     The tap library provides functions for writing test scripts that produce
+     output consistent with the Test Anything Protocol.  A test harness that
+     parses this protocol can run these tests and produce useful reports indi-
+     cating their success or failure.
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/bootstrap.sh
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/bootstrap.sh	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/bootstrap.sh	(revision 21994)
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+set -x
+aclocal || exit 1
+autoheader || autoheader || exit 1
+libtoolize -c -f || libtoolize -c -f || glibtoolize -c -f || exit 1
+automake -a -c || automake -a -c || exit 1
+autoconf || autoconf || exit 1
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/compile
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/compile	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/compile	(revision 21994)
@@ -0,0 +1,142 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand `-c -o'.
+
+scriptversion=2004-10-12.08
+
+# Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.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, 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.
+#
+# 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.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+case $1 in
+  '')
+     echo "$0: No command.  Try \`$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand `-c -o'.
+Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file `INSTALL'.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit 0
+    ;;
+  -v | --v*)
+    echo "compile $scriptversion"
+    exit 0
+    ;;
+esac
+
+ofile=
+cfile=
+eat=
+
+for arg
+do
+  if test -n "$eat"; then
+    eat=
+  else
+    case $1 in
+      -o)
+	# configure might choose to run compile as `compile cc -o foo foo.c'.
+	# So we strip `-o arg' only if arg is an object.
+	eat=1
+	case $2 in
+	  *.o | *.obj)
+	    ofile=$2
+	    ;;
+	  *)
+	    set x "$@" -o "$2"
+	    shift
+	    ;;
+	esac
+	;;
+      *.c)
+	cfile=$1
+	set x "$@" "$1"
+	shift
+	;;
+      *)
+	set x "$@" "$1"
+	shift
+	;;
+    esac
+  fi
+  shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+  # If no `-o' option was seen then we might have been invoked from a
+  # pattern rule where we don't need one.  That is ok -- this is a
+  # normal compilation that the losing compiler can handle.  If no
+  # `.c' file was seen then we are probably linking.  That is also
+  # ok.
+  exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use `[/.-]' here to ensure that we don't use the same name
+# that we are using for the .o file.  Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d
+while true; do
+  if mkdir "$lockdir" >/dev/null 2>&1; then
+    break
+  fi
+  sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+  mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+  mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/configure.in
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/configure.in	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/configure.in	(revision 21994)
@@ -0,0 +1,44 @@
+AC_INIT(tap, 1.01)
+AC_CONFIG_SRCDIR(src/tap.c)
+AM_INIT_AUTOMAKE([foreign])
+AC_CONFIG_HEADERS([src/config.h])
+AC_GNU_SOURCE
+AC_PROG_CC
+AC_PROG_LIBTOOL
+AC_PROG_INSTALL
+
+# Checks for libraries
+case "$host" in
+	*-*-*freebsd4*)
+		LDFLAGS="$LDFLAGS -pthread"
+		HAVE_LIBPTHREAD=1
+		;;
+	*)
+		AC_CHECK_LIB(pthread, main)
+		;;
+esac
+
+dnl build tests at the same time as the source code
+AC_ARG_ENABLE(tests,
+  [AS_HELP_STRING(--enable-tests,build tests at same time as source)],
+  [AC_MSG_RESULT(test building enabled)
+   tests=true],
+   [tests=false])
+AM_CONDITIONAL(BUILD_TESTS, test x$tests = xtrue)
+
+# Checks for header files
+AC_HEADER_STDC
+AC_CHECK_HEADERS([stdlib.h])
+AC_CHECK_HEADERS([pthread.h])
+
+# Checks for  typedefs, structures, and compiler characteristics.
+AC_C_CONST
+
+# Checks for library functions.
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS([atexit])
+
+AC_CONFIG_FILES([Makefile
+		 src/Makefile
+		])
+AC_OUTPUT
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/src/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/src/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/src/.cvsignore	(revision 21994)
@@ -0,0 +1,13 @@
+.deps
+.libs
+Makefile
+Makefile.in
+libtap.la
+tap.lo
+config.h
+config.h.in
+stamp-h1
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/src/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/src/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/src/Makefile.am	(revision 21994)
@@ -0,0 +1,9 @@
+TEST_LTLIBS = libtap.la
+libtap_la_SOURCES = tap.c tap.h
+noinst_HEADERS = tap.h
+
+noinst_LTLIBRARIES = $(TEST_LTLIBS)
+
+#man_MANS = tap.3
+EXTRA_DIST = $(man_MANS)
+
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/src/tap.3
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/src/tap.3	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/src/tap.3	(revision 21994)
@@ -0,0 +1,380 @@
+.Dd December 20, 2004
+.Os
+.Dt TAP 3
+.Sh NAME
+.Nm tap
+.Nd write tests that implement the Test Anything Protocol
+.Sh SYNOPSIS
+.In tap.h
+.Sh DESCRIPTION
+The
+.Nm
+library provides functions for writing test scripts that produce output
+consistent with the Test Anything Protocol.  A test harness that parses
+this protocol can run these tests and produce useful reports indicating
+their success or failure.
+.Ss PRINTF STRINGS
+In the descriptions that follow, for any function that takes as the
+last two parameters
+.Dq Fa char * , Fa ...
+it can be assumed that the
+.Fa char *
+is a
+.Fn printf
+-like format string, and the optional arguments are values to be placed
+in that string.
+.Ss TEST PLANS
+.Bl -tag -width indent
+.It Xo
+.Ft int
+.Fn plan_tests "unsigned int"
+.Xc
+.It Xo
+.Ft int
+.Fn plan_no_plan "void"
+.Xc
+.It Xo
+.Ft int
+.Fn plan_skip_all "char *" "..."
+.Xc
+.El
+.Pp
+You must first specify a test plan.  This indicates how many tests you
+intend to run, and allows the test harness to notice if any tests were
+missed, or if the test program exited prematurely.
+.Pp
+To do this, use
+.Fn plan_tests ,
+which returns the number of planned tests.  The function will cause
+your program to exit prematurely if you specify 0 tests.
+.Pp
+In some situations you may not know how many tests you will be running, or
+you are developing your test program, and do not want to update the
+.Fn plan_tests
+parameter every time you make a change.  For those situations use
+.Fn plan_no_plan .
+It returns 1, and indicates to the test harness that an indeterminate number
+of tests will be run.
+.Pp
+Both
+.Fn plan_tests
+and
+.Fn plan_no_plan
+will cause your test program to exit prematurely with a diagnostic
+message if they are called more than once.
+.Pp
+If your test program detects at run time that some required functionality
+is missing (for example, it relies on a database connection which is not
+present, or a particular configuration option that has not been included
+in the running kernel) use
+.Fn plan_skip_all ,
+passing as parameters a string to display indicating the reason for skipping
+the tests.
+.Ss SIMPLE TESTS
+.Bl -tag -width indent
+.It Xo
+.Ft unsigned int
+.Fn ok "expression" "char *" "..."
+.Xc
+.It Xo
+.Ft unsigned int
+.Fn ok1 "expression"
+.Xc
+.It Xo
+.Ft unsigned int
+.Fn pass "char *" "..."
+.Xc
+.It Xo
+.Ft unsigned int
+.Fn fail "char *" "..."
+.Xc
+.El
+.Pp
+Tests are implemented as expressions checked by calls to the
+.Fn ok
+and
+.Fn ok1
+macros.  In both cases
+.Fa expression
+should evaluate to true if the test succeeded.
+.Pp
+.Fn ok
+allows you to specify a name, or comment, describing the test which will
+be included in the output.
+.Fn ok1
+is for those times when the expression to be tested is self
+explanatory and does not need an associated comment.  In those cases
+the test expression becomes the comment.
+.Pp
+These four calls are equivalent:
+.Bd -literal -offset indent
+int i = 5;
+
+ok(i == 5, "i equals 5");      /* Overly verbose */
+ok(i == 5, "i equals %d", i);  /* Just to demonstrate printf-like
+                                  behaviour of the test name */
+ok(i == 5, "i == 5");          /* Needless repetition */
+ok1(i == 5);                   /* Just right */
+.Ed
+.Pp
+It is good practice to ensure that the test name describes the meaning
+behind the test rather than what you are testing.  Viz
+.Bd -literal -offset indent
+ok(db != NULL, "db is not NULL");            /* Not bad, but */
+ok(db != NULL, "Database conn. succeeded");  /* this is better */
+.Ed
+.Pp
+.Fn ok
+and
+.Fn ok1
+return 1 if the expression evaluated to true, and 0 if it evaluated to
+false.  This lets you chain calls from
+.Fn ok
+to
+.Fn diag
+to only produce diagnostic output if the test failed.  For example, this
+code will include diagnostic information about why the database connection
+failed, but only if the test failed.
+.Bd -literal -offset indent
+ok(db != NULL, "Database conn. succeeded") ||
+    diag("Database error code: %d", dberrno);
+.Ed
+.Pp
+You also have
+.Fn pass
+and
+.Fn fail .
+From the Test::More documentation:
+.Bd -literal -offset indent
+Sometimes you just want to say that the tests have passed.
+Usually the case is you've got some complicated condition
+that is difficult to wedge into an ok().  In this case,
+you can simply use pass() (to declare the test ok) or fail
+(for not ok).
+
+Use these very, very, very sparingly.
+.Ed
+.Pp
+These are synonyms for ok(1, ...) and ok(0, ...).
+.Ss SKIPPING TESTS
+.Bl -tag -width indent
+.It Xo
+.Ft int
+.Fn skip "unsigned int" "char *" "..."
+.Xc
+.It Xo
+.Fn skip_start "expression" "unsigned int" "char *" "..."
+.Xc
+.It Xo
+.Fn skip_end
+.Xc
+.El
+.Pp
+Sets of tests can be skipped.  Ordinarily you would do this because
+the test can't be run in this particular testing environment.
+.Pp
+For example, suppose some tests should be run as root.  If the test is
+not being run as root then the tests should be skipped.  In this 
+implementation, skipped tests are flagged as being ok, with a special
+message indicating that they were skipped.  It is your responsibility
+to ensure that the number of tests skipped (the first parameter to
+.Fn skip )
+is correct for the number of tests to skip.
+.Pp
+One way of implementing this is with a
+.Dq do { } while(0);
+loop, or an
+.Dq if( ) { } else { }
+construct, to ensure that there are no additional side effects from the
+skipped tests.
+.Bd -literal -offset indent
+if(getuid() != 0) {
+        skip(1, "because test only works as root");
+} else {
+        ok(do_something_as_root() == 0, "Did something as root");
+}
+.Ed
+.Pp
+Two macros are provided to assist with this.  The previous example could
+be re-written as follows.
+.Bd -literal -offset indent
+skip_start(getuid() != 0, 1, "because test only works as root");
+
+ok(do_something_as_root() == 0, "Did something as root");
+
+skip_end();
+.Ed
+.Ss MARKING TESTS AS Dq TODO
+.Bl -tag -width indent
+.It Xo
+.Ft void
+.Fn todo_start "char *" "..."
+.Xc
+.It Xo
+.Ft void
+.Fn todo_end "void"
+.Xc
+.El
+.Pp
+Sets of tests can be flagged as being
+.Dq TODO .
+These are tests that you expect to fail, probably because you haven't
+fixed a bug, or finished a new feature yet.  These tests will still be
+run, but with additional output that indicates that they are expected
+to fail.  Should a test start to succeed unexpectedly, tools like
+.Xr prove 1
+will indicate this, and you can move the test out of the todo
+block.  This is much more useful than simply commenting out (or
+.Dq #ifdef 0 ... #endif )
+the tests.
+.Bd -literal -offset indent
+todo_start("dwim() not returning true yet");
+
+ok(dwim(), "Did what the user wanted");
+
+todo_end();
+.Ed
+.Pp
+Should
+.Fn dwim
+ever start succeeding you will know about it as soon as you run the
+tests.  Note that
+.Em unlike
+the
+.Fn skip_*
+family, additional code between
+.Fn todo_start
+and
+.Fn todo_end
+.Em is
+executed.
+.Ss SKIP vs. TODO
+From the Test::More documentation;
+.Bd -literal -offset indent
+If it's something the user might not be able to do, use SKIP.
+This includes optional modules that aren't installed, running
+under an OS that doesn't have some feature (like fork() or
+symlinks), or maybe you need an Internet connection and one
+isn't available.
+
+If it's something the programmer hasn't done yet, use TODO.
+This is for any code you haven't written yet, or bugs you have
+yet to fix, but want to put tests in your testing script 
+(always a good idea).
+.Ed
+.Ss DIAGNOSTIC OUTPUT
+.Bl -tag -width indent
+.It Xo
+.Fr unsigned int
+.Fn diag "char *" "..."
+.Xc
+.El
+.Pp
+If your tests need to produce diagnostic output, use
+.Fn diag .
+It ensures that the output will not be considered by the TAP test harness.
+.Fn diag
+adds the necessary trailing
+.Dq \en
+for you.
+.Bd -literal -offset indent
+diag("Expected return code 0, got return code %d", rcode);
+.Ed
+.Pp
+.Fn diag
+always returns 0.
+.Ss EXIT STATUS
+.Bl -tag -width indent
+.It Xo
+.Fr int
+.Fn exit_status void
+.Xc
+.El
+.Pp
+For maximum compatability your test program should return a particular
+exit code.  This is calculated by
+.Fn exit_status
+so it is sufficient to always return from
+.Fn main
+with either
+.Dq return exit_status();
+or
+.Dq exit(exit_status());
+as appropriate.
+.Sh ENVIRONMENT
+The following environment variables affect
+.Nm .
+.Bl -tag -width indent
+.It Ev HARNESS_ACTIVE
+Causes an extra
+.Dq \en
+to be printed before any diagnostic failure output generated by
+.Nm .
+This variable is normally set if tests are being run under Perl's
+Test::Harness.
+.El
+.Sh EXAMPLES
+The
+.Pa tests
+directory in the source distribution contains numerous tests of
+.Nm
+functionality, written using
+.Nm .
+Examine them for examples of how to construct test suites.
+.Sh COMPATABILITY
+.Nm
+strives to be compatible with the Perl Test::More and Test::Harness 
+modules.  The test suite verifies that
+.Nm
+is bug-for-bug compatible with their behaviour.  This is why some
+functions which would more naturally return nothing return constant
+values.
+.Pp
+If the
+.Lb libpthread
+is found at compile time,
+.Nm
+.Em should
+be thread safe.  Indications to the contrary (and test cases that expose
+incorrect behaviour) are very welcome.
+.Sh SEE ALSO
+.Xr Test::More 1 ,
+.Xr Test::Harness 1 ,
+.Xr prove 1
+.Sh STANDARDS
+.Nm
+requires a
+.St -isoC-99
+compiler.  Some of the
+.Nm
+functionality is implemented as variadic macros, and that functionality
+was not formally codified until C99.  Patches to use
+.Nm
+with earlier compilers that have their own implementation of variadic
+macros will be gratefully received.
+.Sh HISTORY
+.Nm
+was written to help improve the quality and coverage of the FreeBSD
+regression test suite, and released in the hope that others find it
+a useful tool to help improve the quality of their code.
+.Sh AUTHORS
+.An "Nik Clayton" Aq nik@ngo.org.uk ,
+.Aq nik@FreeBSD.org
+.Pp
+.Nm
+would not exist without the efforts of
+.An "Michael G Schwern" Aq schqern@pobox.com ,
+.An "Andy Lester" Aq andy@petdance.com ,
+and the countless others who have worked on the Perl QA programme.
+.Sh BUGS
+Ideally, running the tests would have no side effects on the behaviour
+of the application you are testing.  However, it is not always possible
+to avoid them.  The following side effects of using
+.Nm
+are known.
+.Bl -bullet -offset indent
+.It
+stdout is set to unbuffered mode after calling any of the
+.Fn plan_*
+functions.
+.El
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/src/tap.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/src/tap.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/src/tap.c	(revision 21994)
@@ -0,0 +1,430 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "tap.h"
+
+static int no_plan = 0;
+static int skip_all = 0;
+static int have_plan = 0;
+static unsigned int test_count = 0; /* Number of tests that have been run */
+static unsigned int e_tests = 0; /* Expected number of tests to run */
+static unsigned int failures = 0; /* Number of tests that failed */
+static char *todo_msg = NULL;
+static char *todo_msg_fixed = "libtap malloc issue";
+static int todo = 0;
+static int test_died = 0;
+
+/* Encapsulate the pthread code in a conditional.  In the absence of
+   libpthread the code does nothing */
+#ifdef HAVE_LIBPTHREAD
+#include <pthread.h>
+static pthread_mutex_t M = PTHREAD_MUTEX_INITIALIZER;
+# define LOCK pthread_mutex_lock(&M);
+# define UNLOCK pthread_mutex_unlock(&M);
+#else
+# define LOCK
+# define UNLOCK
+#endif
+
+static void _expected_tests(unsigned int);
+static void _tap_init(void);
+static void _cleanup(void);
+
+/*
+ * Generate a test result.
+ *
+ * ok -- boolean, indicates whether or not the test passed.
+ * test_name -- the name of the test, may be NULL
+ * test_comment -- a comment to print afterwards, may be NULL
+ */
+unsigned int
+_gen_result(int ok, const char *func, char *file, unsigned int line,
+            char *test_name, ...)
+{
+    va_list ap;
+    char *local_test_name = NULL;
+    char *c;
+    int name_is_digits;
+
+    LOCK;
+
+    test_count++;
+
+    /* Start by taking the test name and performing any printf()
+       expansions on it */
+    if(test_name != NULL) {
+        va_start(ap, test_name);
+        vasprintf(&local_test_name, test_name, ap);
+        va_end(ap);
+
+        /* Make sure the test name contains more than digits
+           and spaces.  Emit an error message and exit if it
+           does */
+        if(local_test_name) {
+            name_is_digits = 1;
+            for(c = local_test_name; *c != '\0'; c++) {
+                if(!isdigit(*c) && !isspace(*c)) {
+                    name_is_digits = 0;
+                    break;
+                }
+            }
+
+            if(name_is_digits) {
+                diag("    You named your test '%s'.  You shouldn't use numbers for your test names.", local_test_name);
+                diag("    Very confusing.");
+            }
+        }
+    }
+
+    if(!ok) {
+        printf("not ");
+        failures++;
+    }
+
+    printf("ok %d", test_count);
+
+    if(test_name != NULL) {
+        printf(" - ");
+
+        /* Print the test name, escaping any '#' characters it
+           might contain */
+        if(local_test_name != NULL) {
+            flockfile(stdout);
+            for(c = local_test_name; *c != '\0'; c++) {
+                if(*c == '#')
+                    fputc('\\', stdout);
+                fputc((int)*c, stdout);
+            }
+            funlockfile(stdout);
+        } else { /* vasprintf() failed, use a fixed message */
+            printf("%s", todo_msg_fixed);
+        }
+    }
+
+    /* If we're in a todo_start() block then flag the test as being
+       TODO.  todo_msg should contain the message to print at this
+       point.  If it's NULL then asprintf() failed, and we should
+       use the fixed message.
+
+       This is not counted as a failure, so decrement the counter if
+       the test failed. */
+    if(todo) {
+        printf(" # TODO %s", todo_msg ? todo_msg : todo_msg_fixed);
+        if(!ok)
+            failures--;
+    }
+
+    printf("\n");
+
+    if(!ok) {
+        if(getenv("HARNESS_ACTIVE") != NULL)
+            fputs("\n", stderr);
+
+        diag("    Failed %stest (%s:%s() at line %d)",
+             todo ? "(TODO) " : "", file, func, line);
+    }
+    free(local_test_name);
+
+    UNLOCK;
+
+    /* We only care (when testing) that ok is positive, but here we
+       specifically only want to return 1 or 0 */
+    return ok ? 1 : 0;
+}
+
+/*
+ * Initialise the TAP library.  Will only do so once, however many times it's
+ * called.
+ */
+void
+_tap_init(void)
+{
+    static int run_once = 0;
+
+    if(!run_once) {
+        atexit(_cleanup);
+
+        /* stdout needs to be unbuffered so that the output appears
+           in the same place relative to stderr output as it does 
+           with Test::Harness */
+        setbuf(stdout, 0);
+        run_once = 1;
+    }
+}
+
+/*
+ * Note that there's no plan.
+ */
+int
+plan_no_plan(void)
+{
+
+    LOCK;
+
+    _tap_init();
+
+    if(have_plan != 0) {
+        fprintf(stderr, "You tried to plan twice!\n");
+        test_died = 1;
+        UNLOCK;
+        exit(255);
+    }
+
+    have_plan = 1;
+    no_plan = 1;
+
+    UNLOCK;
+
+    return 1;
+}
+
+/*
+ * Note that the plan is to skip all tests
+ */
+int
+plan_skip_all(char *reason)
+{
+
+    LOCK;
+
+    _tap_init();
+
+    skip_all = 1;
+
+    printf("1..0");
+
+    if(reason != NULL)
+        printf(" # Skip %s", reason);
+
+    printf("\n");
+
+    UNLOCK;
+
+    exit(0);
+}
+
+/*
+ * Note the number of tests that will be run.
+ */
+int
+plan_tests(unsigned int tests)
+{
+
+    LOCK;
+
+    _tap_init();
+
+    if(have_plan != 0) {
+        fprintf(stderr, "You tried to plan twice!\n");
+        test_died = 1;
+        UNLOCK;
+        exit(255);
+    }
+
+    if(tests == 0) {
+        fprintf(stderr, "You said to run 0 tests!  You've got to run something.\n");
+        test_died = 1;
+        UNLOCK;
+        exit(255);
+    }
+
+    have_plan = 1;
+
+    _expected_tests(tests);
+
+    UNLOCK;
+
+    return e_tests;
+}
+
+unsigned int
+diag(char *fmt, ...)
+{
+    va_list ap;
+
+    fputs("# ", stderr);
+
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+
+    fputs("\n", stderr);
+
+    return 0;
+}
+
+void
+_expected_tests(unsigned int tests)
+{
+
+    printf("1..%d\n", tests);
+    e_tests = tests;
+}
+
+int
+skip(unsigned int n, char *fmt, ...)
+{
+    va_list ap;
+    char *skip_msg;
+
+    LOCK;
+
+    va_start(ap, fmt);
+    asprintf(&skip_msg, fmt, ap);
+    va_end(ap);
+
+    while(n-- > 0) {
+        test_count++;
+        printf("ok %d # skip %s\n", test_count,
+               skip_msg != NULL ?
+               skip_msg : "libtap():malloc() failed");
+    }
+
+    free(skip_msg);
+
+    UNLOCK;
+
+    return 1;
+}
+
+void
+todo_start(char *fmt, ...)
+{
+    va_list ap;
+
+    LOCK;
+
+    va_start(ap, fmt);
+    vasprintf(&todo_msg, fmt, ap);
+    va_end(ap);
+
+    todo = 1;
+
+    UNLOCK;
+}
+
+void
+todo_end(void)
+{
+
+    LOCK;
+
+    todo = 0;
+    free(todo_msg);
+
+    UNLOCK;
+}
+
+int
+exit_status(void)
+{
+    int r;
+
+    LOCK;
+
+    /* If there's no plan, just return the number of failures */
+    if(no_plan || !have_plan) {
+        UNLOCK;
+        return failures;
+    }
+
+    /* Ran too many tests?  Return the number of tests that were run
+       that shouldn't have been */
+    if(e_tests < test_count) {
+        r = test_count - e_tests;
+        UNLOCK;
+        return r;
+    }
+
+    /* Return the number of tests that failed + the number of tests
+       that weren't run */
+    r = failures + e_tests - test_count;
+    UNLOCK;
+
+    return r;
+}
+
+/*
+ * Cleanup at the end of the run, produce any final output that might be
+ * required.
+ */
+void
+_cleanup(void)
+{
+
+    LOCK;
+
+    /* If plan_no_plan() wasn't called, and we don't have a plan,
+       and we're not skipping everything, then something happened
+       before we could produce any output */
+    if(!no_plan && !have_plan && !skip_all) {
+        diag("Looks like your test died before it could output anything.");
+        UNLOCK;
+        return;
+    }
+
+    if(test_died) {
+        diag("Looks like your test died just after %d.", test_count);
+        UNLOCK;
+        return;
+    }
+
+
+    /* No plan provided, but now we know how many tests were run, and can
+       print the header at the end */
+    if(!skip_all && (no_plan || !have_plan)) {
+        printf("1..%d\n", test_count);
+    }
+
+    if((have_plan && !no_plan) && e_tests < test_count) {
+        diag("Looks like you planned %d %s but ran %d extra.",
+             e_tests, e_tests == 1 ? "test" : "tests", test_count - e_tests);
+        UNLOCK;
+        return;
+    }
+
+    if((have_plan || !no_plan) && e_tests > test_count) {
+        diag("Looks like you planned %d %s but only ran %d.",
+             e_tests, e_tests == 1 ? "test" : "tests", test_count);
+        UNLOCK;
+        return;
+    }
+
+    if(failures)
+        diag("Looks like you failed %d %s of %d.",
+             failures, failures == 1 ? "test" : "tests", test_count);
+
+    UNLOCK;
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/src/tap.h
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/src/tap.h	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/src/tap.h	(revision 21994)
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* '## __VA_ARGS__' is a gcc'ism. C99 doesn't allow the token pasting
+   and requires the caller to add the final comma if they've ommitted
+   the optional arguments */
+#ifdef __GNUC__
+# define ok(e, test, ...) ((e) ?					\
+			   _gen_result(1, __func__, __FILE__, __LINE__,	\
+				       test, ## __VA_ARGS__) :		\
+			   _gen_result(0, __func__, __FILE__, __LINE__,	\
+				       test, ## __VA_ARGS__))
+
+# define ok1(e) ((e) ?							\
+		 _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \
+		 _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e))
+
+# define pass(test, ...) ok(1, test, ## __VA_ARGS__);
+# define fail(test, ...) ok(0, test, ## __VA_ARGS__);
+
+# define skip_start(test, n, fmt, ...)			\
+	do {						\
+		if((test)) {				\
+			skip(n, fmt, ## __VA_ARGS__);	\
+			continue;			\
+		}
+#elif __STDC_VERSION__ >= 199901L /* __GNUC__ */
+# define ok(e, ...) ((e) ?						\
+		     _gen_result(1, __func__, __FILE__, __LINE__,	\
+				 __VA_ARGS__) :				\
+		     _gen_result(0, __func__, __FILE__, __LINE__,	\
+				 __VA_ARGS__))
+
+# define ok1(e) ((e) ?							\
+		 _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \
+		 _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e))
+
+# define pass(...) ok(1, __VA_ARGS__);
+# define fail(...) ok(0, __VA_ARGS__);
+
+# define skip_start(test, n, ...)			\
+	do {						\
+		if((test)) {				\
+			skip(n,  __VA_ARGS__);		\
+			continue;			\
+		}
+#else /* __STDC_VERSION__ */
+# error "Needs gcc or C99 compiler for variadic macros."
+#endif /* __STDC_VERSION__ */
+
+#define skip_end() } while(0);
+
+unsigned int _gen_result(int, const char *, char *, unsigned int, char *, ...);
+
+int plan_no_plan(void);
+int plan_skip_all(char *);
+int plan_tests(unsigned int);
+
+unsigned int diag(char *, ...);
+
+int skip(unsigned int, char *, ...);
+
+void todo_start(char *, ...);
+void todo_end(void);
+
+int exit_status(void);
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/.cvsignore	(revision 21994)
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/Makefile.am	(revision 21994)
@@ -0,0 +1,7 @@
+SUBDIRS=	diag
+SUBDIRS+=	fail
+SUBDIRS+=	ok
+SUBDIRS+=	pass
+SUBDIRS+=	plan
+SUBDIRS+=	skip
+SUBDIRS+=	todo
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/README
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/README	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/README	(revision 21994)
@@ -0,0 +1,12 @@
+Most of the tests follow the same pattern.
+
+ * test.pl that uses Test::More, and demonstrates whatever functionality 
+   that we're trying to test.  This is the reference code.
+
+ * test.c, which tests the libtap reimplementation of the same functionality.
+
+ * test.t, which compiles the .c program, runs both test scripts, and then 
+   diffs their output to make sure it's identical.
+
+   Right now, test.t is identical in every directory.  This sucks somewhat.
+   It should either be a symlink to a common script
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/diag/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/diag/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/diag/.cvsignore	(revision 21994)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/diag/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/diag/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/diag/Makefile.am	(revision 21994)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/diag/test.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/diag/test.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/diag/test.c	(revision 21994)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	plan_tests(2);
+
+	rc = diag("A diagnostic message");
+	diag("Returned: %d", rc);
+
+	/* Make sure the failure is passed through */
+	ok(1, "test 1") || diag("ok() failed, and shouldn't");
+	ok(0, "test 2") || diag("ok() passed, and shouldn't");
+
+	return exit_status();
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/diag/test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/diag/test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/diag/test.pl	(revision 21994)
@@ -0,0 +1,16 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+plan tests => 2;
+
+$rc = diag("A diagnostic message");
+diag("Returned: $rc");
+
+ok(1, 'test 1') or diag "ok() failed, and shouldn't";
+ok(0, 'test 2') or diag "ok() passed, and shouldn't";
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/diag/test.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/diag/test.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/diag/test.t	(revision 21994)
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+echo '1..7'
+
+perl $srcdir/test.pl 2>/dev/null >test.pl.out
+perlstatus=$?
+
+./test > test.c.out 2>&1
+cstatus=$?
+
+if grep "^# A diagnostic message$" test.c.out > /dev/null ; then
+    echo "ok 1 - found a diagnostic message"
+else
+    echo "not ok 1 - found a diagnostic message"
+    retval=1
+fi
+
+if grep "^# Returned: 0$" test.c.out > /dev/null ; then
+    echo "ok 2 - diag() expected return value" 
+else
+    echo "not ok 2 - diag() expected return value" 
+    retval=1
+fi
+
+if grep "^#     Failed test (.*test.c:main() at line 43)$" test.c.out > /dev/null ; then
+    echo "ok 3 - 'failed test at line' diag" 
+else
+    echo "not ok 3 - 'failed test at line' diag" 
+    retval=1
+fi
+
+if grep "^# ok() passed, and shouldn't$" test.c.out > /dev/null ; then
+    echo "ok 4 - expected diag"
+else
+    echo "ok 4 - expected diag"
+    retval=1
+fi
+
+if grep "^# Looks like you failed 1 test of 2.$" test.c.out > /dev/null ; then
+    echo "ok 5 - failed 1 test"
+ else
+    echo "ok 5 - failed 1 test"
+    retval=1
+fi
+
+sed -e '/^#/D' test.c.out > tmp
+mv tmp test.c.out
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 6 - TAP output is identical'
+else
+	retval=1
+	echo 'not ok 6 - TAP output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 7 - status code'
+else
+	retval=1
+	echo 'not ok 7 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/fail/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/fail/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/fail/.cvsignore	(revision 21994)
@@ -0,0 +1,15 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/fail/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/fail/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/fail/Makefile.am	(revision 21994)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/fail/test.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/fail/test.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/fail/test.c	(revision 21994)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(2);
+	diag("Returned: %d", rc);
+
+	rc = fail("test to fail");
+	diag("Returned: %d", rc);
+
+	rc = fail("test to fail %s", "with extra string");
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/fail/test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/fail/test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/fail/test.pl	(revision 21994)
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 2;
+diag("Returned: " . sprintf('%d', $rc));
+
+$rc = fail('test to fail');
+diag("Returned: $rc");
+
+$rc = fail('test to fail with extra string');
+diag("Returned: $rc");
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/fail/test.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/fail/test.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/fail/test.t	(revision 21994)
@@ -0,0 +1,74 @@
+#!/bin/sh
+
+echo '1..8'
+
+perl $srcdir/test.pl 2>/dev/null > test.pl.out
+perlstatus=$?
+
+./test > test.c.out 2>&1 
+cstatus=$?
+
+if grep "^# Returned: 2$" test.c.out >/dev/null ; then
+  echo "ok 1 - expected return value";
+else
+  echo "not ok 1 - expected return value";
+  retval=1
+fi
+
+if grep "^#     Failed test (.*test.c:main() at line 39)$" test.c.out >/dev/null ; then
+  echo "ok 2 - failed expected test";
+else
+  echo "not ok 2 - failed expected test";
+  retval=1
+fi
+
+if grep "^# Returned: 0$" test.c.out >/dev/null ; then
+  echo "ok 3 - expected return value";
+else
+  echo "not ok 3 - expected return value";
+  retval=1
+fi
+
+if grep "^#     Failed test (.*test.c:main() at line 42)$" test.c.out >/dev/null ; then
+  echo "ok 4 - failed expected test";
+else
+  echo "not ok 4 - failed expected test";
+  retval=1
+fi
+  
+if grep "^# Returned: 0$" test.c.out >/dev/null ; then
+  echo "ok 5 - expected return value";
+else
+  echo "not ok 5 - expected return value";
+  retval=1
+fi
+
+if grep "^# Looks like you failed 2 tests of 2.$" test.c.out >/dev/null ; then
+  echo "ok 6 - expected return value";
+else
+  echo "not ok 6 - expected return value";
+  retval=1
+fi
+
+sed -e '/^#/D' test.c.out > tmp
+mv tmp test.c.out
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 7 - output is identical'
+else
+	retval=1
+	echo 'not ok 7 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 8 - status code'
+else
+	retval=1
+	echo 'not ok 8 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/.cvsignore	(revision 21994)
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/Makefile.am	(revision 21994)
@@ -0,0 +1,3 @@
+SUBDIRS  =	ok
+SUBDIRS +=	ok-hash
+SUBDIRS +=	ok-numeric
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/.cvsignore	(revision 21994)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/Makefile.am	(revision 21994)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.c	(revision 21994)
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(4);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "Test with no hash");
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "Test with one # hash");
+	diag("Returned: %d", rc);
+
+        rc = ok(1, "Test with # two # hashes");
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "Test with ## back to back hashes");
+	diag("Returned: %d", rc);
+	
+	return exit_status();
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.pl	(revision 21994)
@@ -0,0 +1,24 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 4;
+diag("Returned: " . sprintf("%d", $rc));
+
+
+$rc = ok(1, 'Test with no hash');
+diag("Returned: $rc");
+
+$rc = ok(1, 'Test with one # hash');
+diag("Returned: $rc");
+
+$rc = ok(1, 'Test with # two # hashes');
+diag("Returned: $rc");
+
+$rc = ok(1, 'Test with ## back to back hashes');
+diag("Returned: $rc");
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.t	(revision 21994)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/.cvsignore	(revision 21994)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/Makefile.am	(revision 21994)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.c	(revision 21994)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(3);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "First test");
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "1");
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "Third test");
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.pl	(revision 21994)
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 3;
+diag("Returned: " . sprintf("%d", $rc));
+
+
+$rc = ok(1, 'First test');
+diag("Returned: $rc");
+
+$rc = ok(1, '1');
+diag("Returned: $rc");
+
+$rc = ok(1, 'Third test');
+diag("Returned: $rc");
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.t	(revision 21994)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok/.cvsignore	(revision 21994)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok/Makefile.am	(revision 21994)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok/test.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok/test.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok/test.c	(revision 21994)
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(5);
+	diag("Returned: %d", rc);
+
+	rc = ok(1 == 1, "1 equals 1");
+	diag("Returned: %d", rc);
+
+	rc = ok(1 == 1, "1 equals %d", 1);
+	diag("Returned: %d", rc);
+
+	rc = ok1(1 == 1);
+	diag("Returned: %d", rc);
+
+	rc = ok(1 == 2, "1 equals 2");
+	diag("Returned: %d", rc);
+
+	rc = ok1(1 == 2);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok/test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok/test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok/test.pl	(revision 21994)
@@ -0,0 +1,27 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 5;
+diag("Returned: " . sprintf("%d", $rc));
+
+
+$rc = ok(1 == 1, '1 equals 1');	# Test ok() passes when it should
+diag("Returned: $rc");
+
+$rc = ok(1 == 1, '1 equals 1'); # Used for %d testing in test.c
+diag("Returned: $rc");
+
+$rc = ok(1 == 1, '1 == 1');	# Test ok1() passes when it should
+diag("Returned: $rc");
+
+$rc = ok(1 == 2, '1 equals 2');	# Test ok() fails when it should
+diag("Returned: $rc");
+
+$rc = ok(1 == 2, '1 == 2');	# Test ok1() fails when it should
+diag("Returned: $rc");
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok/test.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok/test.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/ok/ok/test.t	(revision 21994)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/pass/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/pass/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/pass/.cvsignore	(revision 21994)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/pass/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/pass/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/pass/Makefile.am	(revision 21994)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/pass/test.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/pass/test.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/pass/test.c	(revision 21994)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(2);
+	diag("Returned: %d", rc);
+
+	rc = pass("test to pass");
+	diag("Returned: %d", rc);
+
+	rc = pass("test to pass %s", "with extra string");
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/pass/test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/pass/test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/pass/test.pl	(revision 21994)
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 2;
+diag("Returned: " . sprintf('%d', $rc));
+
+$rc = pass('test to pass');
+diag("Returned: $rc");
+
+$rc = pass('test to pass with extra string');
+diag("Returned: $rc");
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/pass/test.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/pass/test.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/pass/test.t	(revision 21994)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/.cvsignore	(revision 21994)
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/Makefile.am	(revision 21994)
@@ -0,0 +1,7 @@
+SUBDIRS  =	no-tests
+SUBDIRS +=	no_plan
+SUBDIRS +=	not-enough-tests
+SUBDIRS +=	too-many-plans
+SUBDIRS +=	too-many-tests
+SUBDIRS +=	sane
+SUBDIRS +=	skip_all
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no-tests/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no-tests/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no-tests/.cvsignore	(revision 21994)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no-tests/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no-tests/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no-tests/Makefile.am	(revision 21994)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.c	(revision 21994)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(0);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.pl	(revision 21994)
@@ -0,0 +1,14 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 0;
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.t	(revision 21994)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no_plan/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no_plan/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no_plan/.cvsignore	(revision 21994)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no_plan/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no_plan/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no_plan/Makefile.am	(revision 21994)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.c	(revision 21994)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_no_plan();
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.pl	(revision 21994)
@@ -0,0 +1,14 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+my $rc = 0;
+
+use Test::More;
+
+$rc = plan qw(no_plan);
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.t	(revision 21994)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/.cvsignore	(revision 21994)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/Makefile.am	(revision 21994)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.c	(revision 21994)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(1);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.pl	(revision 21994)
@@ -0,0 +1,20 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 1;
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
+
+$rc = ok(1);
+diag("Returned: $rc");
+
+$rc = ok(1);
+diag("Returned: $rc");
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.t	(revision 21994)
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	# comment this out until we're exit-code compatible with Test::More
+	#retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/sane/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/sane/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/sane/.cvsignore	(revision 21994)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/sane/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/sane/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/sane/Makefile.am	(revision 21994)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/sane/test.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/sane/test.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/sane/test.c	(revision 21994)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(1);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/sane/test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/sane/test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/sane/test.pl	(revision 21994)
@@ -0,0 +1,14 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 1;
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/sane/test.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/sane/test.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/sane/test.t	(revision 21994)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/.cvsignore	(revision 21994)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/Makefile.am	(revision 21994)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/plan.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/plan.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/plan.c	(revision 21994)
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "tap.h"
+
+/* Run pre-defined tests on the test library to make sure that the basic
+   functionality works, and it can be used to test itself afterwards */
+
+int
+main(int argc, char *argv[])
+{
+	plan_skip_all("No good reason");
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.c	(revision 21994)
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_skip_all("No good reason");
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.pl	(revision 21994)
@@ -0,0 +1,11 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan skip_all => "No good reason";
+diag("Returned: " . sprintf("%d", $rc));
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.t	(revision 21994)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/.cvsignore	(revision 21994)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/Makefile.am	(revision 21994)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.c	(revision 21994)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(1);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	rc = plan_tests(1);
+	diag("Returned: %d", rc);
+
+	rc = ok(0, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.pl	(revision 21994)
@@ -0,0 +1,20 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 1;
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
+
+$rc = plan tests => 1;
+diag("Returned: $rc");
+
+$rc = ok(0);
+diag("Returned: $rc");
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.t	(revision 21994)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/.cvsignore	(revision 21994)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/Makefile.am	(revision 21994)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.c	(revision 21994)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(5);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	rc = ok(0, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.pl	(revision 21994)
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 5;
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
+
+$rc = ok(0);
+diag("Returned: $rc");
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.t	(revision 21994)
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+    # we're not exit-status compatible with Test::More yet
+	#retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/skip/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/skip/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/skip/.cvsignore	(revision 21994)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/skip/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/skip/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/skip/Makefile.am	(revision 21994)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/skip/test.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/skip/test.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/skip/test.c	(revision 21994)
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+	unsigned int side_effect = 0;
+
+	rc = plan_tests(4);
+	diag("Returned: %d", rc);
+
+	rc = ok(1 == 1, "1 equals 1");	/* Should always work */
+	diag("Returned: %d", rc);
+
+	do {
+		if(1) {
+			rc = skip(1, "Testing skipping");
+			continue;
+		}
+		
+		side_effect++;
+
+		ok(side_effect == 1, "side_effect checked out");
+
+	} while(0);
+
+	diag("Returned: %d", rc);
+
+	skip_start(1 == 1, 1, "Testing skipping #2");
+
+	side_effect++;
+	rc = ok(side_effect == 1, "side_effect checked out");
+	diag("Returned: %d", rc);
+
+	skip_end();
+
+	rc = ok(side_effect == 0, "side_effect is %d", side_effect);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/skip/test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/skip/test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/skip/test.pl	(revision 21994)
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 4;
+diag("Returned: " . sprintf("%d", $rc));
+
+my $side_effect = 0;		# Check whether skipping has side effects
+
+$rc = ok(1 == 1, '1 equals 1');	# Test ok() passes when it should
+diag("Returned: $rc");
+
+# Start skipping
+SKIP: {
+	$rc = skip "Testing skipping", 1;
+
+	$side_effect++;
+
+	$rc = ok($side_effect == 1, '$side_effect checked out');
+}
+
+diag("Returned: $rc");
+
+SKIP: {
+	$rc = skip "Testing skipping #2", 1;
+	diag("Returned: $rc");
+
+	$side_effect++;
+
+	$rc = ok($side_effect == 1, '$side_effect checked out');
+	diag("Returned: $rc");
+}
+
+$rc = ok($side_effect == 0, "side_effect is $side_effect");
+diag("Returned: $rc");
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/skip/test.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/skip/test.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/skip/test.t	(revision 21994)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/todo/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/todo/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/todo/.cvsignore	(revision 21994)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/todo/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/todo/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/todo/Makefile.am	(revision 21994)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/todo/test.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/todo/test.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/todo/test.c	(revision 21994)
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+	unsigned int side_effect = 0;
+
+	rc = plan_tests(5);
+	diag("Returned: %d", rc);
+
+	rc = ok(1 == 1, "1 equals 1");	/* Should always work */
+	diag("Returned: %d", rc);
+
+	todo_start("For testing purposes");
+
+	side_effect++;
+
+	/* This test should fail */
+	rc = ok(side_effect == 0, "side_effect checked out");
+	diag("Returned: %d", rc);
+
+	/* This test should unexpectedly succeed */
+	rc = ok(side_effect == 1, "side_effect checked out");
+	diag("Returned: %d", rc);
+
+	todo_end();
+
+	todo_start("Testing printf() %s in todo_start()", "expansion");
+
+	rc = ok(0, "dummy test");
+	diag("Returned: %d", rc);
+
+	todo_end();
+
+	rc = ok(side_effect == 1, "side_effect is %d", side_effect);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/todo/test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/todo/test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/todo/test.pl	(revision 21994)
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 5;
+diag("Returned: " . sprintf("%d", $rc));
+
+my $side_effect = 0;		# Check whether TODO has side effects
+
+$rc = ok(1 == 1, '1 equals 1');	# Test ok() passes when it should
+diag("Returned: $rc");
+
+# Start TODO tests
+TODO: {
+	local $TODO = 'For testing purposes';
+
+	$side_effect++;
+
+	# This test should fail
+	$rc = ok($side_effect == 0, 'side_effect checked out');
+	diag("Returned: $rc");
+
+	# This test should unexpectedly succeed
+	$rc = ok($side_effect == 1, 'side_effect checked out');
+	diag("Returned: $rc");
+}
+
+TODO: {
+	local $TODO = 'Testing printf() expansion in todo_start()';
+
+	$rc = ok(0, 'dummy test');
+	diag("Returned: $rc");
+}
+
+$rc = ok($side_effect == 1, "side_effect is $side_effect");
+diag("Returned: $rc");
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/todo/test.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/todo/test.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tap/tests/todo/test.t	(revision 21994)
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+# Test:;More prints diagnostic from TODO tests on stdout
+# http://rt.cpan.org/Ticket/Display.html?id=14982
+sed '/^#/D' test.pl.out > tmp
+mv tmp test.pl.out
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tests.c
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tests.c	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/nebclient/tests/tests.c	(revision 21994)
@@ -0,0 +1,126 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include "nebclient.h"
+#include "tap.h"
+
+#define neb_ok(server, ...) \
+    if (!ok(__VA_ARGS__)) { \
+        diag("nebErr: %s", nebErr(server)); \
+    }
+
+int main (int argc, char **argv) {
+    nebServer       *server = NULL;
+    char            *key = "foobarbaz";
+
+    plan_tests(22);
+
+    if (getenv("NEB_SERVER")) {
+        server = nebServerAlloc(getenv("NEB_SERVER"));
+    } else {
+        server = nebServerAlloc(NULL);
+    }
+    ok(server, "server not NULL");
+
+    printf("# server set to %s\n", server->endpoint);
+
+    {
+        char        *URI = NULL;
+        char        *filename;
+       
+        filename = nebCreate(server, key, NULL, &URI);
+
+        neb_ok(server, filename, "create object");
+        ok(URI, "URI not NULL");
+        neb_ok(server, nebDelete(server, key), "delete object");
+
+        nebFree(URI);
+        nebFree(filename);
+    }
+
+    {
+        char        *URI = NULL;
+        int         fh;
+       
+        fh = nebOpenCreate(server, key, NULL, &URI);
+
+        neb_ok(server, fh > -1, "create new object filehandle");
+        ok(URI, "URI not NULL");
+
+        nebFree(URI);
+        close(fh);
+    }
+
+    {
+        int         fh;
+
+        fh = nebOpen(server, key, NEB_READ);
+
+        neb_ok(server, fh, "open object for reading");
+
+        close(fh);
+    }
+
+    {
+        int         fh;
+
+        fh = nebOpen(server, key, NEB_WRITE);
+
+        neb_ok(server, fh, "open object for writing");
+
+        close(fh);
+    }
+
+
+    neb_ok(server, nebReplicate(server, key, NULL, NULL), "replicate object");
+
+    neb_ok(server, nebOpen(server, key, NEB_WRITE) < 0, "write to object with multiple instances");
+
+    neb_ok(server, nebCull(server, key), "cull object");
+
+    neb_ok(server, nebStat(server, key), "stat object");
+
+    neb_ok(server, nebLock(server, key, NEB_WRITE), "lock object write");
+    neb_ok(server, nebUnlock(server, key, NEB_WRITE), "unlock object write");
+
+    neb_ok(server, nebLock(server, key, NEB_READ), "lock object read");
+    neb_ok(server, nebUnlock(server, key, NEB_READ), "unlock object read");
+
+    {
+        nebObjectInstances *locations = NULL;
+
+        locations = nebFindInstances(server, key, NULL);
+
+        neb_ok(server, locations, "locations not NULL");
+        ok(locations && locations->n == 1, "find instances");
+
+        nebObjectInstancesFree(locations);
+    }
+
+    {
+        char        *filename = NULL;
+       
+        filename = nebFind(server, key);
+
+        neb_ok(server, filename, "find file name");
+
+        nebFree(filename);
+    }
+
+
+    neb_ok(server, nebCopy(server, key, "copyiedfile"), "copy object");
+
+    neb_ok(server, nebDelete(server, key), "delete object");
+
+    neb_ok(server, nebMove(server, "copyiedfile", "movedfile"), "move object");
+
+    if (!nebDelete(server, "movedfile")) {
+        diag( "cleanup failed %s\n", nebErr(server));
+    }
+
+    nebServerFree(server);
+
+    return exit_status();
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/scripts/bench_test.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/scripts/bench_test.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/scripts/bench_test.pl	(revision 21994)
@@ -0,0 +1,41 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings FATAL => qw( all );
+
+use lib "./lib";
+
+use Benchmark qw( timethese );
+use Nebulous::Client;
+
+my $neb = Nebulous::Client->new(
+    proxy   => 'http://localhost:80/nebulous'
+);
+
+my $key = shift || 'foobar';
+
+eval { $neb->delete( $key ); };
+
+my $fh = $neb->create( $key );
+close $fh;
+
+
+timethese( -3,
+    {
+        'stat' => sub {
+            $neb->stat( $key );
+        },
+    }
+);
+
+$neb->delete( $key );
+
+timethese( -3,
+    {
+        'create/delete' => sub {
+            my $fh = $neb->create( $key );
+            close $fh;
+            $neb->delete( $key );
+        },
+    }
+);
Index: /tags/ipp-1-X/rel-0_06/Nebulous/scripts/nebulous.cgi
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/scripts/nebulous.cgi	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/scripts/nebulous.cgi	(revision 21994)
@@ -0,0 +1,15 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id
+ 
+use strict;
+use warnings FATAL => qw( all );
+
+use SOAP::Transport::HTTP;
+use Nebulous::Server;
+   
+SOAP::Transport::HTTP::CGI
+    -> dispatch_to( 'Nebulous::Server' )
+    -> handle;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/scripts/ptest.pl
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/scripts/ptest.pl	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/scripts/ptest.pl	(revision 21994)
@@ -0,0 +1,49 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings FATAL => qw( all );
+
+use lib "./lib";
+
+use Nebulous::Client;
+
+my $neb = Nebulous::Client->new(
+    proxy   => 'http://localhost:80/nebulous'
+);
+
+my $key = shift || 'foobar';
+my $kids = shift || 1;
+
+foreach my $id ( 1..$kids ) {
+    my $pid = fork;
+
+    unless ( $pid )  {
+        my $fname = "${key}_$id";
+        my $fh = $neb->open_create( $fname );
+        die "can't create file $fname" unless $fh;
+
+        print $fh "fooby\n";
+
+        close $fh;
+
+        $fh = $neb->open( $fname, 'read' ) or die "can't open file";
+        close $fh;
+
+        $neb->lock( $fname, 'read' );
+        $neb->unlock( $fname, 'read' );
+        $neb->replicate( $fname );
+        $neb->cull( $fname );
+        $neb->find( $fname );
+        $neb->copy( $fname, $fname . "_copy" );
+        $neb->move( $fname, $fname . "_move" );
+        $neb->delete( $fname . "_copy" );
+        $neb->delete( $fname . "_move" );
+
+        exit 0;
+    }
+}
+
+while ( $kids ) {
+    wait();
+    $kids --;
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/.cvsignore	(revision 21994)
@@ -0,0 +1,3 @@
+TEST
+htdocs
+logs
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/00_distribution.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/00_distribution.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/00_distribution.t	(revision 21994)
@@ -0,0 +1,25 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2005  Joshua Hoblitt
+#
+# $Id: 00_distribution.t,v 1.2 2007-05-02 01:07:56 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use lib qw( ./lib ./t );
+
+use Test::More;
+
+# example taken from Test::Distribution Pod
+
+BEGIN {
+    eval {
+        require Test::Distribution;
+    };
+    if($@) {
+        plan skip_all => 'Test::Distribution not installed';
+    } else {
+        import Test::Distribution not => [qw( versions use podcover )];
+    }
+}
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/01_load.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/01_load.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/01_load.t	(revision 21994)
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 01_load.t,v 1.7 2005-06-30 02:35:06 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use lib qw( ./t ./lib );
+
+use Test::More tests => 8;
+
+BEGIN { use_ok( 'Nebulous::Client' ); }
+BEGIN { use_ok( 'Nebulous::Client::Log' ); }
+BEGIN { use_ok( 'Nebulous::Client::HTTP' ); }
+BEGIN { use_ok( 'Nebulous::Util' ); }
+BEGIN { use_ok( 'Nebulous::Server' ); }
+BEGIN { use_ok( 'Nebulous::Server::SQL' ); }
+BEGIN { use_ok( 'Nebulous::Server::Log' ); }
+BEGIN { use_ok( 'Nebulous::Server::SOAP' ); }
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/02_server_setup.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/02_server_setup.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/02_server_setup.t	(revision 21994)
@@ -0,0 +1,39 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 02_server_setup.t,v 1.5 2006-12-08 03:29:19 jhoblitt Exp $
+
+use strict;
+use warnings;
+
+use Test::More tests => 2;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Test::Nebulous;
+
+Test::Nebulous->setup;
+
+isa_ok(
+    Nebulous::Server->new(
+        dsn         => "DBI:mysql:database=test:host=localhost",
+        dbuser      => "test",
+        dbpasswd    => "",
+    ),
+    "Nebulous::Server"
+);
+
+Test::Nebulous->setup;
+
+eval {
+    Nebulous::Server->new(
+        dsn         => "DBI:mysql:database=foobar:host=localhost",
+        dbuser      => "baz",
+        dbpasswd    =>"boo",
+    );
+};
+like( $@, qr/DBI connect.*? failed/, "bad dsn/user/pass" );
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/03_server_create_object.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/03_server_create_object.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/03_server_create_object.t	(revision 21994)
@@ -0,0 +1,347 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 03_server_create_object.t,v 1.22 2008-01-25 02:06:08 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 65;
+
+use lib qw( ./t ./lib );
+
+use File::ExtAttr qw( getfattr );
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+use Test::URI;
+use URI::Split qw( uri_split );
+
+my $test_xattr = undef;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("foo");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("neb:/foo");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("neb://node01/foo");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("neb://node02/foo");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("/foo");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), '/foo', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+{
+    # key
+    my $uri = $neb->create_object("neb:///foo");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("/foo/");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), '/foo/', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("neb:/foo/");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), '/foo/', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("foo/");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo/', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("foo/bar");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo/bar"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo/bar', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("/foo/bar");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo/bar"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), '/foo/bar', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, volume
+    my $uri = $neb->create_object("foo", "node01");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+}
+
+Test::Nebulous->setup;
+
+{
+    # volume name override
+    my $uri = $neb->create_object("neb://node02/foo", "node01");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    ok($neb->find_instances("foo"), 'object key exists');
+    uri_scheme_ok($uri, 'file');
+}
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+    $neb->create_object("foo");
+};
+like($@, qr/Duplicate entry/, "object already exists");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("neb:/foo");
+    $neb->create_object("neb:/foo");
+};
+like($@, qr/Duplicate entry/, "object already exists");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo", 'node03');
+};
+like($@, qr/node03 is not available/, "request volume this is full");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("neb://node03/foo");
+};
+like($@, qr/node03 is not available/, "request volume this is full");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo", 'node04');
+};
+like($@, qr/node04 is not available/, "request volume with allocate = FALSE, available = FALSE");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("neb://node04/foo");
+};
+like($@, qr/node04 is not available/, "request volume with allocate = FALSE, available = FALSE");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo", 'node05');
+};
+like($@, qr/node05 is not available/, "request volume with allocate = FALSE , available = TRUE");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("neb://node05/foo");
+};
+like($@, qr/node05 is not available/, "request volume with allocate = FALSE , available = TRUE");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo", 'node06');
+};
+like($@, qr/node06 is not available/, "request volume with allocate = TRUE, available = FALSE");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("neb://node06/foo");
+};
+like($@, qr/node06 is not available/, "request volume with allocate = TRUE, available = FALSE");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo", 99);
+};
+like($@, qr/did not pass the \'is valid volume name\'/, "volume name doesn't exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("neb://99/foo");
+};
+like($@, qr/is not a valid volume name/, "volume name doesn't exist");
+
+Test::Nebulous->setup;
+
+eval {
+    # volume name override
+    $neb->create_object("neb://99/foo", "node01");
+};
+like($@, qr/is not a valid volume name/, "volume name doesn't exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object();
+};
+like($@, qr/1 - 2 were expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object(1, "node01", 3);
+};
+like($@, qr/1 - 2 were expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/04_server_replicate_object.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/04_server_replicate_object.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/04_server_replicate_object.t	(revision 21994)
@@ -0,0 +1,124 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 04_server_replicate_object.t,v 1.10 2007-05-08 02:27:42 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 16;
+
+use lib qw( ./t ./lib );
+
+use File::ExtAttr qw( getfattr );
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+use Test::URI;
+use URI::Split qw( uri_split );
+
+my $test_xattr = undef;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+{
+    # key
+    $neb->create_object("foo");
+    my $uri = $neb->replicate_object("foo");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, $volume
+    $neb->create_object("foo");
+    my $uri = $neb->replicate_object("foo", "node01");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "file exists");
+    uri_scheme_ok($uri, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+    is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, $volume
+    $neb->create_object("foo");
+    my $uri1 = $neb->replicate_object("foo", "node01");
+    my $uri2 = $neb->replicate_object("foo", "node02");
+
+    {
+        my ($scheme, $auth, $path, $query, $frag) = uri_split($uri1);
+        ok(-e $path, "file exists");
+        uri_scheme_ok($uri1, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+        is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+    }
+
+    {
+        my ($scheme, $auth, $path, $query, $frag) = uri_split($uri2);
+        ok(-e $path, "file exists");
+        uri_scheme_ok($uri2, 'file');
+
+SKIP: {
+    skip "requires xattr support", 1 unless $test_xattr;
+        is(getfattr($path, 'user.nebulous_key'), 'foo', 'user.nebulous_key xattr');
+}
+    }
+}
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->replicate_object('foo');
+};
+like($@, qr/is valid object key/, 'storage object does not exist');
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+    $neb->replicate_object('foo', 'bar');
+};
+like($@, qr/is valid volume name/, 'storage volume does not exist');
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->replicate_object();
+};
+like($@, qr/1 - 2 were expected/, 'no params');
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+    $neb->replicate_object('foo', 'node01', 3);
+};
+like($@, qr/1 - 2 were expected/, 'too many params');
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/05_server_lock_object.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/05_server_lock_object.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/05_server_lock_object.t	(revision 21994)
@@ -0,0 +1,127 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 05_server_lock_object.t,v 1.8 2007-05-03 22:10:14 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 13;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+{
+    $neb->create_object("foo");
+
+    ok($neb->lock_object("foo", "read"), "read lock");
+}
+
+Test::Nebulous->setup;
+
+{
+    $neb->create_object("foo");
+
+    ok($neb->lock_object("foo", "read"), "read lock");
+    ok($neb->lock_object("foo", "read"), "read lock");
+}
+
+Test::Nebulous->setup;
+
+{
+    $neb->create_object("foo");
+
+    ok($neb->lock_object("foo", "write"), "write lock");
+}
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->lock_object("foo", "read");
+};
+like($@, qr/is valid object key/, "storage object does not exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->lock_object("foo", "write");
+};
+like($@, qr/is valid object key/, "storage object does not exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo", "write");
+    $neb->lock_object("foo", "write");
+};
+like($@, qr/can not write lock twice/, "can not write lock twice");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo", "read");
+    $neb->lock_object("foo", "write");
+};
+like($@, qr/can not write lock after read lock/, "can not write lock after read lock");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo", "write");
+    $neb->lock_object("foo", "read");
+};
+like($@, qr/can not read lock after write lock/, "can not read lock after write lock");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->lock_object();
+};
+like($@, qr/2 were expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo");
+};
+like($@, qr/2 were expected/, "not enough params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo", "both");
+};
+like($@, qr/is read or write/, "not read or write");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo", 'read', 3);
+};
+like($@, qr/2 were expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/06_server_unlock_object.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/06_server_unlock_object.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/06_server_unlock_object.t	(revision 21994)
@@ -0,0 +1,142 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 06_server_unlock_object.t,v 1.8 2007-05-03 22:10:14 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 14;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+{
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo", "read");
+
+    ok($neb->unlock_object("foo", "read"), "read unlock");
+}
+
+Test::Nebulous->setup;
+
+{
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo", "read");
+    $neb->lock_object("foo", "read");
+
+    ok($neb->unlock_object("foo", "read"), "read unlock");
+    ok($neb->unlock_object("foo", "read"), "read unlock");
+}
+
+Test::Nebulous->setup;
+
+{
+    $neb->create_object("foo");
+
+    $neb->lock_object("foo", "write");
+
+    ok($neb->unlock_object("foo", "write"), "write unlock");
+}
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->unlock_object("foo", "read");
+};
+like($@, qr/is valid object key/, "storage object does not exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->unlock_object("foo", "write");
+};
+like($@, qr/is valid object key/, "storage object does not exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->unlock_object("foo", "read");
+};
+like($@, qr/can not remove non-existant read lock/, "no lock set");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->unlock_object("foo", "write");
+};
+like($@, qr/can not remove non-existant write lock/, "no lock set");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+    $neb->lock_object("foo", "write");
+
+    $neb->unlock_object("foo", "read");
+};
+like($@, qr/can not have a read lock under a write lock/, "read unlock under write lock");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+    $neb->lock_object("foo", "read");
+
+    $neb->unlock_object("foo", "write");
+};
+like($@, qr/can not have a write lock under a read lock/, "write unlock under read lock");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->unlock_object();
+};
+like($@, qr/2 were expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->unlock_object("foo");
+};
+like($@, qr/2 were expected/, "not enough params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->unlock_object("foo", "both");
+};
+like($@, qr/is read or write/, "not read or write");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->unlock_object("foo", 'read', 3);
+};
+like($@, qr/2 were expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/07_server_find_instances.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/07_server_find_instances.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/07_server_find_instances.t	(revision 21994)
@@ -0,0 +1,119 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 07_server_find_instances.t,v 1.8 2007-05-03 01:44:24 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 15;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::URI;
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("foo");
+
+    my $locations = $neb->find_instances("foo");
+
+    uri_scheme_ok($locations->[0], 'file');
+    is($uri, $locations->[0], "URIs match");
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri1 = $neb->create_object("foo");
+    my $uri2 = $neb->replicate_object("foo");
+
+    my $locations = $neb->find_instances("foo");
+
+    uri_scheme_ok($locations->[0], 'file');
+    uri_scheme_ok($locations->[1], 'file');
+    ok(eq_set([$uri1, $uri2], $locations), "URIs match");
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, volume
+    my $uri = $neb->create_object('foo', 'node01');
+
+    my $locations = $neb->find_instances('foo', 'node01');
+
+    uri_scheme_ok($locations->[0], 'file');
+    is($uri, $locations->[0], "URIs match");
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri1 = $neb->create_object("foo");
+    my $uri2 = $neb->replicate_object("foo");
+
+    my $locations = $neb->find_instances("foo", "node01");
+
+    uri_scheme_ok($locations->[0], 'file');
+    uri_scheme_ok($locations->[1], 'file');
+    ok(eq_set([$uri1, $uri2], $locations), "URIs match");
+}
+
+# object exists but instance is on a different volume
+Test::Nebulous->setup;
+
+eval {
+    # key, volume
+    my $uri = $neb->create_object('foo', 'node01');
+
+    my $locations = $neb->find_instances('foo', 'node02');
+};
+like($@, qr/no instances on storage volume/, 'instances on a different volume');
+
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->find_instances('foo');
+};
+like($@, qr/is valid object key/, "storage object does not exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+    $neb->find_instances('foo', 'bar');
+};
+like($@, qr/is valid volume name/, "storage volume does not exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->find_instances();
+};
+like($@, qr/1 - 2 were expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+    $neb->find_instances('foo', 'node01', 3);
+};
+like($@, qr/1 - 2 were expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/08_server_delete_instance.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/08_server_delete_instance.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/08_server_delete_instance.t	(revision 21994)
@@ -0,0 +1,73 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 08_server_delete_instance.t,v 1.8 2007-05-03 01:44:24 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 8;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+{
+    my $uri = $neb->create_object("foo");
+
+    ok($neb->delete_instance($uri), "delete instance");
+}
+
+Test::Nebulous->setup;
+
+{
+    my $uri1 = $neb->create_object("foo");
+    my $uri2 = $neb->replicate_object("foo");
+
+    ok($neb->delete_instance($uri1), "delete instance");
+
+    my $locations = $neb->find_instances("foo");
+
+    is($locations->[0], $uri2, "instance remains");
+
+    ok($neb->delete_instance( $uri2 ), "delete instance");
+
+    eval {
+        $neb->find_instances("foo");
+    };
+    like($@, qr/is valid object key/, "storage object was deleted");
+}
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->delete_instance("file:/foo");
+};
+like($@, qr/no instance is associated with uri/, "uri does not exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->delete_instance();
+};
+like($@, qr/1 was expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->delete_instance("foo", 2);
+};
+like($@, qr/1 was expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/09_server_stat_object.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/09_server_stat_object.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/09_server_stat_object.t	(revision 21994)
@@ -0,0 +1,72 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 09_server_stat_object.t,v 1.11 2007-05-03 03:21:28 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 12;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+{
+    $neb->create_object("foo");
+
+    my $info = $neb->stat_object("foo");
+
+    is(scalar @$info, 7, "number of columns");
+}
+
+Test::Nebulous->setup;
+
+{
+    $neb->create_object("foo", "node01");
+
+    my $info = $neb->stat_object("foo");
+
+    is(scalar @$info, 7,                       "number of columns");
+    is(@$info[0], 1,                           "so_id");
+    is(@$info[1], "foo",                       "ext_id");
+    is(@$info[2], 0,                           "read lock");
+    is(@$info[3], undef,                       "write lock");
+    like(@$info[4], qr/....-..-.. ..:..:../,   "epoch");
+    like(@$info[5], qr/....-..-.. ..:..:../,   "mtime");
+    is(@$info[6], 1,                           "instances");
+}
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->stat_object("foo");
+};
+like($@, qr/is valid object key/, "object does not exist");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->stat_object();
+};
+like($@, qr/1 was expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+    $neb->stat_object("foo", 2);
+};
+like($@, qr/1 was expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/10_server_is_valid_volume_name.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/10_server_is_valid_volume_name.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/10_server_is_valid_volume_name.t	(revision 21994)
@@ -0,0 +1,36 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 10_server_is_valid_volume_name.t,v 1.3 2007-03-28 22:02:11 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 3;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+ok($neb->_is_valid_volume_name('node01'), "valid volume name");
+
+Test::Nebulous->setup;
+
+ok($neb->_is_valid_volume_name('node02'), "valid volume name");
+
+Test::Nebulous->setup;
+
+is($neb->_is_valid_volume_name('node99'), undef, "invalid volume name");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/11_server_is_valid_object_key.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/11_server_is_valid_object_key.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/11_server_is_valid_object_key.t	(revision 21994)
@@ -0,0 +1,38 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 11_server_is_valid_object_key.t,v 1.1 2007-05-03 01:44:24 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 2;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+{
+    $neb->create_object('foo');
+
+    ok($neb->_is_valid_object_key('foo'), "valid object key");
+}
+
+Test::Nebulous->setup;
+
+{
+    ok(!$neb->_is_valid_object_key('foo'), "invalid object key");
+}
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/12_server_find_objects.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/12_server_find_objects.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/12_server_find_objects.t	(revision 21994)
@@ -0,0 +1,68 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 12_server_find_objects.t,v 1.1 2007-04-26 23:45:03 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 6;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+# search for a regex of '' should match nothing
+{
+    # key
+    my $uri = $neb->create_object("foo");
+
+    my $keys = $neb->find_objects();
+
+    is(scalar @$keys, 0, 'number of keys found');
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri = $neb->create_object("foo");
+
+    my $keys = $neb->find_objects("foo");
+
+    is(scalar @$keys, 1, 'number of keys found');
+    is($keys->[0], "foo", "key name");
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $uri1 = $neb->create_object("foo");
+    my $uri2 = $neb->replicate_object("foo");
+
+    my $keys = $neb->find_objects("foo");
+
+    is(scalar @$keys, 1, 'number of keys found');
+    is($keys->[0], "foo", "key name");
+}
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->find_objects("foo", 3);
+};
+like($@, qr/1 was expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/13_server_rename_object.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/13_server_rename_object.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/13_server_rename_object.t	(revision 21994)
@@ -0,0 +1,73 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2007  Joshua Hoblitt
+#
+# $Id: 13_server_rename_object.t,v 1.2 2007-05-03 22:10:14 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 6;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+Test::Nebulous->setup;
+
+{
+    my $uri = $neb->create_object("foo");
+
+    $neb->rename_object("foo", "bar");
+
+    my $keys = $neb->find_objects('^foo$');
+    is(scalar @$keys, 0, 'number of keys found');
+    $keys = $neb->find_objects('^bar$');
+    is(scalar @$keys, 1, 'number of keys found');
+}
+
+Test::Nebulous->setup;
+
+# destination key exists
+eval {
+    $neb->create_object('foo');
+    $neb->create_object('bar');
+
+    $neb->rename_object('foo', 'bar');
+};
+like($@, qr/is not valid object key/, "too few params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->rename_object();
+};
+like($@, qr/2 were expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->rename_object("foo");
+};
+like($@, qr/2 were expected/, "too few params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object("foo");
+
+    $neb->rename_object("foo", "bar", "baz");
+};
+like($@, qr/2 were expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/14_server_xattr.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/14_server_xattr.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/14_server_xattr.t	(revision 21994)
@@ -0,0 +1,187 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2007  Joshua Hoblitt
+#
+# $Id: 14_server_xattr.t,v 1.2 2007-05-03 22:10:14 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More tests => 32;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Server;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $neb = Nebulous::Server->new(
+    dsn         => "DBI:mysql:database=test:host=localhost",
+    dbuser      => "test",
+    dbpasswd    => "",
+);
+
+# 1 key / xattr
+
+Test::Nebulous->setup;
+
+{
+    my $uri = $neb->create_object('foo');
+
+    ok($neb->setxattr_object('foo', 'bar', 'baz', 'create'), 'set object xattr');
+    {
+        my @xattrs = $neb->listxattr_object('foo');
+        is(scalar @xattrs, 1, 'number of xattrs');
+        is($xattrs[0], 'bar', 'xattr name');
+    }
+
+    my $value = $neb->getxattr_object('foo', 'bar');
+    is($value, 'baz', 'xattr value');
+
+    ok($neb->removexattr_object('foo', 'bar'), "remove object xattr");
+    {
+        my @xattrs = $neb->listxattr_object('foo');
+        is(scalar @xattrs, 0, 'number of xattrs');
+    }
+}
+
+# multiple xattrs
+
+Test::Nebulous->setup;
+
+{
+    my $uri = $neb->create_object('foo');
+
+    ok($neb->setxattr_object('foo', 'bar', 'baz', 'create'), 'set object xattr');
+    ok($neb->setxattr_object('foo', 'bonk', 'quix', 'create'), 'set object xattr');
+    
+    {
+        my @xattrs = $neb->listxattr_object('foo');
+        is(scalar @xattrs, 2, 'number of xattrs');
+        is($xattrs[0], 'bar', 'xattr name');
+        is($xattrs[1], 'bonk', 'xattr name');
+    }
+
+    my $value = $neb->getxattr_object('foo', 'bar');
+    is($value, 'baz', 'xattr value');
+    $value = $neb->getxattr_object('foo', 'bonk');
+    is($value, 'quix', 'xattr value');
+
+    ok($neb->removexattr_object('foo', 'bar'), "remove object xattr");
+    ok($neb->removexattr_object('foo', 'bonk'), "remove object xattr");
+    {
+        my @xattrs = $neb->listxattr_object('foo');
+        is(scalar @xattrs, 0, 'number of xattrs');
+    }
+}
+
+# replace xattrs
+
+Test::Nebulous->setup;
+
+{
+    my $uri = $neb->create_object('foo');
+
+    ok($neb->setxattr_object('foo', 'bar', 'baz', 'create'), 'set object xattr');
+    ok($neb->setxattr_object('foo', 'bar', 'quix', 'replace'), 're-set object xattr');
+    
+    {
+        my @xattrs = $neb->listxattr_object('foo');
+        is(scalar @xattrs, 1, 'number of xattrs');
+        is($xattrs[0], 'bar', 'xattr name');
+    }
+
+    my $value = $neb->getxattr_object('foo', 'bar');
+    is($value, 'quix', 'xattr value');
+
+    ok($neb->removexattr_object('foo', 'bar'), "remove object xattr");
+    {
+        my @xattrs = $neb->listxattr_object('foo');
+        is(scalar @xattrs, 0, 'number of xattrs');
+    }
+}
+
+# setxattr_object
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->setxattr_object();
+};
+like($@, qr/4 were expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+
+    $neb->setxattr_object('foo', 'bar');
+};
+like($@, qr/4 were expected/, "too few params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+
+    $neb->setxattr_object('foo', 'bar', 'baz');
+};
+like($@, qr/4 were expected/, "too few params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+
+    $neb->setxattr_object('foo', 'bar', 'baz', 'create', 'quix');
+};
+like($@, qr/4 were expected/, "too many params");
+
+# listxattr_object
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+
+    $neb->listxattr_object();
+};
+like($@, qr/1 was expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+
+    $neb->listxattr_object('foo', 'bar');
+};
+like($@, qr/1 was expected/, "too many params");
+
+# getxattr_object
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->getxattr_object();
+};
+like($@, qr/2 were expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+
+    $neb->getxattr_object('foo');
+};
+like($@, qr/2 were expected/, "too few params");
+
+Test::Nebulous->setup;
+
+eval {
+    $neb->create_object('foo');
+
+    $neb->getxattr_object('foo', 'bar', 'baz');
+};
+like($@, qr/2 were expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/50_client_new.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/50_client_new.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/50_client_new.t	(revision 21994)
@@ -0,0 +1,60 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 50_client_new.t,v 1.1 2005-12-03 02:52:31 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 4;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Client;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    isa_ok( $neb, "Nebulous::Client" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+        uri   => "http://example.com/PS/IPP/Nebulous/Client",
+    );
+
+    isa_ok( $neb, "Nebulous::Client" );
+}
+
+Test::Nebulous->setup;
+
+eval {
+    Nebulous::Client->new;
+};
+like( $@, qr/Mandatory parameter/, "no proxy" );
+
+Test::Nebulous->setup;
+
+eval {
+    Nebulous::Client->new(
+        proxy => "foo",
+        dog => "do"
+    );
+};
+like( $@, qr/not listed in the validation options/, "bad param" );
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/51_client_create.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/51_client_create.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/51_client_create.t	(revision 21994)
@@ -0,0 +1,87 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 51_client_create.t,v 1.3 2007-05-01 02:52:04 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 7;
+
+use lib qw( ./t ./lib );
+
+#use Nebulous::Client trace => 'debug';
+use Nebulous::Client;
+use Test::Nebulous;
+use Test::URI;
+use URI::Split qw( uri_split );
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    my $uri = $neb->create("foo");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "good filename");
+    uri_scheme_ok($uri, 'file');
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, volume
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    my $uri = $neb->create("foo", "node01");
+
+    my ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
+    ok(-e $path, "good filename");
+    uri_scheme_ok($uri, 'file');
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->create("foo");
+    is($neb->create("foo"), undef, "object already exists");
+}
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->create();
+};
+like($@, qr/1 - 2 were expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->create(1, 2, 3);
+};
+like($@, qr/1 - 2 were expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/51_client_open_create.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/51_client_open_create.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/51_client_open_create.t	(revision 21994)
@@ -0,0 +1,81 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 51_client_open_create.t,v 1.3 2007-05-01 02:52:04 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 5;
+
+use lib qw( ./t ./lib );
+
+#use Nebulous::Client trace => 'debug';
+use Nebulous::Client;
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    my $fh = $neb->open_create("foo");
+
+    is(ref $fh, 'GLOB', "good filehandle");
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, volume
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    my $fh = $neb->open_create("foo", "node01");
+
+    is(ref $fh, 'GLOB', "good filehandle");
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->open_create("foo");
+    is($neb->open_create("foo"), undef, "object already exists");
+}
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->open_create();
+};
+like($@, qr/1 - 2 were expected/, "no params");
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->open_create(1, 2, 3);
+};
+like($@, qr/1 - 2 were expected/, "too many params");
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/52_client_replicate.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/52_client_replicate.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/52_client_replicate.t	(revision 21994)
@@ -0,0 +1,101 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 52_client_replicate.t,v 1.1 2005-12-03 02:52:31 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 11;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Client;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    my $uri = $neb->replicate( "foo" );
+
+    ok( $uri, "good replication" );
+    ok( -e _get_file_path( $uri ), "file exists" );
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, $volume
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    my $uri = $neb->replicate( "foo", "node01" );
+
+    ok( $uri, "good replication" );
+    ok( -e _get_file_path( $uri ), "file exists" );
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, $volume
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    my $uri1 = $neb->replicate( "foo", "node01" );
+    my $uri2 = $neb->replicate( "foo", "node02" );
+
+    ok( $uri1, "good replication" );
+    ok( $uri2, "good replication" );
+    ok( -e _get_file_path( $uri1 ), "file exists" );
+    ok( -e _get_file_path( $uri2 ), "file exists" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    my $uri = $neb->replicate( "foo" );
+
+    is( $uri, undef, "storage object does not exist" );
+}
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->replicate();
+};
+like( $@, qr/1 - 2 were expected/, "no params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->replicate( 1, 2, 3 );
+};
+like( $@, qr/1 - 2 were expected/, "too many params" );
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/53_client_cull.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/53_client_cull.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/53_client_cull.t	(revision 21994)
@@ -0,0 +1,128 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 53_client_cull.t,v 1.5 2007-05-03 03:21:28 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 15;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Client;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create("foo");
+    $neb->replicate("foo");
+
+    my $uri = $neb->cull("foo");
+
+    ok($uri, "good cull");
+    ok(! -e _get_file_path($uri), "file doesn't exist");
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, $volume
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create("foo");
+    $neb->replicate("foo", "node01");
+
+    my $uri = $neb->cull("foo", "node01");
+
+    ok($uri, "good cull");
+    ok(! -e _get_file_path($uri), "file exists");
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create("foo");
+
+    $neb->replicate("foo", "node01");
+    $neb->replicate("foo", "node02");
+
+    my $uri1 = $neb->cull("foo");
+    my $uri2 = $neb->cull("foo");
+
+    ok($uri1, "good cull");
+    ok($uri2, "good cull");
+    ok(! -e _get_file_path($uri1), "file exists");
+    ok(! -e _get_file_path($uri2), "file exists");
+}
+
+Test::Nebulous->setup;
+
+{
+
+    # key, $volume
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    $neb->replicate( "foo", "node01" );
+    $neb->replicate( "foo", "node02" );
+
+    my $uri1 = $neb->cull( "foo", "node01" );
+    my $uri2 = $neb->cull( "foo", "node02" );
+
+    ok( $uri1, "good cull" );
+    ok( $uri2, "good cull" );
+    ok( ! -e _get_file_path( $uri1 ), "file exists" );
+    ok( ! -e _get_file_path( $uri2 ), "file exists" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    my $uri = $neb->cull( "foo" );
+
+    is( $uri, undef, "storage object does not exist" );
+}
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->cull();
+};
+like( $@, qr/1 - 2 were expected/, "no params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->cull( 1, 2, 3 );
+};
+like( $@, qr/1 - 2 were expected/, "too many params" );
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/54_client_lock.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/54_client_lock.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/54_client_lock.t	(revision 21994)
@@ -0,0 +1,273 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 54_client_lock.t,v 1.1 2005-12-03 02:52:31 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 19;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Client;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    # key, type
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    ok( $neb->lock( "foo", "read" ), "read lock" );
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, type, timeout
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    ok( $neb->lock( "foo", "read", 10 ), "read lock" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    ok( $neb->lock( "foo", "read" ), "read lock" );
+    ok( $neb->lock( "foo", "read" ), "read lock" );
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, type
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    ok( $neb->lock( "foo", "write" ), "write lock" );
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, type, timeout
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    ok( $neb->lock( "foo", "write", 10 ), "write lock" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    is( $neb->lock( "foo", "read" ), undef, "storage object does not exist" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    is( $neb->lock( "foo", "write" ), undef, "storage object does not exist" );
+}
+
+Test::Nebulous->setup;
+
+diag "testing a spinlock, this will be a litle slow...";
+
+eval {
+    local $SIG{ALRM} = sub { alarm 0; die "timeout"; };
+    alarm 8;
+
+    # key, type, timeout
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    $neb->lock( "foo", "read" );
+    $neb->lock( "foo", "write" );
+
+    alarm 0;
+};
+like( $@, qr/timeout/, "default spinlock" );
+
+Test::Nebulous->setup;
+
+diag "testing a spinlock, this will be a litle slow...";
+
+eval {
+    local $SIG{ALRM} = sub { alarm 0; die "timeout"; };
+    alarm 12;
+
+    # key, type, timeout
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    $neb->lock( "foo", "read" );
+    unless ( $neb->lock( "foo", "write" ) ) {
+        alarm 0;
+        die "gaveup";
+    }
+
+    alarm 0;
+};
+like( $@, qr/gaveup/, "default spinlock" );
+
+Test::Nebulous->setup;
+
+diag "testing a spinlock, this will be a litle slow...";
+
+eval {
+    local $SIG{ALRM} = sub { alarm 0; die "timeout"; };
+    alarm 3;
+
+    # key, type, timeout
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    $neb->lock( "foo", "read" );
+    $neb->lock( "foo", "write", 5 );
+
+    alarm 0;
+};
+like( $@, qr/timeout/, "specified spinlock" );
+
+Test::Nebulous->setup;
+
+diag "testing a spinlock, this will be a litle slow...";
+
+eval {
+    local $SIG{ALRM} = sub { alarm 0; die "timeout"; };
+    alarm 7;
+
+    # key, type, timeout
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    $neb->lock( "foo", "read" );
+    unless ( $neb->lock( "foo", "write", 5 ) ) {
+        alarm 0;
+        die "gaveup";
+    }
+
+    alarm 0;
+};
+
+like( $@, qr/gaveup/, "specified spinlock" );
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    $neb->lock( "foo", "write" );
+    is( $neb->lock( "foo", "write", 1 ), undef, "can not write lock twice" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    $neb->lock( "foo", "read" );
+    is( $neb->lock( "foo", "write", 1 ), undef, "can not write lock after read lock" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    $neb->lock( "foo", "write" );
+    is( $neb->lock( "foo", "read", 1 ), undef, "can not read lock after write lock" );
+}
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->lock();
+};
+like( $@, qr/2 - 3 were expected/, "no params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->lock( "foo" );
+};
+like( $@, qr/2 - 3 were expected/, "not enough params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->lock( "foo", "both" );
+};
+like( $@, qr/is read or write/, "not read or write" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->lock( "foo", 'read', 3, "bar" );
+};
+like( $@, qr/2 - 3 were expected/, "too many params" );
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/55_client_unlock.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/55_client_unlock.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/55_client_unlock.t	(revision 21994)
@@ -0,0 +1,170 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 55_client_unlock.t,v 1.1 2005-12-03 02:52:31 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 14;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Client;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+    $neb->lock( "foo", "read" );
+
+    ok( $neb->unlock( "foo", "read" ), "read unlock" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+    $neb->lock( "foo", "read" );
+    $neb->lock( "foo", "read" );
+
+    ok( $neb->unlock( "foo", "read" ), "read unlock" );
+    ok( $neb->unlock( "foo", "read" ), "read unlock" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+    $neb->lock( "foo", "write" );
+
+    ok( $neb->unlock( "foo", "write" ), "write unlock" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    is( $neb->unlock( "foo", "read" ), undef, "storage object does not exist" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    is( $neb->unlock( "foo", "write" ), undef, "storage object does not exist" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    is( $neb->unlock( "foo", "read" ), undef, "no lock set" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    is( $neb->unlock( "foo", "write" ), undef, "no lock set" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+    $neb->lock( "foo", "write" );
+
+    is( $neb->unlock( "foo", "read" ), undef, "read unlock under write lock" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+    $neb->lock( "foo", "read" );
+
+    is( $neb->unlock( "foo", "write" ), undef, "write unlock under read lock" );
+}
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->unlock();
+};
+like( $@, qr/2 were expected/, "no params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->unlock( "foo" );
+};
+like( $@, qr/2 were expected/, "not enough params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->unlock( "foo", "both" );
+};
+like( $@, qr/is read or write/, "not read or write" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->unlock( "foo", 'read', 3 );
+};
+like( $@, qr/2 were expected/, "too many params" );
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/56_client_find_instances.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/56_client_find_instances.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/56_client_find_instances.t	(revision 21994)
@@ -0,0 +1,124 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 56_client_find_instances.t,v 1.1 2005-12-03 02:52:31 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 19;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Client;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    my $locations = $neb->find_instances( "foo" );
+
+    is( scalar @$locations, 1, "found 1" );
+    like( @$locations[0], qr/file:/, "URIs match" );
+    ok( -e _get_file_path( @$locations[0] ), "URI matches file" );
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+    $neb->replicate( "foo" );
+
+    my $locations = $neb->find_instances( "foo" );
+
+    is( scalar @$locations, 2, "found 2" );
+    like( @$locations[0], qr/file:/, "URIs match" );
+    like( @$locations[1], qr/file:/, "URIs match" );
+    ok( -e _get_file_path( @$locations[0] ), "URI matches file" );
+    ok( -e _get_file_path( @$locations[1] ), "URI matches file" );
+}
+
+Test::Nebulous->setup;
+
+{
+    # key, volume
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    my $locations = $neb->find_instances( "foo", "node01" );
+
+    is( scalar @$locations, 1, "found 1" );
+    like( @$locations[0], qr/file:/, "URIs match" );
+    ok( -e _get_file_path( @$locations[0] ), "URI matches file" );
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+    $neb->replicate( "foo" );
+
+    my $locations = $neb->find_instances( "foo", "node01" );
+
+    is( scalar @$locations, 2, "found 2" );
+    like( @$locations[0], qr/file:/, "URIs match" );
+    like( @$locations[1], qr/file:/, "URIs match" );
+    ok( -e _get_file_path( @$locations[0] ), "URI matches file" );
+    ok( -e _get_file_path( @$locations[1] ), "URI matches file" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    is( $neb->find_instances( "foo" ), undef, "storage object does not exist" );
+}
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->find_instances();
+};
+like( $@, qr/1 - 2 were expected/, "no params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->find_instances( "foo", 'read', 3 );
+};
+like( $@, qr/1 - 2 were expected/, "too many params" );
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/57_client_find.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/57_client_find.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/57_client_find.t	(revision 21994)
@@ -0,0 +1,70 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 57_client_find.t,v 1.1 2005-12-03 02:52:31 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 4;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Client;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    my $uri = $neb->create( "foo" );
+
+    my $path = $neb->find( "foo" );
+
+    ok( -e $path, "file exists" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    my $path = $neb->find( "foo" );
+
+    ok( ! -e $path, "file doesn't exist" );
+}
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->find();
+};
+like( $@, qr/1 was expected/, "no params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->find( "foo", "bar" );
+};
+like( $@, qr/1 was expected/, "too many params" );
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/58_client_open.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/58_client_open.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/58_client_open.t	(revision 21994)
@@ -0,0 +1,111 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 58_client_open.t,v 1.1 2005-12-03 02:52:31 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 8;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Client;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+    my $fh = $neb->open( "foo", 'read' );
+
+    is( ref $fh, 'GLOB', "good filehandle" );
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+    my $fh = $neb->open( "foo", 'write' );
+
+    is( ref $fh, 'GLOB', "good filehandle" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    is( ref $neb->open( "foo", 'write' ), 'GLOB', "create new object" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    is( $neb->open( "foo", 'read' ), undef, "can't create new object" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+    $neb->replicate( "foo" );
+
+    is( $neb->open( "foo", 'write' ), undef,
+        "write to object with multiple instances" );
+}
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->open( "foo", 'bar' );
+};
+like( $@, qr/is read or write/, "2nd params not read or write" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->open();
+};
+like( $@, qr/2 were expected/, "no params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->open( 1, 'read', 3 );
+};
+like( $@, qr/2 were expected/, "too many params" );
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/59_client_delete.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/59_client_delete.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/59_client_delete.t	(revision 21994)
@@ -0,0 +1,83 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 59_client_delete.t,v 1.1 2005-12-03 02:52:31 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 7;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Client;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    ok( $neb->delete( "foo" ), "delete object" );
+
+    my $locations = $neb->find_instances( "foo" );
+
+    is( $locations, undef, "no instances" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+    $neb->replicate( "foo" );
+
+    ok( $neb->delete( "foo" ), "delete object" );
+
+    my $locations = $neb->find_instances( "foo" );
+
+    is( $locations, undef, "no instances" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    is( $neb->delete( "foo" ), undef, "delete non-existant object" );
+}
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->delete();
+};
+like( $@, qr/1 was expected/, "no params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->delete( "foo", 2 );
+};
+like( $@, qr/1 was expected/, "too many params" );
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/60_client_copy.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/60_client_copy.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/60_client_copy.t	(revision 21994)
@@ -0,0 +1,100 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 60_client_copy.t,v 1.2 2007-04-27 23:50:57 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 11;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Client;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    ok( $neb->copy( "foo", "foobar" ), "copied object" );
+
+    my $locations1 = $neb->find_instances( "foobar" );
+    my $locations2 = $neb->find_instances( "foobar" );
+
+    is( scalar @$locations1, 1, "old object has an instances" );
+    is( scalar @$locations2, 1, "new object has an instances" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    ok( $neb->copy( "foo", "foobar", "node01" ), "copied object" );
+
+    my $locations1 = $neb->find_instances( "foobar" );
+    my $locations2 = $neb->find_instances( "foobar" );
+
+    is( scalar @$locations1, 1, "old object has an instances" );
+    is( scalar @$locations2, 1, "new object has an instances" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    ok( ! $neb->copy( "foo", "foobar" ), "copy non-existant object" );
+
+    my $locations = $neb->find_instances( "foobar" );
+
+    is( $locations, undef, "new object has no instances" );
+}
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->copy();
+};
+like( $@, qr/2 - 3 were expected/, "no params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->copy( "foo" );
+};
+like( $@, qr/2 - 3 were expected/, "not enough params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->copy( "foo", "bar", "baz", "bong" );
+};
+like( $@, qr/2 - 3 were expected/, "too many params" );
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/61_client_move.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/61_client_move.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/61_client_move.t	(revision 21994)
@@ -0,0 +1,83 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 61_client_move.t,v 1.1 2005-12-03 02:52:31 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 8;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Client;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    ok( $neb->move( "foo", "foobar" ), "move object" );
+
+    my $locations1 = $neb->find_instances( "foo" );
+    my $locations2 = $neb->find_instances( "foobar" );
+
+    is( $locations1, undef, "old object has no instances" );
+    is( scalar @$locations2, 1, "new object has an instances" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    ok( ! $neb->move( "foo", "foobar" ), "move non-existant object" );
+
+    my $locations = $neb->find_instances( "foobar" );
+
+    is( $locations, undef, "new object has no instances" );
+}
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->move();
+};
+like( $@, qr/2 were expected/, "no params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->move( "foo" );
+};
+like( $@, qr/2 were expected/, "not enough params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->move( "foo", "bar", "baz" );
+};
+like( $@, qr/2 were expected/, "too many params" );
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/62_client_delete_instance.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/62_client_delete_instance.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/62_client_delete_instance.t	(revision 21994)
@@ -0,0 +1,92 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 62_client_delete_instance.t,v 1.1 2005-12-03 02:52:31 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 9;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Client;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    my $locations = $neb->find_instances( "foo" );
+
+    my $uri = $neb->delete_instance( @$locations[0] );
+
+    is( $uri, @$locations[0], "delete instance" );
+
+    ok( ! -e _get_file_path( @$locations[0] ), "deleted file" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+    $neb->replicate( "foo" );
+
+    my $uri1 = $neb->find_instances( "foo" )->[0];
+
+    ok( $neb->delete_instance( $uri1 ), "delete instance" );
+
+    my $uri2 = $neb->find_instances( "foo" )->[0];
+
+    isnt( $uri1, $uri2, "other instance remains" );
+
+    ok( $neb->delete_instance( $uri2 ), "delete instance" );
+
+    my $locations = $neb->find_instances( "foo" );
+
+    is( $locations, undef, "no remaning instances" );
+}
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    my $uri = $neb->delete_instance( "file:/foo" );
+
+    is( $uri, undef, "uri does not exist" );
+}
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->delete_instance();
+};
+like( $@, qr/1 was expected/, "no params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->delete_instance( "foo", 2 );
+};
+like( $@, qr/1 was expected/, "too many params" );
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/63_client_stat.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/63_client_stat.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/63_client_stat.t	(revision 21994)
@@ -0,0 +1,86 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 63_client_stat.t,v 1.3 2007-05-03 22:10:14 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 12;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Client;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    my $info = $neb->stat( "foo" );
+
+    is( scalar @$info, 7, "number of columns" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo", "node01" );
+
+    my $info = $neb->stat( "foo" );
+
+    is( scalar @$info, 7,                       "number of columns" );
+    is( @$info[0], 1,                           "so_id" );
+    is( @$info[1], "foo",                       "ext_id" );
+    is( @$info[2], 0,                           "read lock" );
+    is( @$info[3], undef,                       "write lock" );
+    like( @$info[4], qr/....-..-.. ..:..:../,   "epoch" );
+    like( @$info[5], qr/....-..-.. ..:..:../,   "mtime" );
+    is( @$info[6], 1,                           "instances" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    my $info = $neb->stat( "foo" );
+
+    is( $info, undef, "object does not exist" );
+}
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->stat();
+};
+like( $@, qr/1 was expected/, "no params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->stat( "foo", 2 );
+};
+like( $@, qr/1 was expected/, "too many params" );
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/64_client_find_objects.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/64_client_find_objects.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/64_client_find_objects.t	(revision 21994)
@@ -0,0 +1,92 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 64_client_find_objects.t,v 1.2 2008-01-25 20:54:04 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 7;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Client;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    my $keys = $neb->find_objects();
+
+    # undef indicates an error
+    is($keys, undef, 'undef is an error');
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+
+    my $keys = $neb->find_objects( "foo" );
+
+    is(scalar @$keys, 1, 'number of keys found');
+    is($keys->[0], "foo", "key name");
+}
+
+Test::Nebulous->setup;
+
+{
+    # key
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create( "foo" );
+    $neb->replicate( "foo" );
+
+    my $keys = $neb->find_objects( "foo" );
+
+    is(scalar @$keys, 1, 'number of keys found');
+    is($keys->[0], "foo", "key name");
+}
+
+Test::Nebulous->setup;
+
+{
+    # key does not exist
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    my $keys = $neb->find_objects( "bar" );
+
+    is_deeply($keys, [], 'number of keys found');
+}
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->find_objects( "foo", 3 );
+};
+like( $@, qr/1 was expected/, "too many params" );
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/75_parse_neb_key.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/75_parse_neb_key.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/75_parse_neb_key.t	(revision 21994)
@@ -0,0 +1,170 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 75_parse_neb_key.t,v 1.2 2008-01-23 22:46:44 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Test::More;
+
+plan tests => 36;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+# neb://<volume name>/...
+# neb:path...
+# neb:/path... (same as neb:path, leading '/' is stripped)
+# neb:///path... (same as neb:path)
+
+# key
+{
+    my ($volume, $path) = parse_neb_key('foo/bar/baz/quix');
+
+    is($path, 'foo/bar/baz/quix', 'path');
+    is($volume, undef, 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('/foo/bar/baz/quix');
+
+    is($path, 'foo/bar/baz/quix', 'path');
+    is($volume, undef, 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('//foo/bar/baz/quix');
+
+    is($path, 'foo/bar/baz/quix', 'path');
+    is($volume, undef, 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('///foo/bar/baz/quix');
+
+    is($path, 'foo/bar/baz/quix', 'path');
+    is($volume, undef, 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('foo////bar/baz/quix');
+
+    is($path, 'foo/bar/baz/quix', 'path');
+    is($volume, undef, 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('foo/bar/baz/quix/');
+
+    is($path, 'foo/bar/baz/quix', 'path');
+    is($volume, undef, 'volume name');
+}
+
+
+# URI w/ volume name
+{
+    my ($volume, $path) = parse_neb_key('neb://foo/bar/baz/quix');
+
+    is($path, 'bar/baz/quix', 'path');
+    is($volume, 'foo', 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('neb://foo//bar/baz/quix');
+
+    is($path, 'bar/baz/quix', 'path');
+    is($volume, 'foo', 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('neb://foo///bar/baz/quix');
+
+    is($path, 'bar/baz/quix', 'path');
+    is($volume, 'foo', 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('neb://foo/bar///baz/quix');
+
+    is($path, 'bar/baz/quix', 'path');
+    is($volume, 'foo', 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('neb://foo/bar/baz/quix/');
+
+    is($path, 'bar/baz/quix', 'path');
+    is($volume, 'foo', 'volume name');
+}
+
+
+# URI w/o volume name
+
+{
+    my ($volume, $path) = parse_neb_key('neb:/foo/bar/baz/quix');
+
+    is($path, 'foo/bar/baz/quix', 'path');
+    is($volume, undef, 'volume name');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('neb:///foo/bar/baz/quix');
+
+    is($volume, undef, 'volume name');
+    is($path, 'foo/bar/baz/quix', 'path');
+}
+
+{
+    my ($volume, $path) = parse_neb_key('neb://///foo/bar/baz/quix');
+
+    is($path, 'foo/bar/baz/quix', 'path');
+    is($volume, undef, 'volume name');
+}
+
+# key w/ whitespace
+eval {
+    parse_neb_key('/ foo/bar/baz/quix');
+};
+like( $@, qr/may not contain whitespace/, "whitespace" );
+
+eval {
+    parse_neb_key(' /foo/bar/baz/quix');
+};
+like( $@, qr/may not contain whitespace/, "whitespace" );
+
+eval {
+    parse_neb_key('/foo/bar/baz/quix ');
+};
+like( $@, qr/may not contain whitespace/, "whitespace" );
+
+# URI w/ whitespace
+
+eval {
+    parse_neb_key('neb ://foo/bar/baz/quix');
+};
+like( $@, qr/may not contain whitespace/, "whitespace" );
+
+eval {
+    parse_neb_key('neb:// foo/bar/baz/quix');
+};
+like( $@, qr/may not contain whitespace/, "whitespace" );
+
+eval {
+    parse_neb_key(' neb://foo/bar/baz/quix');
+};
+like( $@, qr/may not contain whitespace/, "whitespace" );
+
+eval {
+    parse_neb_key('neb://foo/bar/baz/quix ');
+};
+like( $@, qr/may not contain whitespace/, "whitespace" );
+
+# URI w/o volume requires leading slash
+eval {
+    my ($volume, $path) = parse_neb_key('neb:foo/bar/baz/quix');
+};
+like( $@, qr/requires a leading slash/, "leading slash" );
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/90_nebclient.t
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/90_nebclient.t	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/90_nebclient.t	(revision 21994)
@@ -0,0 +1,25 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 90_nebclient.t,v 1.2 2007-04-26 22:27:13 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+use lib qw( ./t ./lib );
+
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+$ENV{'NEB_SERVER'} = "http://" . Apache::Test->config->{ 'hostport' } . "/nebulous";
+
+chdir "./nebclient";
+system "make check";
+
+Test::Nebulous->cleanup;
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/TEST.PL
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/TEST.PL	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/TEST.PL	(revision 21994)
@@ -0,0 +1,12 @@
+#file:t/TEST.PL
+#--------------
+#!perl
+
+use strict;
+use warnings FATAL => 'all';
+
+use lib qw(lib);
+
+use Apache::TestRunPerl ();
+
+Apache::TestRunPerl->new->run(@ARGV);
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/Test/Nebulous.pm
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/Test/Nebulous.pm	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/Test/Nebulous.pm	(revision 21994)
@@ -0,0 +1,88 @@
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id: Nebulous.pm,v 1.15 2007-05-04 23:36:46 jhoblitt Exp $
+
+package Test::Nebulous;
+
+use strict;
+
+use DBI;
+use File::Path qw( mkpath rmtree );
+use File::Temp qw( tempdir );
+use Nebulous::Server::SQL;
+
+my $dsn     = "DBI:mysql:database=test:host=localhost";
+my $user    = "test";
+my $passwd  = "";
+
+my $dbh = DBI->connect( $dsn, $user, $passwd );
+my $sql = Nebulous::Server::SQL->new;
+
+# suppress uninitalized warnings
+my $dir1 = "";
+my $dir2 = "";
+my $dir3 = "";
+my $dir4 = "";
+my $dir5 = "";
+my $dir6 = "";
+
+sub setup {
+    my $self = shift;
+
+    $self->cleanup;
+
+    # create directories after cleanup
+    $dir1 = tempdir( CLEANUP => 0 );
+    $dir2 = tempdir( CLEANUP => 0 );
+    $dir3 = tempdir( CLEANUP => 0 );
+    $dir4 = tempdir( CLEANUP => 0 );
+    $dir5 = tempdir( CLEANUP => 0 );
+    $dir6 = tempdir( CLEANUP => 0 );
+
+    foreach my $statement (@{ $sql->get_db_schema }) {
+        $dbh->do( $statement );
+    }
+
+    # node01/node02: allocate = TRUE
+    $dbh->do(qq{ INSERT INTO volume (vol_id, name, path, allocate, available) VALUES (1, 'node01', ?, TRUE, TRUE) }, undef, $dir1);
+    $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e7) }, undef, $dir1);
+
+    $dbh->do(qq{ INSERT INTO volume (vol_id, name, path, allocate, available) VALUES (2, 'node02', ?, TRUE, TRUE) }, undef, $dir2);
+    $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e8) }, undef, $dir2);
+
+    # node03: allocate = TRUE, volume full
+    $dbh->do(qq{ INSERT INTO volume (vol_id, name, path, allocate, available) VALUES (3, 'node03', ?, TRUE, TRUE) }, undef, $dir3);
+    $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e10) }, undef, $dir3);
+
+    # node04: allocate = FALSE, available = FALSE
+    $dbh->do(qq{ INSERT INTO volume (vol_id, name, path, allocate, available) VALUES (4, 'node04', ?, FALSE, FALSE) }, undef, $dir4);
+    $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e7) }, undef, $dir4);
+
+    # node05: allocate = FALSE, available = TRUE
+    $dbh->do(qq{ INSERT INTO volume (vol_id, name, path, allocate, available) VALUES (5, 'node05', ?, FALSE, TRUE) }, undef, $dir5);
+    $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e7) }, undef, $dir5);
+
+    # node06: allocate = TRUE, available = FALSE
+    $dbh->do(qq{ INSERT INTO volume (vol_id, name, path, allocate, available) VALUES (6, 'node06', ?, TRUE, FALSE) }, undef, $dir4);
+    $dbh->do(qq{ INSERT INTO mount VALUES (?, 10e10, 10e7) }, undef, $dir6);
+
+    $dbh->do(qq{ call getmountedvol() });
+}
+
+sub cleanup {
+    foreach my $statement (@{ $sql->get_db_clear }) {
+        $dbh->do( $statement );
+    }
+
+    # on the first call to setup the $dir[12] will be ""
+    rmtree([$dir1], 0, 1) if -e $dir1;
+    rmtree([$dir2], 0, 1) if -e $dir2;
+    rmtree([$dir3], 0, 1) if -e $dir3;
+    rmtree([$dir4], 0, 1) if -e $dir4;
+    rmtree([$dir5], 0, 1) if -e $dir5;
+    rmtree([$dir6], 0, 1) if -e $dir6;
+}
+
+1;
+
+__END__
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/conf/.cvsignore
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/conf/.cvsignore	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/conf/.cvsignore	(revision 21994)
@@ -0,0 +1,6 @@
+apache_test_config.pm
+extra.conf
+httpd.conf
+modperl_inc.pl
+modperl_startup.pl
+startup.pl
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/conf/extra.conf.in
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/conf/extra.conf.in	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/conf/extra.conf.in	(revision 21994)
@@ -0,0 +1,11 @@
+#file:t/conf/extra.conf.in
+#-------------------------
+# this file will be Include-d by @ServerRoot@/httpd.conf
+
+<Location /nebulous>
+    SetHandler perl-script
+    PerlResponseHandler Apache2::SOAP
+    PerlSetVar dispatch_to "PerlHandler Nebulous::Server::SOAP"
+    PerlSetVar options "compress_threshold => 10000"
+</Location>
+
Index: /tags/ipp-1-X/rel-0_06/Nebulous/t/conf/startup.pl.in
===================================================================
--- /tags/ipp-1-X/rel-0_06/Nebulous/t/conf/startup.pl.in	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/Nebulous/t/conf/startup.pl.in	(revision 21994)
@@ -0,0 +1,24 @@
+use strict;
+use warnings FATAL => qw( all );
+
+use lib qw( @ServerRoot@/../lib );
+
+use Apache::DBI;
+use DBI;
+use Nebulous::Server::SOAP;
+use Nebulous::Server::Apache;
+use Nebulous::Server;
+
+my $dsn         = "DBI:mysql:database=test:host=localhost";
+my $dbuser      = "test";
+my $dbpasswd    = "";
+
+Apache::DBI->connect_on_init( $dsn, $dbuser, $dbpasswd );
+Nebulous::Server::SOAP->new_on_init(
+    dsn         => $dsn,
+    dbuser      => $dbuser,
+    dbpasswd    => $dbpasswd,
+    log_level   => 'all',
+);
+
+1;
Index: /tags/ipp-1-X/rel-0_06/glueforge/INSTALL
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/INSTALL	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/INSTALL	(revision 21994)
@@ -0,0 +1,95 @@
+# $Id: INSTALL,v 1.6 2006-01-11 02:12:34 jhoblitt Exp $
+
+Using the glueforge meta-database API generator
+--
+
+- Step 0
+
+Setup your shell's environment for Pan-STARRS CVS.  If you need help setting up
+CVS please see this article:
+
+    http://pan-starrs.ifa.hawaii.edu/project/resources/ps-cvs.html
+
+- Step 1
+
+Install the PS:IPP::Metadata::Config and Template modules.
+
+# PS:IPP::Metadata::Config
+$ cvs co PS-IPP-Metadata-Config
+$ cd PS-IPP-Metadata-Config
+$ perl Build.PL
+$ ./Build
+$ ./Build test
+# if you have sudo
+$ sudo ./Build install
+# if not
+$ su
+$ ./Build install
+
+# Template
+# if you have sudo
+$ sudo perl -MCPAN -e 'install Template'
+# if not
+$ su -
+$ perl -MCPAN -e 'install Template'
+
+If you have never used CPAN before you will be given a series of prompts to
+configure the module.
+
+- Step 2
+
+Checkout the glueforge module from Pan-STARRS CVS and build it.  If you need
+help setting up CVS please see this article:
+
+    http://pan-starrs.ifa.hawaii.edu/project/resources/ps-cvs.html
+
+$ cvs co glueforge
+$ cd glueforge
+$ ./autogen.sh
+$ make
+
+- Step 3
+
+Create a MetadataConfig file that describes the table you want to access.  The
+MetadataConfig file syntax is described in the pslib SDRS.  glueforge specific
+details are included in the "glueforge" man page. For reference, both a simple
+and complex config example is provided in the examples directory.
+
+$ perldoc glueforge
+
+or
+
+$ man glueforge
+
+$ cat examples/simple.md
+
+or
+
+$ cat examples/complex.md
+
+- Step 4
+
+Generate the database bindings with the "glueforge" executable.  The example
+simple.md file will generate code under the directory "foodb".
+
+$./glueforge -t templates/psdb -i examples/simple.md
+$ cd foodb
+
+- Step 5
+
+Package the software for distribution.  This is the same as for any 'standard'
+autotools package.  Please note that you must have pslib installed for the step
+to complete.  If you need help installing pslib please see this article:
+
+    http://pan-starrs.ifa.hawaii.edu/project/IPP/software/jhbuild/
+
+$ jhbuild shell
+$ ./autogen.sh && make dist
+
+This should generate two packages suitable for distribution.
+
+$ ls -la foodb-*
+-rw-r--r--  1 jhoblitt users 216367 Jul 28 17:54 foodb-0.0.1.tar.bz2
+-rw-r--r--  1 jhoblitt users 324926 Jul 28 17:54 foodb-0.0.1.tar.gz
+
+The End.
Index: /tags/ipp-1-X/rel-0_06/glueforge/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/Makefile.am	(revision 21994)
@@ -0,0 +1,35 @@
+SUBDIRS = templates/psdb
+
+bin_SCRIPTS = glueforge
+CLEANFILES = $(bin_SCRIPTS)
+
+do_subst = sed \
+	-e 's,[@]datadir[@],$(datadir),g' \
+	-e 's,[@]PACKAGE_NAME[@],$(PACKAGE_NAME),g' \
+	-e 's,[@]PACKAGE_VERSION[@],$(PACKAGE_VERSION),g'
+
+glueforge: glueforge.in
+	$(do_subst) < $(srcdir)/glueforge.in > glueforge
+	chmod +x glueforge
+
+example_files = \
+   examples/simple.md \
+   examples/complex.md
+
+glueforgedatadir = $(datadir)/@PACKAGE_NAME@
+exampledir = $(glueforgedatadir)/examples
+example_DATA = $(example_files)
+
+install-data-local:
+	chmod 0755 $(glueforgedatadir) $(exampledir)
+
+man_MANS = \
+    $(top_builddir)/@PACKAGE_NAME@.1
+
+@PACKAGE@.1: glueforge
+	$(POD2MAN) glueforge > @PACKAGE@.1
+
+clean-local:
+	-rm -rf docs @PACKAGE@.1
+
+EXTRA_DIST = autogen.sh glueforge.in $(example_files)
Index: /tags/ipp-1-X/rel-0_06/glueforge/autogen.sh
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/autogen.sh	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/autogen.sh	(revision 21994)
@@ -0,0 +1,103 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+PROJECT=glueforge
+TEST_TYPE=-f
+# change this to be a unique filename in the top level dir
+FILE=autogen.sh
+
+DIE=0
+
+LIBTOOLIZE=libtoolize
+ACLOCAL=aclocal
+AUTOHEADER=autoheader
+AUTOMAKE=automake
+AUTOCONF=autoconf
+
+#($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
+#        echo
+#        echo "You must have $LIBTOOlIZE installed to compile $PROJECT."
+#        echo "Download the appropriate package for your distribution,"
+#        echo "or get the source tarball at http://ftp.gnu.org/gnu/libtool/"
+#        DIE=1
+#}
+
+($ACLOCAL --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $ACLOCAL installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
+        DIE=1
+}
+
+#($AUTOHEADER --version) < /dev/null > /dev/null 2>&1 || {
+#        echo
+#        echo "You must have $AUTOHEADER installed to compile $PROJECT."
+#        echo "Download the appropriate package for your distribution,"
+#        echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
+#        DIE=1
+#}
+
+($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOMAKE installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
+        DIE=1
+}
+
+($AUTOCONF --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOCONF installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
+        DIE=1
+}
+
+if test "$DIE" -eq 1; then
+        exit 1
+fi
+
+test $TEST_TYPE $FILE || {
+        echo "You must run this script in the top-level $PROJECT directory"
+        exit 1
+}
+
+if test -z "$*"; then
+        echo "I am going to run ./configure with no arguments - if you wish "
+        echo "to pass any to it, please specify them on the $0 command line."
+fi
+
+#$LIBTOOLIZE --copy --force || echo "$LIBTOOlIZE failed"
+$ACLOCAL -I m4 || echo "$ACLOCAL failed"
+#$AUTOHEADER || echo "$AUTOHEADER failed"
+$AUTOMAKE --add-missing --force-missing --copy || echo "$AUTOMAKE failed"
+$AUTOCONF || echo "$AUTOCONF failed"
+
+cd $ORIGDIR
+
+run_configure=true
+for arg in $*; do
+    case $arg in
+        --no-configure)
+            run_configure=false
+            ;;
+        *)
+            ;;
+    esac
+done
+
+if $run_configure; then
+    $srcdir/configure --enable-maintainer-mode "$@"
+    echo
+    echo "Now type 'make' to compile $PROJECT."
+else
+    echo
+    echo "Now run 'configure' and 'make' to compile $PROJECT."
+fi
Index: /tags/ipp-1-X/rel-0_06/glueforge/configure.ac
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/configure.ac	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/configure.ac	(revision 21994)
@@ -0,0 +1,30 @@
+AC_PREREQ(2.59)
+
+AC_INIT([glueforge], [0.06], [jhoblitt@cpan.org])
+AC_CONFIG_SRCDIR([glueforge.in])
+
+AM_INIT_AUTOMAKE([1.6 foreign dist-bzip2])
+AM_MAINTAINER_MODE
+
+AC_PROG_INSTALL
+
+AC_PROG_PERL_MODULES(
+  [PS::IPP::Metadata::Config], ,
+  [AC_MSG_ERROR(perl module PS::IPP::Metadata::Config is required)]
+)
+
+AC_PROG_PERL_MODULES(
+  [Template], ,
+  [AC_MSG_ERROR(perl module Template is required)]
+)
+
+AC_PATH_PROG([POD2MAN], [pod2man], [missing])
+if test "$POD2MAN" = "missing" ; then
+  AC_MSG_ERROR([pod2man is required])
+fi
+
+AC_CONFIG_FILES([
+  Makefile
+  templates/psdb/Makefile
+])
+AC_OUTPUT
Index: /tags/ipp-1-X/rel-0_06/glueforge/examples/complex.md
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/examples/complex.md	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/examples/complex.md	(revision 21994)
@@ -0,0 +1,20 @@
+glueforge METADATA
+    pkg_name        STR  foodb 
+    pkg_namespace   STR  foo
+END
+
+foo METADATA
+    foo     STR     60      # Primary Key
+    bar     S32     0 
+    baz     F32     0.0
+    boing   F64     0.0
+    zot     BOOL    t       # Key
+END
+
+bar METADATA
+    zot     BOOL    t       # Key
+    boing   F64     0.0
+    baz     F32     0.0
+    bar     S32     0 
+    foo     STR     60      # Primary Key
+END
Index: /tags/ipp-1-X/rel-0_06/glueforge/examples/simple.md
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/examples/simple.md	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/examples/simple.md	(revision 21994)
@@ -0,0 +1,6 @@
+table   STR     foo
+foo     STR     60      # Primary Key
+bar     S32     0 
+baz     F32     0.0
+boing   F64     0.0
+zot     BOOL    t       # Key
Index: /tags/ipp-1-X/rel-0_06/glueforge/glueforge.in
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/glueforge.in	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/glueforge.in	(revision 21994)
@@ -0,0 +1,481 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2005-2006  Joshua Hoblitt
+#
+# $Id: glueforge.in,v 1.42 2006-01-11 02:39:16 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '@PACKAGE_VERSION@';
+
+use PS::IPP::Metadata::Config;
+use Template;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ( $input, $output, $template );
+GetOptions(
+    'input=s'       => \$input,
+    'output=s'      => \$output,
+    'template=s'    => \$template,
+) || pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required option: --input|-i", -exitval => 2 ) unless $input;
+
+$template = "@datadir@/@PACKAGE_NAME@/templates/psdb" unless $template;
+
+die "file doesn't exist: $input" unless -e $input;
+die "file isn't readable: $input" unless -r $input;
+
+my $config = parse_config( $input );
+
+die "file doesn't not contain a valid config" unless defined $config->[0];
+
+# if the first hash has a class of "metadata" then this is a complex config.
+# Otherwise it is a simple config.
+my $complex = ($config->[0]->{class} eq "metadata") ? 1 : 0;
+
+my $data; # hashref
+if ($complex) {
+    $data = complex_config($config);
+} else {
+    $data = simple_config($config);
+}
+
+# determine output path
+$output = $data->{pkg_name} unless defined $output;
+
+my %tt = (
+    'autogen_sh.tt'         => "$output/autogen.sh",
+    'configure_ac.tt'       => "$output/configure.ac",
+    'pkgconfig_pc_in.tt'    => "$output/$data->{pkg_name}.pc.in",
+    'doxyfile_in.tt'        => "$output/Doxyfile.in",
+    'top_makefile_am.tt'    => "$output/Makefile.am",
+    'src_makefile_am.tt'    => "$output/src/Makefile.am",
+    'header.tt'             => "$output/src/$data->{pkg_name}.h",
+    'code.tt'               => "$output/src/$data->{pkg_name}.c",
+    'tests_makefile_am.tt'  => "$output/tests/Makefile.am",
+    'testsuite_at.tt'       => "$output/tests/testsuite.at",
+    'dbsetup_c.tt'          => "$output/tests/dbsetup.c",
+    'dbcleanup_c.tt'        => "$output/tests/dbcleanup.c",
+    'alloc_c.tt'            => "$output/tests/alloc.c",
+    'init_c.tt'             => "$output/tests/init.c",
+    'cleanup_c.tt'          => "$output/tests/cleanup.c",
+    'createtable_c.tt'      => "$output/tests/createtable.c",
+    'droptable_c.tt'        => "$output/tests/droptable.c",
+    'insert_c.tt'           => "$output/tests/insert.c",
+    'pop_c.tt'              => "$output/tests/pop.c",
+    'insertobject_c.tt'     => "$output/tests/insertobject.c",
+    'popobject_c.tt'        => "$output/tests/popobject.c",
+    'insertfits_c.tt'       => "$output/tests/insertfits.c",
+    'popfits_c.tt'          => "$output/tests/popfits.c",
+    'selectrowsfits_c.tt'   => "$output/tests/selectrowsfits.c",
+    'metadatafromobject_c.tt' => "$output/tests/metadatafromobject.c",
+    'objectfrommetadata_c.tt' => "$output/tests/objectfrommetadata.c",
+);
+
+my $mangler = Template->new({ INCLUDE_PATH => $template });
+
+foreach my $t ( keys %tt ) {
+    $mangler->process( $t, $data, $tt{$t})
+        or die $mangler->error;
+}
+
+# make autogen.sh executable
+# permissions are in octal
+chmod 0744, $tt{'autogen_sh.tt'}; 
+
+sub parse_config {
+    my $file = shift;
+
+    my $mdparser = PS::IPP::Metadata::Config->new;
+    $mdparser->overwrite( 1 );
+
+    open( my $data, $file ) or die "can't open file: $!";
+    my $example = do { local $/; <$data> };
+    close( $data ) or die "can't close file: $!";
+
+    my $config = $mdparser->parse( $example )
+        or die "error parsing file: $input";
+
+    return $config;
+}
+
+sub lookup_type {
+    my $type = shift;
+
+    my %primitives = map { $_ => 1 } qw( S8 S16 S32 S64 U8 U16 U32 U64 F32 F64 );
+    my %mtypes = map { $_ => "PS_DATA_$_" } keys %primitives;
+    my %ctypes = map { $_ => "ps$_" } keys %primitives;
+
+    my %ttypes = (
+        S8      => -8,
+        S16     => -16,
+        S32     => -32,
+        S64     => -64,
+        U8      => 8,
+        U16     => 16,
+        U32     => 32,
+        U64     => 64,
+        F32     => 32.32,
+        F64     => 64.64,
+    );
+
+    if ( $primitives{$type} ) {
+        return {
+            ctype   => $ctypes{$type},
+            mtype   => $mtypes{$type},
+            test    => $ttypes{$type},
+        };
+    } elsif ( $type =~ /STR|STRING/ ) {
+        return {
+            ctype   => "char*",
+            mtype   => 'PS_DATA_STR',
+            test    => '"a string"',
+        };
+    } elsif ( $type =~ /BOOL/ ) {
+        return {
+            ctype   => "bool",
+            mtype   => 'PS_DATA_BOOL',
+            test    => 'true',
+        };
+    } else {
+        return undef;
+    }
+}
+
+sub simple_config {
+    my $config = shift;
+
+    # find table name
+    my $table_name;
+    for (my $i = 0; $i < @{$config}; $i++) {
+        my $elem = $config->[$i];
+
+        if ( $elem->{name} eq "table" ) {
+            $table_name = $elem->{value};
+
+            # delete element from array
+            splice @$config, $i, 1;
+
+            last;
+        }
+    }
+
+    my %data;
+
+    # global data
+    $data{pkg_name}         = $table_name . "db";
+    $data{pkg_namespace}    = $table_name;
+
+    # per table data
+    my %table;
+    $table{name}        = $table_name;
+    $table{namespace}   = $table_name;
+    $table{object_name} = $table{namespace} . "Row";
+
+    my @items;
+
+    # setup items
+    for (my $i = 0; $i < @{$config}; $i++) {
+        my $elem = $config->[$i];
+
+        my $mdtypes = lookup_type( $elem->{type} );
+        next if ! defined $mdtypes;
+
+        push @items, {
+            name    => $elem->{name},
+            type    => $elem->{type},
+            ctype   => $mdtypes->{ctype},
+            mtype   => $mdtypes->{mtype},
+            test    => $mdtypes->{test},
+            comment => $elem->{comment},
+            value   => $elem->{value},
+        };
+    }
+
+    $table{columns} = \@items;
+    $data{tables} = [ \%table ];
+
+    return \%data;
+}
+
+sub complex_config {
+    my $config = shift;
+
+    # find the glueforge metadata
+    my $glueforge_meta;
+    for (my $i = 0; $i < @{$config}; $i++) {
+        my $elem = $config->[$i];
+
+        if ($elem->{name} eq "glueforge") {
+            $glueforge_meta = $elem;
+
+            # delete element from array
+            splice @$config, $i, 1;
+
+            last;
+        }
+    }
+
+    die "missing glueforge METADATA" unless defined $glueforge_meta;
+
+    # global data
+
+    # process glueforge metadata for global data
+    my ($pkg_name, $pkg_namespace);
+    foreach my $item (@{$glueforge_meta->{value}}) {
+        if ($item->{name} eq 'pkg_name') {
+            $pkg_name = $item->{value};
+        } elsif ($item->{name} eq 'pkg_namespace') {
+            $pkg_namespace = $item->{value};
+        } else {
+            die "invalid glueforge METADATA key: $item->{name}";
+        }
+    }
+
+    die "pkg_name is required in complex config" unless defined $pkg_name;
+    die "pkg_namespace is required in complex config" unless defined
+        $pkg_namespace;
+
+    my %data;
+    $data{pkg_name}         = $pkg_name;
+    $data{pkg_namespace}    = $pkg_namespace;
+
+    # setup one table per nested metadata
+    my @tables;
+    foreach my $meta (@{$config}) {
+        push @tables, tabledata_from_meta($meta);
+    }
+
+    $data{tables} = \@tables;
+
+    return \%data;
+}
+
+sub tabledata_from_meta {
+    my $meta = shift;   # hashref
+
+    die "not a valid metadata" unless $meta->{class} eq 'metadata';
+
+    my $table_name = $meta->{name};
+
+    my @fields;
+    foreach my $column (@{$meta->{value}}) {
+        my $mdtypes = lookup_type( $column->{type} );
+        next if not defined $mdtypes;
+
+        push @fields, {
+            name    => $column->{name},
+            type    => $column->{type},
+            ctype   => $mdtypes->{ctype},
+            mtype   => $mdtypes->{mtype},
+            test    => $mdtypes->{test},
+            comment => $column->{comment},
+            value   => $column->{value},
+        };
+    }
+
+    my %table = (
+        name        => $table_name,
+        namespace   => $table_name,
+        object_name => $table_name . "Row",
+        columns     => \@fields,
+    );
+
+    return \%table;
+}
+
+__END__
+
+=pod
+
+=head1 NAME
+
+@PACKAGE_NAME@ - auto-generate Pan-STARRS IPP 'meta' database bindings
+
+=head1 SYNOPSIS
+
+    @PACKAGE_NAME@ --input <filename> [--output <dirname>] [--template <dirname>]
+
+=head1 DESCRIPTION
+
+This program generates a set of database table format specific bindings in the
+ANSI C language.  The code generated is largely just wrapper functions around
+the C<pslib> C<psDB> API.  Table information is read in from a configuration
+file in the pslib C<MetadataConfig> format.  A complete autotools configured
+package that builds both static & shared libraries is generated.
+
+=head2 Features
+
+=over 4
+
+=item * Generates a complete autoconf/automake/libtool package.
+
+=item * Generated packages include an C<autogen.sh> script.
+
+=item * Installs a pkgconfig C<.pc> data file.
+
+=item * Includes a table format specific autotest test suite.
+
+=item * Builds both shared and static libraries by default.
+
+=item * Generates man pages and HTML documentation with Doxygen.
+
+=item * Header files should be C++ safe.
+
+=item * Functions to open and close database connections.
+
+=item * Functions to create and destroy a table of the appropriate format.
+
+=item * Functions to insert and pop a row.
+
+=item * Functions to insert and pop a simple object representing a row.
+
+=item * Functions to insert, select, and pop to/from FITS files.
+
+=item * Functions to convert between row structs and pslib C<psMetadata>s.
+
+=back
+
+=head1 TABLE DESCRIPTION FORMAT
+
+There are two slightly different configuration file forms.  A C<simple> format
+for describing a single table and a C<complex> format for describing more then
+one table and/or configuring specific details as to how the package is
+generated.  The syntax for both of these forms follows the C<Configuration
+files> format as described in C<PSDC-430-007>.
+
+=head2 Simple configuration
+
+A simple config file specifies the name of the table, the name and types of all
+columns, and can optionally specify which column(s) are to be used as indexes.
+
+=head2 Example simple configuration
+
+    table   STR     foo
+    foo     STR     60      # Primary Key
+    bar     S32     0
+    baz     F32     0.0
+    boing   F64     0.0
+    zot     BOOL    t       # Key
+
+The key name C<table> is reserved and specifies the name of the database table.
+It may appear any where in the file but it is most I<convenient> to have it as
+the first line of the table description.
+
+The value of a C<STR> column specifies the maximum number of characters that
+the database is required to store for that field.  The values for C<S32>,
+C<F32>, C<F64>, & C<BOOL> columns are ignored.
+
+Keys maybe specified as a C<Primary Key> or C<Key>.  Only one C<Primary Key>
+may be specified per table.
+
+The key name C<position> is also reserved as it is used internally by the
+database bindings.
+
+=head2 Complex configuration
+
+A complex config file consists of a series of C<METADATA> blocks.  One (and
+only one) of these blocks I<must> be named C<glueforge>. This block
+contains the global package configuration data.  Only the keys C<pkg_name> and
+C<pkg_namespace> are allowed in this block and they are both required.
+
+All other C<METADATA> blocks describe a single table with the name of the
+C<METATA> block being the tables name.  Otherwise, the format of items
+contained in a C<METADATA> block is the same as for the simple configuration.
+
+Note that nested C<METADATA> blocks are not allowed.
+
+=head2 Example complex configuration
+
+glueforge METADATA
+    pkg_name        STR  foodb 
+    pkg_namespace   STR  foo
+END
+
+foo METADATA
+    foo     STR     60      # Primary Key
+    bar     S32     0 
+    baz     F32     0.0
+    boing   F64     0.0
+    zot     BOOL    t       # Key
+END
+
+bar METADATA
+    zot     BOOL    t       # Key
+    boing   F64     0.0
+    baz     F32     0.0
+    bar     S32     0 
+    foo     STR     60      # Primary Key
+END
+
+=head1 OPTIONS
+
+=over 4
+
+=item * --input|-i <filename>
+
+File to read table description from.
+
+=item * --output|-o <dirname>
+
+Send the generate files to this directory name.
+
+Defaults to the name of the database table.
+
+=item * --template|-t <dirname>
+
+Directory to load template files from.
+
+Defaults to C<@datadir@/@PACKAGE_NAME@/templates/psdb>.
+
+=back
+
+=head1 BUGS
+
+The format of configuration files is not rigorously checked.  Improperly
+formatted files may not be caught and cause random (possibly silent) errors
+and/or improperly code generation.
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2005-2006  Joshua Hoblitt.  All rights reserved.
+
+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.
+
+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.
+
+The full text of the license can be found in the L<perlgpl> Pod as supplied
+with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+C<pslib>, C<PSDC-430-007>. L<PS:IPP::Metadata::Config>
+
+=cut
Index: /tags/ipp-1-X/rel-0_06/glueforge/m4/ac_prog_perl_modules.m4
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/m4/ac_prog_perl_modules.m4	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/m4/ac_prog_perl_modules.m4	(revision 21994)
@@ -0,0 +1,53 @@
+dnl @synopsis AC_PROG_PERL_MODULES([MODULES], [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+dnl
+dnl Checks to see if the the given perl modules are available. If true
+dnl the shell commands in ACTION-IF-TRUE are executed. If not the shell
+dnl commands in ACTION-IF-FALSE are run. Note if $PERL is not set (for
+dnl example by calling AC_CHECK_PROG, or AC_PATH_PROG),
+dnl AC_CHECK_PROG(PERL, perl, perl) will be run.
+dnl
+dnl Example:
+dnl
+dnl   AC_CHECK_PERL_MODULES(Text::Wrap Net::LDAP, ,
+dnl                         AC_MSG_WARN(Need some Perl modules)
+dnl
+dnl @category InstalledPackages
+dnl @author Dean Povey <povey@wedgetail.com>
+dnl @version 2002-09-25
+dnl @license AllPermissive
+
+AC_DEFUN([AC_PROG_PERL_MODULES],[
+    ac_perl_modules="$1"
+    # Make sure we have perl
+    if test -z "$PERL"; then
+        AC_CHECK_PROG(PERL,perl,perl)
+    fi
+
+    if test "x$PERL" != x; then
+        ac_perl_modules_failed=0
+        for ac_perl_module in $ac_perl_modules; do
+            AC_MSG_CHECKING(for perl module $ac_perl_module)
+
+            # Would be nice to log result here, but can't rely on autoconf
+            # internals
+            $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1
+            if test $? -ne 0; then
+                AC_MSG_RESULT(no);
+                ac_perl_modules_failed=1
+            else
+                AC_MSG_RESULT(ok);
+            fi
+        done
+
+        # Run optional shell commands
+        if test "$ac_perl_modules_failed" = 0; then
+            :
+            $2
+        else
+            :
+            $3
+        fi
+    else
+        AC_MSG_WARN(could not find perl)
+    fi
+])
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/Makefile.am
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/Makefile.am	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/Makefile.am	(revision 21994)
@@ -0,0 +1,83 @@
+template_files = \
+    alloc.tt \
+    alloc_at.tt \
+    alloc_c.tt \
+    alloc_h.tt \
+    autogen_sh.tt \
+    bootstrap_sh.tt \
+    cleanup.tt \
+    cleanup_at.tt \
+    cleanup_c.tt \
+    cleanup_h.tt \
+    code.tt \
+    configure_ac.tt \
+    createtable.tt \
+    createtable_at.tt \
+    createtable_c.tt \
+    createtable_h.tt \
+    dbcleanup_c.tt \
+    dbsetup_c.tt \
+    doxyfile_in.tt \
+    droptable.tt \
+    droptable_at.tt \
+    droptable_c.tt \
+    droptable_h.tt \
+    header.tt \
+    init.tt \
+    init_at.tt \
+    init_c.tt \
+    init_h.tt \
+    insert.tt \
+    insert_at.tt \
+    insert_c.tt \
+    insert_h.tt \
+    insertfits.tt \
+    insertfits_at.tt \
+    insertfits_c.tt \
+    insertfits_h.tt \
+    insertobject.tt \
+    insertobject_at.tt \
+    insertobject_c.tt \
+    insertobject_h.tt \
+    makefile.tt \
+    metadatafromobject.tt \
+    metadatafromobject_at.tt \
+    metadatafromobject_c.tt \
+    metadatafromobject_h.tt \
+    object_h.tt \
+    objectfrommetadata.tt \
+    objectfrommetadata_at.tt \
+    objectfrommetadata_c.tt \
+    objectfrommetadata_h.tt \
+    pkgconfig_pc_in.tt \
+    pop.tt \
+    pop_at.tt \
+    pop_c.tt \
+    pop_h.tt \
+    popfits.tt \
+    popfits_at.tt \
+    popfits_c.tt \
+    popfits_h.tt \
+    popobject.tt \
+    popobject_at.tt \
+    popobject_c.tt \
+    popobject_h.tt \
+    selectrowobjects.tt \
+    selectrowobjects_h.tt \
+    selectrowsfits.tt \
+    selectrowsfits_at.tt \
+    selectrowsfits_c.tt \
+    selectrowsfits_h.tt \
+    src_makefile_am.tt \
+    tests_makefile_am.tt \
+    testsuite_at.tt \
+    top_makefile_am.tt
+
+templatedir = $(datadir)/@PACKAGE_NAME@/templates
+psdbtemplatedir = $(templatedir)/psdb
+psdbtemplate_DATA = $(template_files)
+
+install-data-hook:
+	chmod 0755 $(templatedir) $(psdbtemplatedir)
+
+EXTRA_DIST = $(template_files)
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/alloc.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/alloc.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/alloc.tt	(revision 21994)
@@ -0,0 +1,40 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+static void [% table.object_name %]Free([% table.object_name %] *object);
+
+[% table.object_name %] *[% table.object_name %]Alloc(
+[%- SET i = 0 -%]
+[% FOREACH item = table.columns -%]
+[% IF i == 0 %][% i = 1 %][% ELSE %], [% END -%]
+[% IF item.type == "STR" -%]
+const char *[% item.name %]
+[%- ELSE -%]
+[% item.ctype %] [% item.name %]
+[%- END -%]
+[% END -%]
+)
+{
+    [% indented(table.object_name, "*object") %];
+
+    object = psAlloc(sizeof([% table.object_name %]));
+    psMemSetDeallocator(object, (psFreeFunc)[% table.object_name %]Free);
+
+[% FOREACH item = table.columns -%]
+[% IF item.type == "STR" -%]
+    object->[% item.name %] = psStringCopy([% item.name %]);
+[% ELSE -%]
+    object->[% item.name %] = [% item.name %];
+[% END -%]
+[% END -%]
+
+    return object;
+}
+
+static void [% table.object_name %]Free([% table.object_name %] *object)
+{
+[% FOREACH item = table.columns -%]
+[% IF item.type == "STR" -%]
+    psFree(object->[% item.name %]);
+[% END -%]
+[% END -%]
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/alloc_at.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/alloc_at.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/alloc_at.tt	(revision 21994)
@@ -0,0 +1,6 @@
+AT_SETUP([[% table.object_name %]Alloc()])
+AT_KEYWORDS([[% table.object_name %]Alloc])
+
+AT_CHECK([alloc])
+
+AT_CLEANUP
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/alloc_c.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/alloc_c.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/alloc_c.tt	(revision 21994)
@@ -0,0 +1,42 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+#include <pslib.h>
+#include <[% pkg_name %].h>
+#include <stdlib.h>
+
+#define MAX_STRING_LENGTH 1024
+
+int main ()
+{
+[% FOREACH table = tables -%]
+    {
+        [% indented(table.object_name, "*object") %];
+
+        object = [% table.object_name %]Alloc(
+[%- SET i = 0 -%]
+[%- FOREACH item = table.columns -%]
+        [%- IF i == 0 -%][%- i = 1 -%][%- ELSE -%], [% END -%] [%- item.test -%]
+[%- END -%]
+    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+[% FOREACH item = table.columns -%]
+[% IF item.type == "S32" or item.type == "F32" or item.type == "F64" or item.type == "BOOL" -%]
+        if (!object->[% item.name %] == [% item.test %]) {
+[% ELSIF item.type == "STR" -%]
+        if (strncmp(object->[% item.name %], [% item.test %], MAX_STRING_LENGTH)) {
+[% END -%]
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+[% END -%]
+
+        psFree(object);
+    }
+
+[% END -%]
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/alloc_h.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/alloc_h.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/alloc_h.tt	(revision 21994)
@@ -0,0 +1,18 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+/** Creates a new [% table.object_name %] object
+ *
+ *  @return A new [% table.object_name %] object or NULL on failure.
+ */
+
+[% table.object_name %] *[% table.object_name %]Alloc(
+[%- SET i = 0 -%]
+[% FOREACH item = table.columns -%]
+[% IF i == 0 %][% i = 1 %][% ELSE %],[% END %]
+[% IF item.type == "STR" -%]
+    [% indented("const char", "*$item.name") %]
+[%- ELSE -%]
+    [% indented("$item.ctype", "$item.name") %]
+[%- END -%]
+[% END %]
+);
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/autogen_sh.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/autogen_sh.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/autogen_sh.tt	(revision 21994)
@@ -0,0 +1,103 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+PROJECT=[% pkg_name %]
+TEST_TYPE=-f
+# change this to be a unique filename in the top level dir
+FILE=autogen.sh
+
+DIE=0
+
+LIBTOOLIZE=libtoolize
+ACLOCAL=aclocal
+AUTOHEADER=autoheader
+AUTOMAKE=automake
+AUTOCONF=autoconf
+
+($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $LIBTOOlIZE installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/libtool/"
+        DIE=1
+}
+
+($ACLOCAL --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $ACLOCAL installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
+        DIE=1
+}
+
+($AUTOHEADER --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOHEADER installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
+        DIE=1
+}
+
+($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOMAKE installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
+        DIE=1
+}
+
+($AUTOCONF --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOCONF installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
+        DIE=1
+}
+
+if test "$DIE" -eq 1; then
+        exit 1
+fi
+
+test $TEST_TYPE $FILE || {
+        echo "You must run this script in the top-level $PROJECT directory"
+        exit 1
+}
+
+if test -z "$*"; then
+        echo "I am going to run ./configure with no arguments - if you wish "
+        echo "to pass any to it, please specify them on the $0 command line."
+fi
+
+$LIBTOOLIZE --copy --force || echo "$LIBTOOlIZE failed"
+$ACLOCAL || echo "$ACLOCAL failed"
+$AUTOHEADER || echo "$AUTOHEADER failed"
+$AUTOMAKE --add-missing --force-missing --copy || echo "$AUTOMAKE failed"
+$AUTOCONF || echo "$AUTOCONF failed"
+
+cd $ORIGDIR
+
+run_configure=true
+for arg in $*; do
+    case $arg in
+        --no-configure)
+            run_configure=false
+            ;;
+        *)
+            ;;
+    esac
+done
+
+if $run_configure; then
+    $srcdir/configure --enable-maintainer-mode "$@"
+    echo
+    echo "Now type 'make' to compile $PROJECT."
+else
+    echo
+    echo "Now run 'configure' and 'make' to compile $PROJECT."
+fi
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/bootstrap_sh.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/bootstrap_sh.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/bootstrap_sh.tt	(revision 21994)
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+libtoolize --automake --copy \
+&& aclocal \
+&& autoheader \
+&& automake --foreign --add-missing --copy \
+&& autoconf
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/cleanup.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/cleanup.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/cleanup.tt	(revision 21994)
@@ -0,0 +1,4 @@
+void [% pkg_namespace %]Cleanup(psDB *dbh)
+{
+    psDBCleanup(dbh);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/cleanup_at.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/cleanup_at.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/cleanup_at.tt	(revision 21994)
@@ -0,0 +1,6 @@
+AT_SETUP([[% table.namespace %]Cleanup()])
+AT_KEYWORDS([[% table.namespace %]Cleanup])
+
+AT_CHECK([cleanup])
+
+AT_CLEANUP
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/cleanup_c.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/cleanup_c.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/cleanup_c.tt	(revision 21994)
@@ -0,0 +1,17 @@
+#include <pslib.h>
+#include <[% pkg_name %].h>
+#include <stdlib.h>
+
+int main ()
+{
+    psDB            *dbh;
+
+    dbh = psDBInit("localhost", "test", NULL, "test");
+    if (!dbh) {
+        exit(EXIT_FAILURE);
+    }
+
+    [% pkg_namespace %]Cleanup(dbh);
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/cleanup_h.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/cleanup_h.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/cleanup_h.tt	(revision 21994)
@@ -0,0 +1,6 @@
+/** Closes a database connection
+ */
+
+void [% pkg_namespace %]Cleanup(
+    psDB            *dbh                ///< Database handle
+);
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/code.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/code.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/code.tt	(revision 21994)
@@ -0,0 +1,25 @@
+#include "[% pkg_name %].h"
+
+[% FOREACH table = tables -%]
+#define [% table.namespace FILTER upper %]_TABLE_NAME "[% table.name %]"
+#define [% table.namespace FILTER upper %]_INDEX_NAME "position"
+[% END -%]
+#define MAX_STRING_LENGTH 1024
+
+[% INCLUDE init.tt %]
+[% INCLUDE cleanup.tt %]
+[% FOREACH table = tables -%]
+[% INCLUDE alloc.tt %]
+[% INCLUDE createtable.tt %]
+[% INCLUDE droptable.tt %]
+[% INCLUDE insert.tt %]
+[% INCLUDE pop.tt %]
+[% INCLUDE insertobject.tt %]
+[% INCLUDE popobject.tt %]
+[% INCLUDE insertfits.tt %]
+[% INCLUDE popfits.tt %]
+[% INCLUDE selectrowsfits.tt %]
+[% INCLUDE metadatafromobject.tt %]
+[% INCLUDE objectfrommetadata.tt -%]
+[% INCLUDE selectrowobjects.tt -%]
+[% END -%]
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/configure_ac.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/configure_ac.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/configure_ac.tt	(revision 21994)
@@ -0,0 +1,41 @@
+AC_PREREQ(2.59)
+
+AC_INIT([[% pkg_name %]], [0.0.1], [pan-starrs.ifa.hawaii.edu])
+AC_CONFIG_SRCDIR([[% pkg_name %].pc.in])
+
+AM_INIT_AUTOMAKE([1.6 foreign dist-bzip2])
+AM_CONFIG_HEADER([config.h])
+AM_MAINTAINER_MODE
+
+AC_CONFIG_TESTDIR([tests])
+AC_CONFIG_FILES([tests/Makefile])
+AM_MISSING_PROG([AUTOM4TE], [autom4te])
+
+AC_LANG(C)
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+
+PKG_CHECK_MODULES([PSLIB], [pslib >= 0.6.0]) 
+
+AC_PATH_PROG([PERL], [perl], [missing])
+if test "$PERL" = "missing" ; then
+  AC_MSG_ERROR([perl is required])
+fi
+
+AC_PATH_PROG([DOXYGEN], [doxygen], [missing])
+if test "$DOXYGEN" = "missing" ; then
+  AC_MSG_ERROR([doxygen is required])
+fi
+
+dnl is this the best was to setup recursive CFLAGS?
+[% pkg_name %]_CFLAGS="-Wall -pedantic -std=c99 -fno-strict-aliasing"
+AC_SUBST([[% pkg_name %]_CFLAGS])
+
+AC_CONFIG_FILES([
+  Makefile
+  src/Makefile
+  [% pkg_name %].pc
+  Doxyfile
+])
+AC_OUTPUT
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/createtable.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/createtable.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/createtable.tt	(revision 21994)
@@ -0,0 +1,43 @@
+bool [% table.namespace %]CreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, [% table.namespace FILTER upper %]_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", [% table.namespace FILTER upper %]_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+[% FOREACH item = table.columns -%]
+[% IF item.comment;
+    SET item.comment = "\"$item.comment\"";
+ELSE;
+    SET item.comment = 'NULL';
+END;
+-%]
+[% IF item.type == "S32" or item.type == "F32" or item.type == "F64" -%]
+    if (!psMetadataAdd[% item.type %](md, PS_LIST_TAIL, "[% item.name %]", 0, [% item.comment %], [% item.value %])) {
+[% ELSIF item.type == "STR" -%]
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "[% item.name %]", 0, [% item.comment %], "[% item.value %]")) {
+[% ELSIF item.type == "BOOL" -%]
+[% IF item.value == 1;
+    SET item.value = "true";
+ELSE;
+    SET item.value = "false";
+END;
+-%]
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "[% item.name %]", PS_DATA_BOOL, [% item.comment %], [% item.value %])) {
+[% END -%]
+        psError(PS_ERR_UNKNOWN, false, "failed to add item [% item.name %]");
+        psFree(md);
+        return false;
+    }
+[% END -%]
+
+    status = psDBCreateTable(dbh, [% table.namespace FILTER upper %]_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/createtable_at.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/createtable_at.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/createtable_at.tt	(revision 21994)
@@ -0,0 +1,9 @@
+AT_SETUP([[% table.namespace %]CreateTable()])
+AT_KEYWORDS([[% table.namespace %]CreateTable])
+
+# make sure the table is not there.
+AT_CHECK([dbcleanup])
+AT_CHECK([createtable])
+AT_CHECK([dbcleanup])
+
+AT_CLEANUP
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/createtable_c.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/createtable_c.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/createtable_c.tt	(revision 21994)
@@ -0,0 +1,25 @@
+#include <pslib.h>
+#include <[% pkg_name %].h>
+#include <stdlib.h>
+
+int main ()
+{
+[% FOREACH table = tables -%]
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(![% table.namespace %]CreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+[% END -%]
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/createtable_h.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/createtable_h.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/createtable_h.tt	(revision 21994)
@@ -0,0 +1,8 @@
+/** Creates a new [% table.name %] table
+ *
+ * @return true on success
+ */
+
+bool [% table.namespace %]CreateTable(
+    psDB            *dbh                ///< Database handle
+);
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/dbcleanup_c.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/dbcleanup_c.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/dbcleanup_c.tt	(revision 21994)
@@ -0,0 +1,20 @@
+#include <pslib.h>
+#include <stdlib.h>
+
+int main ()
+{
+    psDB            *dbh;
+
+    dbh = psDBInit("localhost", "test", NULL, "test");
+    if (!dbh) {
+        exit(EXIT_FAILURE);
+    }
+
+[% FOREACH table = tables -%]
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS [% table.name %]");
+[% END -%]
+
+    psDBCleanup(dbh);
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/dbsetup_c.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/dbsetup_c.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/dbsetup_c.tt	(revision 21994)
@@ -0,0 +1,23 @@
+#include <pslib.h>
+#include <[% pkg_name %].h>
+#include <stdlib.h>
+
+int main ()
+{
+    psDB            *dbh;
+
+    dbh = psDBInit("localhost", "test", NULL, "test");
+    if (!dbh) {
+        exit(EXIT_FAILURE);
+    }
+
+    // remove the table if it already exists
+[% FOREACH table = tables -%]
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS [% table.name %]");
+    [% table.namespace %]CreateTable(dbh);
+
+[% END -%]
+    psDBCleanup(dbh);
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/doxyfile_in.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/doxyfile_in.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/doxyfile_in.tt	(revision 21994)
@@ -0,0 +1,1219 @@
+# Doxyfile 1.4.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = @PACKAGE_NAME@
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = @PACKAGE_VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+# @top_builddir@ doesn't work for some reason
+OUTPUT_DIRECTORY       = @builddir@/docs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# This tag can be used to specify the encoding used in the generated output. 
+# The encoding is not always determined by the language that is chosen, 
+# but also whether or not the output is meant for Windows or non-Windows users. 
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
+# forces the Windows encoding (this is the default for the Windows binary), 
+# whereas setting the tag to NO uses a Unix-style encoding (the default for 
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING   = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like the Qt-style comments (thus requiring an 
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
+# only. Doxygen will then generate output that is more tailored for Java. 
+# For instance, namespaces will be presented as packages, qualified scopes 
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation.
+
+SHOW_DIRECTORIES       = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from the 
+# version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the progam writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = @top_srcdir@/src
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS          = *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories.
+
+EXCLUDE_PATTERNS       = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = YES
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = @PERL@
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# generate a call dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable call graphs for selected 
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that a graph may be further truncated if the graph's 
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH 
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), 
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, which results in a white background. 
+# Warning: Depending on the platform used, enabling this option may lead to 
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to 
+# read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/droptable.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/droptable.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/droptable.tt	(revision 21994)
@@ -0,0 +1,4 @@
+bool [% table.namespace %]DropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, [% table.namespace FILTER upper %]_TABLE_NAME);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/droptable_at.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/droptable_at.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/droptable_at.tt	(revision 21994)
@@ -0,0 +1,9 @@
+AT_SETUP([[% table.namespace %]DropTable()])
+AT_KEYWORDS([[% table.namespace %]DropTable])
+
+# make sure the table is not there.
+AT_CHECK([dbsetup])
+AT_CHECK([droptable])
+AT_CHECK([dbcleanup])
+
+AT_CLEANUP
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/droptable_c.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/droptable_c.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/droptable_c.tt	(revision 21994)
@@ -0,0 +1,25 @@
+#include <pslib.h>
+#include <[% pkg_name %].h>
+#include <stdlib.h>
+
+int main ()
+{
+[% FOREACH table = tables -%]
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (![% table.namespace %]DropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+[% END -%]
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/droptable_h.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/droptable_h.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/droptable_h.tt	(revision 21994)
@@ -0,0 +1,8 @@
+/** Deletes a [% table.name %] table
+ *
+ * @return true on success
+ */
+
+bool [% table.namespace %]DropTable(
+    psDB            *dbh                ///< Database handle
+);
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/header.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/header.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/header.tt	(revision 21994)
@@ -0,0 +1,38 @@
+#ifndef [% pkg_name FILTER upper %]_H
+#define [% pkg_name FILTER upper %]_H 1
+
+#include <pslib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// @addtogroup [% pkg_name %]
+/// @{
+
+[% INCLUDE init_h.tt %]
+[% INCLUDE cleanup_h.tt %]
+[% FOREACH table = tables -%]
+[% INCLUDE object_h.tt %]
+[% INCLUDE alloc_h.tt %]
+[% INCLUDE createtable_h.tt %]
+[% INCLUDE droptable_h.tt %]
+[% INCLUDE insert_h.tt %]
+[% INCLUDE pop_h.tt %]
+[% INCLUDE insertobject_h.tt %]
+[% INCLUDE popobject_h.tt %]
+[% INCLUDE insertfits_h.tt %]
+[% INCLUDE popfits_h.tt %]
+[% INCLUDE selectrowsfits_h.tt %]
+[% INCLUDE metadatafromobject_h.tt %]
+[% INCLUDE objectfrommetadata_h.tt -%]
+[% INCLUDE selectrowobjects_h.tt -%]
+[% END -%]
+
+/// @}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // [% table.namespace FILTER upper %]_DB_H
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/init.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/init.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/init.tt	(revision 21994)
@@ -0,0 +1,4 @@
+psDB *[% pkg_namespace %]Init(const char *host, const char *user, const char *passwd, const char *dbname)
+{
+    return psDBInit(host, user, passwd, dbname);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/init_at.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/init_at.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/init_at.tt	(revision 21994)
@@ -0,0 +1,6 @@
+AT_SETUP([[% table.namespace %]Init()])
+AT_KEYWORDS([[% table.namespace %]Init])
+
+AT_CHECK([init])
+
+AT_CLEANUP
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/init_c.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/init_c.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/init_c.tt	(revision 21994)
@@ -0,0 +1,17 @@
+#include <pslib.h>
+#include <[% pkg_name %].h>
+#include <stdlib.h>
+
+int main ()
+{
+    psDB            *dbh;
+
+    dbh = [% pkg_namespace %]Init("localhost", "test", NULL, "test");
+    if (!dbh) {
+        exit(EXIT_FAILURE);
+    }
+
+    psDBCleanup(dbh);
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/init_h.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/init_h.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/init_h.tt	(revision 21994)
@@ -0,0 +1,12 @@
+/** Opens a new database connection
+ *
+ *  @return A new psDB object if the database connection is successful or NULL
+ *  on failure.
+ */
+
+psDB *[% pkg_namespace %]Init(
+    const char      *host,              ///< Database server hostname
+    const char      *user,              ///< Database username
+    const char      *passwd,            ///< Database password
+    const char      *dbname             ///< Database table.namespace
+);
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insert.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insert.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insert.tt	(revision 21994)
@@ -0,0 +1,35 @@
+bool [% table.namespace %]Insert(psDB * dbh,
+[%- SET i = 0 -%]
+[% FOREACH item = table.columns -%]
+[% IF i == 0 %][% i = 1 %] [% ELSE %], [% END -%]
+[% IF item.type == "STR" -%]
+const char *[% item.name %]
+[%- ELSE -%]
+[% item.ctype %] [% item.name %]
+[%- END -%]
+[% END -%]
+)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+[% FOREACH item = table.columns -%]
+[% IF item.type == "S32" or item.type == "F32" or item.type == "F64" -%]
+    if (!psMetadataAdd[% item.type %](md, PS_LIST_TAIL, "[% item.name %]", 0, NULL, [% item.name %])) {
+[% ELSIF item.type == "STR" -%]
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "[% item.name %]", 0, NULL, psStringCopy([% item.name %]))) {
+[% ELSIF item.type == "BOOL" -%]
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "[% item.name %]", PS_DATA_BOOL, NULL, [% item.name %])) {
+[% END -%]
+        psError(PS_ERR_UNKNOWN, false, "failed to add item [% item.name %]");
+        psFree(md);
+        return false;
+    }
+[% END -%]
+
+    status = psDBInsertOneRow(dbh, [% table.namespace FILTER upper %]_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insert_at.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insert_at.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insert_at.tt	(revision 21994)
@@ -0,0 +1,8 @@
+AT_SETUP([[% table.namespace %]Insert()])
+AT_KEYWORDS([[% table.namespace %]Insert])
+
+AT_CHECK([dbsetup])
+AT_CHECK([insert])
+AT_CHECK([dbcleanup])
+
+AT_CLEANUP
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insert_c.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insert_c.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insert_c.tt	(revision 21994)
@@ -0,0 +1,32 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+#include <pslib.h>
+#include <[% pkg_name %].h>
+#include <stdlib.h>
+
+int main ()
+{
+[% FOREACH table = tables -%]
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (![% table.namespace %]Insert(dbh, 
+[%- SET i = 0 -%]
+[%- FOREACH item = table.columns -%]
+[%- IF i == 0 -%][%- i = 1 -%][%- ELSE -%], [% END -%] [%- item.test -%]
+[%- END -%]
+)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+[% END -%]
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insert_h.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insert_h.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insert_h.tt	(revision 21994)
@@ -0,0 +1,21 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool [% table.namespace %]Insert(
+    psDB            *dbh,               ///< Database handle
+[%- SET i = 0 -%]
+[% FOREACH item = table.columns -%]
+[% IF i == 0 %][% i = 1 %][% ELSE %],[% END %]
+[% IF item.type == "STR" -%]
+    [% indented("const char", "*$item.name") -%]
+[% ELSE -%]
+    [% indented("$item.ctype", "$item.name") -%]
+[% END -%]
+[% END %]
+);
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertfits.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertfits.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertfits.tt	(revision 21994)
@@ -0,0 +1,34 @@
+bool [% table.namespace %]InsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  [% table.namespace FILTER upper %]_TABLE_NAME
+    if (!psFitsMoveExtName(fits, [% table.namespace FILTER upper %]_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", [% table.namespace FILTER upper %]_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, [% table.namespace FILTER upper %]_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertfits_at.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertfits_at.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertfits_at.tt	(revision 21994)
@@ -0,0 +1,15 @@
+AT_SETUP([[% table.namespace %]InsertFits()])
+AT_KEYWORDS([[% table.namespace %]InsertFits])
+
+AT_CHECK([dbsetup])
+# run insert so there is a row in the table
+AT_CHECK([insert])
+# run popfis so there is afits file to read
+AT_CHECK([popfits])
+AT_CHECK([insertfits])
+AT_CHECK([dbcleanup])
+if [ test -f "blargh" ] ; then
+    rm -f "blargh"
+fi
+
+AT_CLEANUP
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertfits_c.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertfits_c.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertfits_c.tt	(revision 21994)
@@ -0,0 +1,40 @@
+#include <pslib.h>
+#include <[% pkg_name %].h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#define TMP_FILENAME "./blargh"
+
+int main ()
+{
+[% FOREACH table = tables -%]
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (![% table.namespace %]InsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+[% END -%]
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertfits_h.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertfits_h.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertfits_h.tt	(revision 21994)
@@ -0,0 +1,14 @@
+/** Insert data from a binary FITS table [% table.object_name %] into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool [% table.namespace %]InsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertobject.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertobject.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertobject.tt	(revision 21994)
@@ -0,0 +1,10 @@
+bool [% table.namespace %]InsertObject(psDB *dbh, [% table.object_name %] *object)
+{
+    return [% table.namespace %]Insert(dbh,
+[%- SET i = 0 -%]
+[%- FOREACH item = table.columns -%]
+[%- IF i == 0 -%][%- i = 1 -%] [% ELSE %], [% END -%]
+object->[% item.name -%]
+[%- END -%]
+);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertobject_at.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertobject_at.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertobject_at.tt	(revision 21994)
@@ -0,0 +1,8 @@
+AT_SETUP([[% table.namespace %]InsertObject()])
+AT_KEYWORDS([[% table.namespace %]InsertObject])
+
+AT_CHECK([dbsetup])
+AT_CHECK([insertobject])
+AT_CHECK([dbcleanup])
+
+AT_CLEANUP
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertobject_c.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertobject_c.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertobject_c.tt	(revision 21994)
@@ -0,0 +1,39 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+#include <pslib.h>
+#include <[% pkg_name %].h>
+#include <stdlib.h>
+
+int main ()
+{
+[% FOREACH table = tables -%]
+    {
+        psDB            *dbh;
+        [% indented(table.object_name, "*object") %];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = [% table.object_name %]Alloc(
+[%- SET i = 0 -%]
+[%- FOREACH item = table.columns -%]
+    [%- IF i == 0 -%][%- i = 1 -%][%- ELSE -%], [% END -%] [%- item.test -%]
+[%- END -%]
+);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (![% table.namespace %]InsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+[% END -%]
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertobject_h.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertobject_h.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/insertobject_h.tt	(revision 21994)
@@ -0,0 +1,13 @@
+[% USE format -%]
+[% indented = format('%-15s %-20s') -%]
+/** Insert a single [% table.object_name %] object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool [% table.namespace %]InsertObject(
+    psDB            *dbh,               ///< Database handle
+    [% indented(table.object_name, "*object") %]///< [% table.object_name %] object
+);
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/makefile.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/makefile.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/makefile.tt	(revision 21994)
@@ -0,0 +1,19 @@
+SHELL   = /bin/sh
+CFLAGS  = -g -O0 -pipe -fpic -Wall -pedantic -std=c99
+LIBS    = -lpslib
+CFLAGS += `mysql_config --cflags`
+LIBS   += `mysql_config --libs`
+
+
+objects=[% table.namespace %]db.o
+
+all: lib[% table.namespace %]db.so
+
+lib[% table.namespace %]db.so: $(objects)
+	$(CC) $(CFLAGS) -shared -o lib[% table.namespace %]db.so $(objects) $(LIBS)
+
+$(objects): %.o : %.c
+	$(CC) $(CFLAGS) -o $@ -c $<
+
+clean:
+	$(RM) *.so *.o core test
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/metadatafromobject.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/metadatafromobject.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/metadatafromobject.tt	(revision 21994)
@@ -0,0 +1,21 @@
+psMetadata *[% table.namespace %]MetadataFromObject(const [% table.object_name %] *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+[% FOREACH item = table.columns -%]
+[% IF item.type == "S32" or item.type == "F32" or item.type == "F64" -%]
+    if (!psMetadataAdd[% item.type %](md, PS_LIST_TAIL, "[% item.name %]", 0, NULL, object->[% item.name %])) {
+[% ELSIF item.type == "STR" -%]
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "[% item.name %]", 0, NULL, psStringCopy(object->[% item.name %]))) {
+[% ELSIF item.type == "BOOL" -%]
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "[% item.name %]", PS_DATA_BOOL, NULL, object->[% item.name %])) {
+[% END -%]
+        psError(PS_ERR_UNKNOWN, false, "failed to add item [% item.name %]");
+        psFree(md);
+        return NULL;
+    }
+[% END -%]
+
+    return md;
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/metadatafromobject_at.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/metadatafromobject_at.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/metadatafromobject_at.tt	(revision 21994)
@@ -0,0 +1,6 @@
+AT_SETUP([[% table.namespace %]MetadataFromObject()])
+AT_KEYWORDS([[% table.namespace %]MetadataFromObject])
+
+AT_CHECK([metadatafromobject])
+
+AT_CLEANUP
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/metadatafromobject_c.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/metadatafromobject_c.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/metadatafromobject_c.tt	(revision 21994)
@@ -0,0 +1,53 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+#include <pslib.h>
+#include <[% pkg_name %].h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAX_STRING_LENGTH 1024
+
+int main ()
+{
+[% FOREACH table = tables -%]
+    {
+        psMetadata      *md;
+        [% indented(table.object_name, "*object") %];
+        bool            status;
+
+        object = [% table.object_name %]Alloc(
+[%- SET i = 0 -%]
+[%- FOREACH item = table.columns -%]
+    [%- IF i == 0 -%][%- i = 1 -%][%- ELSE -%], [% END -%] [%- item.test -%]
+[%- END -%]
+);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = [% table.namespace %]MetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+[% FOREACH item = table.columns -%]
+[% IF item.type == "S32" or item.type == "F32" or item.type == "F64" -%]
+        if (!psMetadataLookup[% item.type %](&status, md, "[% item.name %]") == [% item.test %]) {
+[% ELSIF item.type == "STR" -%]
+        if (strncmp(psMetadataLookupPtr(&status, md, "[% item.name %]"), [% item.test %], MAX_STRING_LENGTH)) {
+[% ELSIF item.type == "BOOL" -%]
+        if (!psMetadataLookupBool(&status, md, "[% item.name %]") == [% item.test %]) {
+[% END -%]
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+[% END -%]
+
+        psFree(md);
+    }
+
+[% END -%]
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/metadatafromobject_h.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/metadatafromobject_h.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/metadatafromobject_h.tt	(revision 21994)
@@ -0,0 +1,10 @@
+[% USE format -%]
+[% indented = format('%-15s %-20s') -%]
+/** Convert a [% table.object_name %] into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *[% table.namespace %]MetadataFromObject(
+    [% indented("const $table.object_name", "*object") %]///< fooRow to convert into a psMetadata
+);
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/object_h.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/object_h.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/object_h.tt	(revision 21994)
@@ -0,0 +1,17 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+/** [% table.object_name %] data structure
+ *
+ * Structure for representing a single row of [% table.name %] table data.
+ */
+
+typedef struct {
+[% SET i = 0 -%]
+[% FOREACH item = table.columns -%]
+[% IF item.type == "STR" -%]
+    [% indented("char", "*$item.name") %];
+[% ELSE -%]
+    [% indented("$item.ctype", "$item.name") %];
+[% END -%]
+[% END -%]
+} [% table.object_name %];
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/objectfrommetadata.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/objectfrommetadata.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/objectfrommetadata.tt	(revision 21994)
@@ -0,0 +1,34 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+[% table.object_name %] *[% table.namespace %]ObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+[% FOREACH item = table.columns -%]
+[% IF item.type == "STR" -%]
+    [% indented("char", "*$item.name") %];
+[% ELSE-%]
+    [% indented("$item.ctype", "$item.name") %];
+[% END -%]
+[% END -%]
+
+[% FOREACH item = table.columns -%]
+[% IF item.type == "S32" or item.type == "F32" or item.type == "F64" -%]
+    [% item.name %] = psMetadataLookup[% item.type %](&status, md, "[% item.name %]");
+[% ELSIF item.type == "STR" -%]
+    [% item.name %] = psMetadataLookupPtr(&status, md, "[% item.name %]");
+[% ELSIF item.type == "BOOL" -%]
+    [% item.name %] = psMetadataLookupBool(&status, md, "[% item.name %]");
+[% END -%]
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item [% item.name %]");
+        return false;
+    }
+[% END -%]
+
+    return [% table.object_name %]Alloc(
+[%- SET i = 0 -%]
+[% FOREACH item = table.columns -%]
+[% IF i == 0 -%][%- i = 1 -%][% ELSE %], [% END -%]
+[% item.name %]
+[%- END -%]);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/objectfrommetadata_at.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/objectfrommetadata_at.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/objectfrommetadata_at.tt	(revision 21994)
@@ -0,0 +1,6 @@
+AT_SETUP([[% table.namespace %]ObjectFromMetadata()])
+AT_KEYWORDS([[% table.namespace %]ObjectFromMetadata])
+
+AT_CHECK([objectfrommetadata])
+
+AT_CLEANUP
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/objectfrommetadata_c.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/objectfrommetadata_c.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/objectfrommetadata_c.tt	(revision 21994)
@@ -0,0 +1,55 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+#include <pslib.h>
+#include <[% pkg_name %].h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAX_STRING_LENGTH 1024
+
+int main ()
+{
+[% FOREACH table = tables -%]
+    {
+        psMetadata      *md;
+        [% indented(table.object_name, "*object") %];
+
+        md = psMetadataAlloc();
+[% FOREACH item = table.columns -%]
+[% IF item.type == "S32" or item.type == "F32" or item.type == "F64" -%]
+        if (!psMetadataAdd[% item.type %](md, PS_LIST_TAIL, "[% item.name %]", 0, NULL, [% item.test %])) {
+[% ELSIF item.type == "STR" -%]
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "[% item.name %]", 0, NULL, [% item.test %])) {
+[% ELSIF item.type == "BOOL" -%]
+        if (!psMetadataAdd(md, PS_LIST_TAIL, "[% item.name %]", PS_DATA_BOOL, NULL, [% item.test %])) {
+[% END -%]
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+[% END -%]
+
+        object = [% table.namespace %]ObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+[% FOREACH item = table.columns -%]
+[% IF item.type == "S32" or item.type == "F32" or item.type == "F64" or item.type == "BOOL" -%]
+        if (!object->[% item.name %] == [% item.test %]) {
+[% ELSIF item.type == "STR" -%]
+        if (strncmp(object->[% item.name %], [% item.test %], MAX_STRING_LENGTH)) {
+[% END -%]
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+[% END -%]
+
+        psFree(object);
+    }
+
+[% END -%]
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/objectfrommetadata_h.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/objectfrommetadata_h.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/objectfrommetadata_h.tt	(revision 21994)
@@ -0,0 +1,8 @@
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A [% table.object_name %] pointer or NULL on error
+ */
+
+[% table.object_name %] *[% table.namespace %]ObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/pkgconfig_pc_in.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/pkgconfig_pc_in.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/pkgconfig_pc_in.tt	(revision 21994)
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: @PACKAGE@
+Description: some library
+Version: @VERSION@
+Requires: pslib
+Libs: -L${libdir} -l@PACKAGE@
+Cflags: -I${includedir}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/pop.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/pop.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/pop.tt	(revision 21994)
@@ -0,0 +1,75 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+bool [% table.namespace %]Pop(psDB *dbh, 
+[%- SET i = 0 -%]
+[% FOREACH item = table.columns -%]
+[% IF i == 0 %][% i = 1 %][% ELSE %], [% END -%]
+[% IF item.type == "STR" -%]
+char **[% item.name -%]
+[% ELSE -%]
+[% item.ctype %] *[% item.name -%]
+[% END -%]
+[% END %])
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, [% table.namespace FILTER upper %]_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", [% table.namespace FILTER upper %]_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    // FIXME: psArrayGet should increment the ref count
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, [% table.namespace FILTER upper %]_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", [% table.namespace FILTER upper %]_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, [% table.namespace FILTER upper %]_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, [% table.namespace FILTER upper %]_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+[% FOREACH item = table.columns -%]
+[% IF item.type == "S32" or item.type == "F32" or item.type == "F64" -%]
+    *[% item.name %] = psMetadataLookup[% item.type %](&status, row, "[% item.name %]");
+[% ELSIF item.type == "STR" -%]
+    *[% item.name %] = psMetadataLookupPtr(&status, row, "[% item.name %]");
+[% ELSIF item.type == "BOOL" -%]
+    *[% item.name %] = psMetadataLookupBool(&status, row, "[% item.name %]");
+[% END -%]
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item [% item.name %]");
+        psFree(row);
+        return false;
+    }
+[% END -%]
+
+    psFree(row);
+
+    return true;
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/pop_at.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/pop_at.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/pop_at.tt	(revision 21994)
@@ -0,0 +1,10 @@
+AT_SETUP([[% table.namespace %]Pop()])
+AT_KEYWORDS([[% table.namespace %]Pop])
+
+AT_CHECK([dbsetup])
+# run insert so there is a row in the table
+AT_CHECK([insert])
+AT_CHECK([pop])
+AT_CHECK([dbcleanup])
+
+AT_CLEANUP
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/pop_c.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/pop_c.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/pop_c.tt	(revision 21994)
@@ -0,0 +1,43 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+#include <pslib.h>
+#include <[% pkg_name %].h>
+#include <stdlib.h>
+
+int main ()
+{
+[% FOREACH table = tables -%]
+    {
+        psDB            *dbh;
+[% FOREACH item = table.columns -%]
+[% IF item.type == "STR" -%]
+        [% indented("char", "$item.name[256]") %];
+[% ELSE-%]
+        [% indented("$item.ctype", "$item.name") %];
+[% END -%]
+[% END -%]
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (![% table.namespace %]Pop(dbh, 
+[%- SET i = 0 -%]
+[% FOREACH item = table.columns -%]
+[% IF i == 0 %][% i = 1 %][% ELSE %], [% END -%]
+[% IF item.type == "STR" -%]
+(char **)&[% item.name -%]
+[% ELSE-%]
+&[% item.name -%]
+[% END -%]
+[% END %])) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+[% END -%]
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/pop_h.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/pop_h.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/pop_h.tt	(revision 21994)
@@ -0,0 +1,19 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool [% table.namespace %]Pop(
+    psDB            *dbh,               ///< Database handle
+[%- SET i = 0 -%]
+[% FOREACH item = table.columns -%]
+[% IF i == 0 %][% i = 1 %][% ELSE %],[% END %]
+[% IF item.type == "STR" -%]
+    [% indented("char", "**$item.name") -%]
+[% ELSE -%]
+    [% indented("$item.ctype", "*$item.name") -%]
+[% END -%]
+[% END %]
+);
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popfits.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popfits.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popfits.tt	(revision 21994)
@@ -0,0 +1,24 @@
+bool [% table.namespace %]PopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (![% table.namespace %]SelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                [% table.namespace FILTER upper %]_TABLE_NAME, [% table.namespace FILTER upper %]_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popfits_at.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popfits_at.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popfits_at.tt	(revision 21994)
@@ -0,0 +1,13 @@
+AT_SETUP([[% table.namespace %]PopFits()])
+AT_KEYWORDS([[% table.namespace %]PopFits])
+
+AT_CHECK([dbsetup])
+# run insert so there is a row in the table
+AT_CHECK([insert])
+AT_CHECK([popfits])
+AT_CHECK([dbcleanup])
+if [ test -f "blargh" ] ; then
+    rm -f "blargh"
+fi
+
+AT_CLEANUP
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popfits_c.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popfits_c.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popfits_c.tt	(revision 21994)
@@ -0,0 +1,40 @@
+#include <pslib.h>
+#include <[% pkg_name %].h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#define TMP_FILENAME "./blargh"
+
+int main ()
+{
+[% FOREACH table = tables -%]
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (![% table.namespace %]PopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+[% END -%]
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popfits_h.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popfits_h.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popfits_h.tt	(revision 21994)
@@ -0,0 +1,13 @@
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool [% table.namespace %]PopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popobject.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popobject.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popobject.tt	(revision 21994)
@@ -0,0 +1,33 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+[% table.object_name %] *[% table.namespace %]PopObject(psDB *dbh)
+{
+[% FOREACH item = table.columns -%]
+[% IF item.type == "STR" -%]
+    [% indented("char", "$item.name[256]") %];
+[% ELSE-%]
+    [% indented("$item.ctype", "$item.name") %];
+[% END -%]
+[% END -%]
+
+    if (![% table.namespace %]Pop(dbh, 
+[%- SET i = 0 -%]
+[% FOREACH item = table.columns -%]
+[% IF i == 0 %][% i = 1 %][% ELSE %], [% END -%]
+[% IF item.type == "STR" -%]
+(char **)&[% item.name -%]
+[% ELSE-%]
+&[% item.name -%]
+[% END -%]
+[% END %])) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return [% table.object_name %]Alloc(
+[%- SET i = 0 -%]
+[% FOREACH item = table.columns -%]
+[% IF i == 0 -%][%- i = 1 -%][% ELSE %], [% END -%]
+[% item.name %]
+[%- END -%]);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popobject_at.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popobject_at.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popobject_at.tt	(revision 21994)
@@ -0,0 +1,10 @@
+AT_SETUP([[% table.namespace %]PopObject()])
+AT_KEYWORDS([[% table.namespace %]PopObject])
+
+AT_CHECK([dbsetup])
+# run insert so there is a row in the table
+AT_CHECK([insert])
+AT_CHECK([popobject])
+AT_CHECK([dbcleanup])
+
+AT_CLEANUP
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popobject_c.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popobject_c.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popobject_c.tt	(revision 21994)
@@ -0,0 +1,30 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+#include <pslib.h>
+#include <[% pkg_name %].h>
+#include <stdlib.h>
+
+int main ()
+{
+[% FOREACH table = tables -%]
+    {
+        psDB            *dbh;
+        [% indented(table.object_name, "*object") %];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = [% table.namespace %]PopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+[% END -%]
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popobject_h.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popobject_h.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/popobject_h.tt	(revision 21994)
@@ -0,0 +1,8 @@
+/** Removes the last row from the database and returns it
+ *
+ * @return A new [% table.object_name %] on success or NULL on failure.
+ */
+
+[% table.object_name %] *[% table.namespace %]PopObject(
+    psDB            *dbh                ///< Database handle
+);
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowobjects.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowobjects.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowobjects.tt	(revision 21994)
@@ -0,0 +1,33 @@
+psArray *[% table.namespace %]SelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, [% table.namespace FILTER upper %]_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, [% table.namespace FILTER upper %]_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", [% table.namespace FILTER upper %]_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, [% table.namespace %]ObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowobjects_h.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowobjects_h.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowobjects_h.tt	(revision 21994)
@@ -0,0 +1,12 @@
+/** Selects up to limit rows from the database and returns as [% table.object_name %] objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *[% table.namespace %]SelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowsfits.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowsfits.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowsfits.tt	(revision 21994)
@@ -0,0 +1,37 @@
+bool [% table.namespace %]SelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, [% table.namespace FILTER upper %]_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, [% table.namespace FILTER upper %]_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", [% table.namespace FILTER upper %]_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    // FIXME: needs to be after a new ext is written?
+    if (!psFitsSetExtName(fits, [% table.namespace FILTER upper %]_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to set FITS HDU extension name");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowsfits_at.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowsfits_at.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowsfits_at.tt	(revision 21994)
@@ -0,0 +1,13 @@
+AT_SETUP([[% table.namespace %]SelectRowsFits()])
+AT_KEYWORDS([[% table.namespace %]SelectRowsFits])
+
+AT_CHECK([dbsetup])
+# run insert so there is a row in the table
+AT_CHECK([insert])
+AT_CHECK([selectrowsfits])
+AT_CHECK([dbcleanup])
+if [ test -f "blargh" ] ; then
+    rm -f "blargh"
+fi
+
+AT_CLEANUP
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowsfits_c.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowsfits_c.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowsfits_c.tt	(revision 21994)
@@ -0,0 +1,34 @@
+#include <pslib.h>
+#include <[% pkg_name %].h>
+#include <stdlib.h>
+
+#define TMP_FILENAME "./blargh"
+
+int main ()
+{
+[% FOREACH table = tables -%]
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (![% table.namespace %]SelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+[% END -%]
+    exit(EXIT_SUCCESS);
+}
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowsfits_h.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowsfits_h.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/selectrowsfits_h.tt	(revision 21994)
@@ -0,0 +1,16 @@
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool [% table.namespace %]SelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/src_makefile_am.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/src_makefile_am.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/src_makefile_am.tt	(revision 21994)
@@ -0,0 +1,10 @@
+AM_CFLAGS = @[% pkg_name %]_CFLAGS@
+
+include_HEADERS = [% pkg_name %].h
+lib_LTLIBRARIES = lib[% pkg_name %].la
+lib[% pkg_name %]_la_CFLAGS  = $(PSLIB_CFLAGS) $(AM_CFLAGS)
+lib[% pkg_name %]_la_LIBS    = $(PSLIB_LIBS) $(AM_LIBS)
+lib[% pkg_name %]_la_LDFLAGS = -release $(PACKAGE_VERSION)
+lib[% pkg_name %]_la_SOURCES = \
+    [% pkg_name %].h \
+    [% pkg_name %].c
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/tests_makefile_am.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/tests_makefile_am.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/tests_makefile_am.tt	(revision 21994)
@@ -0,0 +1,67 @@
+# copied from bison-1.875d
+
+EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4
+
+DISTCLEANFILES       = atconfig $(check_SCRIPTS)
+MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE)
+
+## ------------ ##
+## package.m4.  ##
+## ------------ ##
+
+$(srcdir)/package.m4: $(top_srcdir)/configure.ac
+	{					\
+	  echo '# Signature of the current package.'; \
+	  echo 'm4_define([AT_PACKAGE_NAME],      [@PACKAGE_NAME@])'; \
+	  echo 'm4_define([AT_PACKAGE_TARNAME],   [@PACKAGE_TARNAME@])'; \
+	  echo 'm4_define([AT_PACKAGE_VERSION],   [@PACKAGE_VERSION@])'; \
+	  echo 'm4_define([AT_PACKAGE_STRING],    [@PACKAGE_STRING@])'; \
+	  echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \
+	} >$(srcdir)/package.m4
+
+## ------------ ##
+## Test suite.  ##
+## ------------ ##
+
+TESTSUITE = $(srcdir)/testsuite
+
+AUTOTEST = $(AUTOM4TE) --language=autotest
+$(TESTSUITE): package.m4 $(TESTSUITE_AT)
+	$(AUTOTEST) -I $(srcdir) testsuite.at -o $@.tmp
+	mv $@.tmp $@
+
+atconfig: $(top_builddir)/config.status
+	cd $(top_builddir) && ./config.status tests/$@
+
+clean-local:
+	test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean
+
+check-local: atconfig $(TESTSUITE)
+	$(SHELL) $(TESTSUITE)
+
+#
+# END BISON
+#
+
+UNITS = \
+	alloc \
+	init \
+	cleanup \
+	createtable \
+    droptable \
+    insert \
+    pop \
+    insertobject \
+    popobject \
+    insertfits \
+    popfits \
+    selectrowsfits \
+    metadatafromobject \
+    objectfrommetadata
+
+AM_CPPFLAGS = -I$(top_srcdir)/src$
+AM_CFLAGS   = @[% pkg_name %]_CFLAGS@ $(PSLIB_CFLAGS)$
+AM_LDFLAGS  = $(PSLIB_LIBS)$
+LDADD       = $(top_builddir)/src/lib[% pkg_name %].la$
+
+check_PROGRAMS = dbsetup dbcleanup $(UNITS)
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/testsuite_at.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/testsuite_at.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/testsuite_at.tt	(revision 21994)
@@ -0,0 +1,33 @@
+m4_version_prereq([2.59])
+
+AT_INIT
+
+###
+[% INCLUDE alloc_at.tt %]
+###
+[% INCLUDE init_at.tt %]
+###
+[% INCLUDE cleanup_at.tt %]
+###
+[% INCLUDE createtable_at.tt %]
+###
+[% INCLUDE droptable_at.tt %]
+###
+[% INCLUDE insert_at.tt %]
+###
+[% INCLUDE pop_at.tt %]
+###
+[% INCLUDE insertobject_at.tt %]
+###
+[% INCLUDE popobject_at.tt %]
+###
+[% INCLUDE insertfits_at.tt %]
+###
+[% INCLUDE popfits_at.tt %]
+###
+[% INCLUDE selectrowsfits_at.tt %]
+###
+[% INCLUDE metadatafromobject_at.tt %]
+###
+[% INCLUDE objectfrommetadata_at.tt %]
+###
Index: /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/top_makefile_am.tt
===================================================================
--- /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/top_makefile_am.tt	(revision 21994)
+++ /tags/ipp-1-X/rel-0_06/glueforge/templates/psdb/top_makefile_am.tt	(revision 21994)
@@ -0,0 +1,26 @@
+SUBDIRS = src tests
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA= [% pkg_name %].pc
+
+EXTRA_DIST = [% pkg_name %].pc.in Doxyfile.in
+
+man_MANS = \
+    $(top_builddir)/docs/man/man3/[% pkg_name %].3 \
+[%- FOREACH table = tables %]
+[% IF NOT loop.last -%]
+    $(top_builddir)/docs/man/man3/[% table.object_name %].3 \
+[%- ELSE -%]
+    $(top_builddir)/docs/man/man3/[% table.object_name %].3 
+[% END -%]
+[% END %]
+
+docs/man/man3/[% pkg_name %].3
+[%- FOREACH table = tables -%]
+ docs/man/man3/[% table.object_name %].3
+[%- IF loop.last %]:[% END -%]
+[%- END %]
+	$(DOXYGEN)
+
+clean-local:
+	-rm -rf docs
