SOPE/0000755000000000000000000000000015004363604010323 5ustar rootrootSOPE/sope-xml/0000755000000000000000000000000015004363604012067 5ustar rootrootSOPE/sope-xml/pyxSAXDriver/0000755000000000000000000000000015004363604014437 5ustar rootrootSOPE/sope-xml/pyxSAXDriver/bundle-info.plist0000644000000000000000000000045015004363604017715 0ustar rootroot{ requires = { bundleManagerVersion = 1; classes = ( { name = NSObject; } ); }; provides = { SAXDrivers = ( { name = pyxSAXDriver; sourceTypes = ( "text/pyx" ); } ); classes = ( { name = pyxSAXDriver; } ); }; } SOPE/sope-xml/pyxSAXDriver/pyxSAXDriver.h0000644000000000000000000000337315004363604017166 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __pyxSAXDriver_H__ #define __pyxSAXDriver_H__ #import #include #include #include #include #include #include #include #include @class NSMutableArray; @class SaxAttributes; @interface pyxSAXDriver : NSObject < SaxXMLReader > { @private id contentHandler; id dtdHandler; id errorHandler; id entityResolver; id lexicalHandler; id declHandler; int depth; NSMutableArray *nsStack; BOOL fNamespaces; BOOL fNamespacePrefixes; /* cache */ id locator; SaxAttributes *attrs; } @end #endif /* __pyxSAXDriver_H__ */ SOPE/sope-xml/pyxSAXDriver/GNUmakefile0000644000000000000000000000056315004363604016515 0ustar rootroot# GNUstep makefile include ../../config.make include $(GNUSTEP_MAKEFILES)/common.make include ../Version include ./Version BUNDLE_NAME = pyxSAXDriver BUNDLE_EXTENSION = .sax BUNDLE_INSTALL_DIR = ${SOPE_SAXDRIVERS}/ pyxSAXDriver_OBJC_FILES = pyxSAXDriver.m -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/bundle.make -include GNUmakefile.postamble SOPE/sope-xml/pyxSAXDriver/ChangeLog0000644000000000000000000000171415004363604016214 0ustar rootroot2004-11-04 Helge Hess * use Version file for install directory location 2004-08-29 Helge Hess * added hack to install the project in FHS locations - the SAX driver will be installed in FHS_INSTALL_ROOT if specified (eg make FHS_INSTALL_ROOT=/usr/local) 2004-08-24 Helge Hess * GNUmakefile: install SAX driver in Library/SaxDrivers-4.3/ * GNUmakefile: install SAX driver in Library/SaxDrivers/4.3/ 2004-05-05 Marcus Mueller * GNUmakefile: added support for building with GNUSTEP_BUILD_DIR environment variable set for recent gnustep-make package. 2003-12-03 Helge Hess * GNUmakefile: include common.make from GNUSTEP_MAKEFILES 2003-01-07 Helge Hess * fixed a compilation bug, maybe the driver needs to be updated to the current SAX API * created ChangeLog SOPE/sope-xml/pyxSAXDriver/COPYING0000644000000000000000000006130315004363604015475 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-xml/pyxSAXDriver/fhs.make0000644000000000000000000000137415004363604016063 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib64/ else FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib/ endif FHS_SAX_DIR=$(FHS_LIB_DIR)sope-$(SOPE_MAJOR_VERSION).$(SOPE_MINOR_VERSION)/saxdrivers/ fhs-sax-dirs :: $(MKDIRS) $(FHS_SAX_DIR) move-bundles-to-fhs :: fhs-sax-dirs @echo "moving bundles $(BUNDLE_INSTALL_DIR) to $(FHS_SAX_DIR) .." for i in $(BUNDLE_NAME); do \ j="$(FHS_SAX_DIR)/$${i}$(BUNDLE_EXTENSION)"; \ if test -d $$j; then rm -r $$j; fi; \ mv "$(BUNDLE_INSTALL_DIR)/$${i}$(BUNDLE_EXTENSION)" $$j; \ done move-to-fhs :: move-bundles-to-fhs after-install :: move-to-fhs endif SOPE/sope-xml/pyxSAXDriver/README0000644000000000000000000000052015004363604015314 0ustar rootrootpyxSAXDriver ============ This directory contains the sources for a SAX driver bundle which can read so called "pyx" files. PYX is a line based representation for XML useful for processing XML files using Unix cmdline tools (like grep or awk). The parser itself is written in Objective-C (and probably pretty slow for large files ;-) SOPE/sope-xml/pyxSAXDriver/GNUmakefile.postamble0000644000000000000000000000036215004363604020477 0ustar rootroot# postprocessing ifneq ($(GNUSTEP_BUILD_DIR),) after-all :: @(cp bundle-info.plist \ $(GNUSTEP_BUILD_DIR)/$(BUNDLE_NAME)$(BUNDLE_EXTENSION)) else after-all :: @(cd $(BUNDLE_NAME)$(BUNDLE_EXTENSION);\ cp ../bundle-info.plist .) endif SOPE/sope-xml/pyxSAXDriver/pyxSAXDriver-Info.plist0000644000000000000000000000151415004363604020756 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable pyxSAXDriver CFBundleGetInfoString CFBundleIconFile CFBundleIdentifier org.opengroupware.xml.pyxSAXDriver CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleShortVersionString CFBundleSignature ???? CFBundleVersion 4.2 CSResourcesFileMapped yes SOPE/sope-xml/pyxSAXDriver/pyxSAXDriver.m0000644000000000000000000002117315004363604017171 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pyxSAXDriver.h" #include #include #include #import #if NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY # include # include #endif static NSString *SaxDeclHandlerProperty = @"http://xml.org/sax/properties/declaration-handler"; static NSString *SaxLexicalHandlerProperty = @"http://xml.org/sax/properties/lexical-handler"; #if 0 static NSString *SaxDOMNodeProperty = @"http://xml.org/sax/properties/dom-node"; static NSString *SaxXMLStringProperty = @"http://xml.org/sax/properties/xml-string"; #endif @implementation pyxSAXDriver - (id)init { self->nsStack = [[NSMutableArray alloc] init]; /* feature defaults */ self->fNamespaces = YES; self->fNamespacePrefixes = NO; return self; } - (void)dealloc { RELEASE(self->nsStack); RELEASE(self->attrs); RELEASE(self->declHandler); RELEASE(self->lexicalHandler); RELEASE(self->contentHandler); RELEASE(self->dtdHandler); RELEASE(self->errorHandler); RELEASE(self->entityResolver); [super dealloc]; } /* properties */ - (void)setProperty:(NSString *)_name to:(id)_value { if ([_name isEqualToString:SaxLexicalHandlerProperty]) { ASSIGN(self->lexicalHandler, _value); return; } if ([_name isEqualToString:SaxDeclHandlerProperty]) { ASSIGN(self->declHandler, _value); return; } [SaxNotRecognizedException raise:@"PropertyException" format:@"don't know property %@", _name]; } - (id)property:(NSString *)_name { if ([_name isEqualToString:SaxLexicalHandlerProperty]) return self->lexicalHandler; if ([_name isEqualToString:SaxDeclHandlerProperty]) return self->declHandler; [SaxNotRecognizedException raise:@"PropertyException" format:@"don't know property %@", _name]; return nil; } /* features */ - (void)setFeature:(NSString *)_name to:(BOOL)_value { if ([_name isEqualToString:@"http://xml.org/sax/features/namespaces"]) { self->fNamespaces = _value; return; } if ([_name isEqualToString: @"http://xml.org/sax/features/namespace-prefixes"]) { self->fNamespacePrefixes = _value; return; } [SaxNotRecognizedException raise:@"FeatureException" format:@"don't know feature %@", _name]; } - (BOOL)feature:(NSString *)_name { if ([_name isEqualToString:@"http://xml.org/sax/features/namespaces"]) return self->fNamespaces; if ([_name isEqualToString: @"http://xml.org/sax/features/namespace-prefixes"]) return self->fNamespacePrefixes; [SaxNotRecognizedException raise:@"FeatureException" format:@"don't know feature %@", _name]; return NO; } /* handlers */ #if 0 - (void)setDocumentHandler:(id)_handler { SaxDocumentHandlerAdaptor *a; a = [[SaxDocumentHandlerAdaptor alloc] initWithDocumentHandler:_handler]; [self setContentHandler:a]; RELEASE(a); } #endif - (void)setDTDHandler:(id)_handler { ASSIGN(self->dtdHandler, _handler); } - (id)dtdHandler { return self->dtdHandler; } - (void)setErrorHandler:(id)_handler { ASSIGN(self->errorHandler, _handler); } - (id)errorHandler { return self->errorHandler; } - (void)setEntityResolver:(id)_handler { ASSIGN(self->entityResolver, _handler); } - (id)entityResolver { return self->entityResolver; } - (void)setContentHandler:(id)_handler { ASSIGN(self->contentHandler, _handler); } - (id)contentHandler { return self->contentHandler; } /* parsing */ - (void)parseFromSource:(id)_source { NSAutoreleasePool *pool; NSArray *lines; if ([_source isKindOfClass:[NSString class]]) { lines = [_source componentsSeparatedByString:@"\n"]; } else if ([_source isKindOfClass:[NSData class]]) { _source = [[NSString alloc] initWithData:_source encoding:[NSString defaultCStringEncoding]]; lines = [_source componentsSeparatedByString:@"\n"]; RELEASE(_source); } else { SaxParseException *e; NSDictionary *ui; ui = [NSDictionary dictionaryWithObjectsAndKeys: _source ? _source : @"", @"source", self, @"parser", nil]; e = (id)[SaxParseException exceptionWithName:@"SaxIOException" reason:@"can't handle data-source" userInfo:ui]; [self->errorHandler fatalError:e]; return; } pool = [[NSAutoreleasePool alloc] init]; /* start parsing lines */ { NSEnumerator *e; NSString *line; e = [lines objectEnumerator]; while ((line = [e nextObject])) { recheck: if ([line hasPrefix:@"("]) { NSMutableDictionary *ns = nil; NSString *startTag; NSDictionary *nsDict = nil; /* not yet finished ! */ startTag = [line substringFromIndex:1]; line = [e nextObject]; while ([line hasPrefix:@"A"]) { /* attribute */ NSString *rawName, *value; unsigned idx; line = [line substringFromIndex:1]; if ((idx = [line indexOfString:@" "]) == NSNotFound) { value = @""; rawName = line; } else { rawName = [line substringToIndex:idx]; value = [line substringFromIndex:(idx + 1)]; } if ([rawName hasPrefix:@"xmlns"]) { /* a namespace declaration */ if (ns == nil) ns = [[NSMutableDictionary alloc] init]; if ([rawName hasPrefix:@"xmlns:"]) { /* eg */ NSString *prefix, *uri; prefix = [rawName substringFromIndex:6]; uri = value; [ns setObject:uri forKey:prefix]; if (self->fNamespaces) [self->contentHandler startPrefixMapping:prefix uri:uri]; } else { /* eg */ [ns setObject:value forKey:@":"]; } } } /* start tag finished */ nsDict = [ns copy]; RELEASE(ns); ns = nil; /* manage namespace stack */ if (nsDict == nil) nsDict = [NSDictionary dictionary]; [self->nsStack addObject:nsDict]; /* to be completed ! */ if (line != nil) goto recheck; } } } RELEASE(pool); } - (void)parseFromSystemId:(NSString *)_sysId { NSString *s; /* _sysId is a URI */ if (![_sysId hasPrefix:@"file://"]) { SaxParseException *e; NSDictionary *ui; ui = [NSDictionary dictionaryWithObjectsAndKeys: _sysId ? _sysId : @"", @"systemID", self, @"parser", nil]; e = (id)[SaxParseException exceptionWithName:@"SaxIOException" reason:@"can't handle system-id" userInfo:ui]; [self->errorHandler fatalError:e]; return; } /* cut off file:// */ _sysId = [_sysId substringFromIndex:7]; /* start parsing .. */ if ((s = [NSString stringWithContentsOfFile:_sysId])) [self parseFromSource:s]; } /* entities */ - (NSString *)replacementStringForEntityNamed:(NSString *)_entityName { //NSLog(@"get entity: %@", _entityName); return [[@"&" stringByAppendingString:_entityName] stringByAppendingString:@";"]; } /* namespace support */ - (NSString *)nsUriForPrefix:(NSString *)_prefix { NSEnumerator *e; NSDictionary *ns; e = [self->nsStack reverseObjectEnumerator]; while ((ns = [e nextObject])) { NSString *uri; if ((uri = [ns objectForKey:_prefix])) return uri; } return nil; } - (NSString *)defaultNamespace { return [self nsUriForPrefix:@":"]; } @end /* pyxSAXDriver */ SOPE/sope-xml/pyxSAXDriver/GNUmakefile.preamble0000644000000000000000000000056315004363604020303 0ustar rootroot# compilation settings ifeq ($(frameworks),yes) BUNDLE_INSTALL_DIR := $(FRAMEWORK_INSTALL_DIR)/SaxObjC.framework/Resources/SaxDrivers/ endif pyxSAXDriver_RESOURCE_FILES = bundle-info.plist pyxSAXDriver_LOCALIZED_RESOURCE_FILES = pyxSAXDriver_BUNDLE_LIBS += -lSaxObjC ADDITIONAL_INCLUDE_DIRS += -I.. -I../.. ADDITIONAL_LIB_DIRS += -L../SaxObjC/$(GNUSTEP_OBJ_DIR) SOPE/sope-xml/pyxSAXDriver/slashdot.pyx0000644000000000000000000000776615004363604017042 0ustar rootroot(ultramode -\n (story -\n (title -100 Mbit/s on Fibre to the home )title -\n (url -http://slashdot.org/articles/99/06/06/1440211.shtml )url -\n (time -1999-06-06 14:39:59 )time -\n (author -CmdrTaco )author -\n (department -wouldn't-it-be-nice )department -\n (topic -internet )topic -\n (comments -20 )comments -\n (section -articles )section -\n (image -topicinternet.jpg )image -\n )story -\n (story -\n (title -Gimp 1.2 Preview )title -\n (url -http://slashdot.org/articles/99/06/06/1438246.shtml )url -\n (time -1999-06-06 14:38:40 )time -\n (author -CmdrTaco )author -\n (department -stuff-to-read )department -\n (topic -gimp )topic -\n (comments -12 )comments -\n (section -articles )section -\n (image -topicgimp.gif )image -\n )story -\n (story -\n (title -Sony's AIBO robot Sold Out )title -\n (url -http://slashdot.org/articles/99/06/06/1432256.shtml )url -\n (time -1999-06-06 14:32:51 )time -\n (author -CmdrTaco )author -\n (department -stuff-to-see )department -\n (topic -tech )topic -\n (comments -10 )comments -\n (section -articles )section -\n (image -topictech2.jpg )image -\n )story -\n (story -\n (title -Ask Slashdot: Another Word for "Hacker"? )title -\n (url -http://slashdot.org/askslashdot/99/06/05/1815225.shtml )url -\n (time -1999-06-05 20:00:00 )time -\n (author -Cliff )author -\n (department -hacker-vs-cracker )department -\n (topic -news )topic -\n (comments -385 )comments -\n (section -askslashdot )section -\n (image -topicnews.gif )image -\n )story -\n (story -\n (title -Corel Linux FAQ )title -\n (url -http://slashdot.org/articles/99/06/05/1842218.shtml )url -\n (time -1999-06-05 18:42:06 )time -\n (author -CmdrTaco )author -\n (department -stuff-to-read )department -\n (topic -corel )topic -\n (comments -164 )comments -\n (section -articles )section -\n (image -topiccorel.gif )image -\n )story -\n (story -\n (title -Upside downsides MP3.COM. )title -\n (url -http://slashdot.org/articles/99/06/05/1558210.shtml )url -\n (time -1999-06-05 15:56:45 )time -\n (author -CmdrTaco )author -\n (department -stuff-to-think-about )department -\n (topic -music )topic -\n (comments -48 )comments -\n (section -articles )section -\n (image -topicmusic.gif )image -\n )story -\n (story -\n (title -2 Terabits of Bandwidth )title -\n (url -http://slashdot.org/articles/99/06/05/1554258.shtml )url -\n (time -1999-06-05 15:53:43 )time -\n (author -CmdrTaco )author -\n (department -faster-porn )department -\n (topic -internet )topic -\n (comments -66 )comments -\n (section -articles )section -\n (image -topicinternet.jpg )image -\n )story -\n (story -\n (title -Suppression of cold fusion research? )title -\n (url -http://slashdot.org/articles/99/06/04/2313200.shtml )url -\n (time -1999-06-04 23:12:29 )time -\n (author -Hemos )author -\n (department -possibly-probably )department -\n (topic -science )topic -\n (comments -217 )comments -\n (section -articles )section -\n (image -topicscience.gif )image -\n )story -\n (story -\n (title -California Gov. Halts Wage Info Sale )title -\n (url -http://slashdot.org/articles/99/06/04/235256.shtml )url -\n (time -1999-06-04 23:05:34 )time -\n (author -Hemos )author -\n (department -woo-hoo! )department -\n (topic -usa )topic -\n (comments -16 )comments -\n (section -articles )section -\n (image -topicus.gif )image -\n )story -\n (story -\n (title -Red Hat Announces IPO )title -\n (url -http://slashdot.org/articles/99/06/04/0849207.shtml )url -\n (time -1999-06-04 19:30:18 )time -\n (author -Justin )author -\n (department -details-sketchy )department -\n (topic -redhat )topic -\n (comments -155 )comments -\n (section -articles )section -\n (image -topicredhat.gif )image -\n )story -\n )ultramode SOPE/sope-xml/GNUmakefile0000644000000000000000000000102315004363604014135 0ustar rootroot# GNUstep makefile include ../config.make include $(GNUSTEP_MAKEFILES)/common.make PACKAGE_NAME=sope-xml VERSION=4.5.0 SUBPROJECTS = \ SaxObjC \ DOM \ XmlRpc SUBPROJECTS += STXSaxDriver ifneq ($(HAS_LIBRARY_xml2),no) SUBPROJECTS += libxmlSAXDriver endif ifeq ($(frameworks),yes) include umbrella.make endif # project makefiles include $(GNUSTEP_MAKEFILES)/aggregate.make ifeq ($(frameworks),yes) include $(GNUSTEP_MAKEFILES)/framework.make endif # package macosx-pkg :: all ../maintenance/make-osxpkg.sh sope-xml SOPE/sope-xml/ChangeLog0000644000000000000000000000551215004363604013644 0ustar rootroot2008-03-03 Marcus Mueller * README-OSX.txt: Updated 2006-04-21 Marcus Mueller * GNUmakefile: reverse test for libxml2 existence flag - this allows for building libxml2 even if we didn't run configure :-) 2005-08-26 Helge Hess * all makefiles: add common.h as the precompiled header file 2005-08-09 Helge Hess * all makefiles: added flags to build only frameworks on MacOSX 2004-10-17 Helge Hess * all makefiles: include config.make if available 2004-09-21 Marcus Mueller * sope-xml.xcode: Fixed dependencies to resemble the make process more closely. Our aim should be to stick to the make process as closely as possible, so we shouldn't introduce dependencies in non-toplevel projects. 2004-08-29 Marcus Mueller * sope-xml.xcode: new Xcode aggregate project * SxXML*: removed old Xcode projects 2004-08-20 Helge Hess * moved iCalSaxDriver to sope-ical * moved ExpatSaxDriver, CFXMLSaxDriver to Recycler * moved PlistSaxDriver to samples 2004-08-03 Marcus Mueller * SxXML.xcode: fixed missing SaxObjC build dependency. libxmlSAXDriver is now built before SaxObjC, so copying it in the framework's wrapper will succeed. 2004-07-21 Marcus Mueller * README-OSX.txt: Major overhaul for build description, especially the Xcode section. 2004-07-16 Marcus Mueller * SxXML.xcode: added 'Wrapper' build style and 'Wrapper Contents' target. Use these to build the frameworks in an appropriate form to have them embedded in an applications app wrapper's 'Frameworks' folder. 2004-05-05 Marcus Mueller * ExpatSaxDriver/GNUmakefile, PlistSaxDriver/GNUmakefile: added support for building with GNUSTEP_BUILD_DIR environment variable set for recent gnustep-make package. 2004-03-24 Marcus Mueller * SxXML.xcode: added -headerpad_max_install_names to linker flags where appropriate. 2004-03-08 Helge Hess * SxXML.xcode: added a README file * README-OSX.txt: added some build notes 2004-02-29 Helge Hess * GNUmakefile: compile STXSaxDriver per default * SxXML.xcode: added new STXSaxDriver for parsing structured text files 2004-02-10 Marcus Mueller * SxXML.xcode: Updated prebinding information according to README-OSX.txt. Also, added Foundation.framework explicitly to all subprojects. * README-OSX.txt: New README currently describing prebinding information for Mac OS X. * ChangeLog: created. SOPE/sope-xml/dummy.c0000644000000000000000000000151115004363604013364 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // required for compilation of empty MacOSX frameworks ... SOPE/sope-xml/STXSaxDriver/0000755000000000000000000000000015004363604014375 5ustar rootrootSOPE/sope-xml/STXSaxDriver/bundle-info.plist0000644000000000000000000000064315004363604017657 0ustar rootroot{ requires = { bundleManagerVersion = 1; classes = ( { name = NSObject; } ); }; provides = { SAXDrivers = ( { name = STXSaxDriver; sourceTypes = ( "text/structured" ); }, { name = STXSaxDriver; sourceTypes = ( "text/restructured" ); } ); classes = ( { name = STXSaxDriver; } ); }; } SOPE/sope-xml/STXSaxDriver/STXSaxDriver-Info.plist0000644000000000000000000000153515004363604020655 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable STXSaxDriver CFBundleGetInfoString CFBundleIconFile CFBundleIdentifier org.opengroupware.SOPE.sope-xml.STXSaxDriver CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleShortVersionString CFBundleSignature ???? CFBundleVersion 4.5.14 NSPrincipalClass STXSaxDriver SOPE/sope-xml/STXSaxDriver/GNUmakefile0000644000000000000000000000102515004363604016445 0ustar rootroot# GNUstep makefile include ../../config.make include $(GNUSTEP_MAKEFILES)/common.make include ../Version include ./Version BUNDLE_NAME = STXSaxDriver BUNDLE_EXTENSION = .sax BUNDLE_INSTALL_DIR = $(SOPE_SAXDRIVERS) STXSaxDriver_PCH_FILE = common.h STXSaxDriver_OBJC_FILES += \ STXSaxDriver.m \ StructuredTextBodyElement+SAX.m STXSaxDriver_SUBPROJECTS += \ ExtraSTX \ Model STXSaxDriver_RESOURCE_FILES += Version -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/bundle.make -include GNUmakefile.postamble SOPE/sope-xml/STXSaxDriver/ChangeLog0000644000000000000000000002157215004363604016156 0ustar rootroot2007-02-21 Marcus Mueller * v4.7.15 * STXSaxDriver.m, ExtraSTX/StructuredTextRenderingDelegate.h: changed the API, which was broken by design, to properly deal with block elements (which can be nested). * Model/{StructuredTextBodyElement.[hm], StructuredTextParagraph.m}: changed API and implementation to properly deal with block elements. * data/znektest1.stx: trimmed testcase 2007-02-19 Marcus Mueller * data/znektest1.stx: added testcase demonstrating a bug in conjunction with lists and hyperlinks 2007-02-12 Marcus Mueller * STXSaxDriver.xcodeproj: added Xcode 2.4 project file 2006-07-03 Helge Hess * fixed gcc 4.1 warnings, use %p for pointers formats (v4.5.14) 2005-08-27 Helge Hess * added common.h in project subdirs for PCH support (v4.5.13) 2005-08-16 Helge Hess * v4.5.12 * install into SaxObjC framework Resources when being used with OSX * bumped version to 4.5 to be consistent with the remaining SOPE versioning 2005-05-03 Helge Hess * Model/StructuredTextBodyElement.m: fixed a gcc 4.0 warning (v1.0.11) 2004-11-04 Helge Hess * use Version file for install directory location 2004-10-21 Helge Hess * ExtraSTX/GNUmakefile, Model/GNUmakefile: fixed for config.make compilation (v1.0.10) 2004-08-29 Helge Hess * added hack to install the project in FHS locations - the SAX driver will be installed in FHS_INSTALL_ROOT if specified (eg make FHS_INSTALL_ROOT=/usr/local) (v1.0.9) 2004-08-24 Helge Hess * GNUmakefile: install SAX driver in Library/SaxDrivers-4.3/ (v1.0.8) * GNUmakefile: install SAX driver in Library/SaxDrivers/4.3/ (v1.0.7) 2004-05-05 Marcus Mueller * GNUmakefile.preamble, GNUmakefile.postamble: added support for building with GNUSTEP_BUILD_DIR environment variable set for recent gnustep-make package. (v1.0.6) 2004-03-16 Helge Hess * bundle-info.plist: fixed a type in the bundle-info.plist (v1.0.5) 2004-03-04 Helge Hess * STXSaxDriver.m: fixed a bug with header generation (header subelements did not properly generate) (v1.0.4) * STXSaxDriver.m: added proper error handling for missing files (v1.0.3) 2004-03-04 Helge Hess * ExtraSTX/StructuredText.m: applied a bugfix on the header processing by Mirko (v1.0.2) 2004-02-29 Helge Hess * v1.0.1 * initial import of the SAX driver into OpenGroupware.org - many thanks go to extrapola for contributing the STX framework to OGo * removed things unnecessary for the SAX driver * replace some -rangeOfString: NSNotFound checks which do not work with libFoundation (need to check for range.length==0 instead!) * added the STXSaxDriver, an application of the StructuredText code * reformatted code according to OGo styleguides 2004-02-15 Mirko Viviani * StructuredTextBodyElement.m: implementato link image ed escaping stile C. * NSString_StructuredText_Extra.m: implementato escaping di stringhe. 2004-02-10 Giulio Cesare Solaroli * Aggiunti alcuni test per la verifica della gestione dei link attorno alle immagini. 2004-01-16 Giulio Cesare Solaroli * Aggiunto un test (test__characterEscaping) che fallisce, mostrando un problema nella gestione nell'escape dei caratteri. 2004-01-13 Mirko Viviani * StructuredText.m ([-separateIntoBlocks]): ignora linee contenente solo spazi o tab. 2004-01-12 Mirko Viviani * StructuredText.m ([-separateIntoBlocks]): rimuove \r dal testo. 2004-01-08 Mirko Viviani * StructuredText.subproj/StructuredTextBodyElement.m: fix del link target. 2003-12-19 Mirko Viviani * StructuredText.subproj/StructuredTextBodyElement.m: aggiunto riconoscimento chiavi dinamiche. * StructuredTextRenderingDelegate.h: aggiunto metodo chiamato per chiavi dinamiche. 2003-12-18 Mirko Viviani * StructuredTextRenderingDelegate.m ([-insertPreprocessedTextForKey: inContext:]): metodo chiamato dal preprocessore per sostituire le chiavi. * StructuredText.subproj/StructuredTextBodyElement.m: implementato preprocessore. 2003-12-16 Mirko Viviani * Test.subproj/Test_StructuredText.m: aggiunto test per link Extrapola. * StructuredTextRenderingDelegate.h: corretto metodo per link Extrapola e aggiunto parametro target al link. * StructuredText.subproj/StructuredTextBodyElement.m: implementato link Extrapola. 2003-12-11 Mirko Viviani * StructuredText.subproj/StructuredTextHeader.m: implementato rendering con delegate. * StructuredText.subproj/StructuredTextListItem.m: come sopra. * StructuredText.subproj/StructuredTextBodyElement.m: Spostato il parser da StructuredTextParagraph. 2003-12-08 Mirko Viviani * StructuredText.subproj/StructuredTextParagraph.m: implementati link. * Test.subproj/StructuredText_TEST.m ([StructuredTextListItem -toTestInContext:]): fix per liste nidificate. * StructuredText_XHTML.m ([StructuredTextListItem -toXhtmlInContext:]): come sopra. * Test.subproj/Test_StructuredText.m: corretti vari tests. * StructuredLine.m ([-setText:]): setta correttamente il numero di spazi iniziali. * StructuredText.m ([-buildList], [-checkForListItem:]): implementata lista numerata. ([-adjustLineLevels]): setta i livelli correttamente anche per liste. ([-lineType]): fix per liste. ([-checkForListItem]): spostato codice in listItemTypology: ([-buildList]): fix per liste nidificate. * StructuredStack.m ([-pop]): posiziona correttamente il cursore. 2003-12-08 Mirko Viviani * StructuredText.subproj/StructuredTextParagraph.m ([-parseText:inContext:]): modificato in metodo ricorsivo. Implementato bold, underline e italico. ([-findBoldSubstring:]: Ricerca terminatore stringa in grassetto. ([-findItalicsSubstring:]: Ricerca terminatore stringa in italico. ([-findUnderlineSubstring:]: Ricerca terminatore stringa in sottolineato. ([-boldText:inContext]): formatta il testo con il delegato. ([-italicsText:inContext]): come sopra. ([-underlineText:inContext]): come sopra. 2003-12-05 Mirko Viviani * StructuredText_XHTML.m ([StructuredTextListItem -toXhtmlInContext]): fix per list item. * StructuredText.m ([-buildLiteralBlock]): aggiunto newline a fine riga. 2003-12-04 Mirko Viviani * StructuredText.subproj/StructuredTextHeader.m: modificato inizializzatore per settare il livello dell'header. Vari fix. * StructuredText.m: implementate le liste di tipo DEFINITION, i blocchi preformattati e gli header. * StructuredLine.m ([-setText:]: setta il testo originale. ([-text]): ritorna il testo privo di spazi iniziali/finali e newline. ([-originalText]): ritorna il testo originale. * StructuredText.subproj/StructuredTextLiteralBlock.m ([-initWithString:]: inizializza il blocco. * StructuredText.subproj/StructuredTextListItem.m: aggiunto testo del list item per i tipi DEFINITION. * StructuredStack.m ([-objectRelativeToCursorAtIndex:]: ritorna l'oggetto con un indice relativo alla posizione corrente del cursore. 2003-12-01 Mirko Viviani * StructuredText.subproj/StructuredTextBodyElement.m: metodi per la gestione degli elementi figli. * StructuredText.m: fix delle strutture di stack, una (paragraphs) per la gestione delle linee di testo da processare, l'altra (stack) per la posizione nell'albero del documento. * StructuredStack.m ([StructuredStack -currentObject], [StructuredStack -nextObject]): fix per fine array. * StructuredText.subproj/StructuredTextList.h: fix typo. * StructuredText.subproj/StructuredTextListItem.m.|.h: inizializzazione e settaggio lista di appartenenza. _list non deve essere rilasciato. 2003-11-27 Mirko Viviani * StructuredTextRenderingDelegate.m ([StructuredTextRenderingDelegate -insertExtrapolaLink:withAction:parameters:inContext:]): uso di NSStringFromClass() per ottenere nome di classe. * StructuredText.subproj/StructuredTextParagraph.m: inizializzazione e minimo uso del delegate per il test. * StructuredText.subproj/StructuredTextDocument.m|.h ([-addBodyElement]): aggiunge un elemento al documento. * PB.project, GSmakefile, Makefile: Aggiunto framework IBNExtensions SOPE/sope-xml/STXSaxDriver/common.h0000644000000000000000000000150715004363604016041 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #import SOPE/sope-xml/STXSaxDriver/ExtraSTX/0000755000000000000000000000000015004363604016057 5ustar rootrootSOPE/sope-xml/STXSaxDriver/ExtraSTX/StructuredText_XHTML.h0000644000000000000000000000365615004363604022227 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #error does not compile, just for reference! @interface StructuredTextRenderingDelegate_XHTML : StructuredTextRenderingDelegate @end @interface NSArray (StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)aContext; @end @interface StructuredText (StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)aContext; @end @interface StructuredTextDocument (StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)aContext; @end @interface StructuredTextBodyElement (StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)aContext; @end @interface StructuredTextHeader (StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)aContext; @end @interface StructuredTextParagraph (StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)aContext; @end @interface StructuredTextList (StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)aContext; @end @interface StructuredTextListItem (StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)aContext; @end @interface StructuredTextLiteralBlock (StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)aContext; @end SOPE/sope-xml/STXSaxDriver/ExtraSTX/GNUmakefile0000644000000000000000000000063015004363604020130 0ustar rootroot# GNUstep makefile include ../../../config.make include $(GNUSTEP_MAKEFILES)/common.make SUBPROJECT_NAME = ExtraSTX ExtraSTX_PCH_FILE = common.h ExtraSTX_OBJC_FILES = \ NSString+STX.m \ StructuredLine.m \ StructuredStack.m \ StructuredText.m \ ADDITIONAL_INCLUDE_DIRS += -I. -I../Model -I.. -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/subproject.make -include GNUmakefile.postamble SOPE/sope-xml/STXSaxDriver/ExtraSTX/StructuredStack.h0000644000000000000000000000232515004363604021364 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import @interface StructuredStack : NSObject { NSMutableArray *_stack; int start; int pos; BOOL cursorFIFO; } - (NSMutableArray *)stack; - (void)removeAllObjects; - (void)push:(id)anObject; - (id)pop; - (void)first; - (void)last; - (id)nextObject; - (id)currentObject; - (id)prevObject; - (BOOL)cursorFollowsFIFO; - (void)setCursorFollowsFIFO:(BOOL)aValue; - (id)objectRelativeToCursorAtIndex:(int)anIndex; @end SOPE/sope-xml/STXSaxDriver/ExtraSTX/common.h0000644000000000000000000000002715004363604017517 0ustar rootroot#include "../common.h" SOPE/sope-xml/STXSaxDriver/ExtraSTX/StructuredText_XHTML.m0000644000000000000000000001667515004363604022241 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #error does not compile, just for reference! #include "StructuredText_XHTML.h" #include "common.h" @implementation StructuredTextRenderingDelegate_XHTML - (NSString *)insertText:(NSString *)_txt inContext:(NSDictionary *)_ctx { return [NSString stringWithFormat:@"

%@

", _txt]; } - (NSString *)insertItalics:(NSString *)_txt inContext:(NSDictionary *)_ctx { return [NSString stringWithFormat: @"%@", _txt]; } - (NSString *)insertUnderline:(NSString *)_txt inContext:(NSDictionary *)_ctx { return [NSString stringWithFormat: @"%@", _txt]; } - (NSString *)insertBold:(NSString *)_txt inContext:(NSDictionary *)_ctx { return [NSString stringWithFormat:@"%@", _txt]; } - (NSString *)insertPreformatted:(NSString *)_txt inContext:(NSDictionary *)_ctx { return [NSString stringWithFormat: @"%@", _txt]; } - (NSString *)insertLink:(NSString *)_txt withUrl:(NSString *)anUrl target:(NSString *)aTarget inContext:(NSDictionary *)_ctx { NSString *result; if ([aTarget length] > 0) { result = [NSString stringWithFormat: @"%@", anUrl, aTarget, _txt]; } else { result = [NSString stringWithFormat:@"%@", anUrl, _txt]; } return result; } - (NSString *)insertEmail:(NSString *)_txt withAddress:(NSString *)anAddress inContext:(NSDictionary *)_ctx { return [NSString stringWithFormat:@"%@", anAddress, _txt]; } - (NSString *)insertImage:(NSString *)_txt withUrl:(NSString *)anUrl inContext:(NSDictionary *)_ctx { return [NSString stringWithFormat:@"", anUrl, _txt]; } - (NSString *)insertExtrapolaLink:(NSString *)_txt parameters:(NSDictionary *)someParameters withTarget:(NSString *)aTarget inContext:(NSDictionary *)_ctx { NSString *result; NSString *targetString; if ([aTarget length] > 0) targetString = [NSString stringWithFormat:@" target = \"%@\"", aTarget]; else targetString = @""; result = [NSString stringWithFormat: @"%@", [someParameters objectForKey:@"page"], targetString, _txt]; return result; } - (NSString *)insertPreprocessedTextForKey:(NSString *)aKey inContext:(NSDictionary *)_ctx { return [_ctx objectForKey:aKey]; } @end /* StructuredTextRenderingDelegate_XHTML */ @implementation NSArray (StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)_ctx { NSMutableString *result; int i,c; c = [self count]; result = [NSMutableString stringWithCapacity:(c * 16)]; for (i = 0; i < c; i++) { id currentObject; currentObject = [self objectAtIndex:i]; [result appendString:[currentObject toXhtmlInContext:_ctx]]; } return result; } @end @implementation StructuredText(StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)_ctx { return [[self document] toXhtmlInContext:_ctx]; } @end /* StructuredText(StructuredText_XHTML) */ @implementation StructuredTextDocument(StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)_ctx { return [[self bodyElements] toXhtmlInContext:_ctx]; } @end /* StructuredTextDocument(StructuredText_XHTML) */ @implementation StructuredTextBodyElement(StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)_ctx { return [[self elements] toXhtmlInContext:_ctx]; } @end /* StructuredTextBodyElement(StructuredText_XHTML) */ @implementation StructuredTextHeader(StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)_ctx { NSMutableString *ms; id delegate; delegate = [StructuredTextRenderingDelegate_XHTML delegate] ; ms = [NSMutableString stringWithCapacity:64]; [ms appendFormat:@"", [self level]]; [ms appendString:[self textParsedWithDelegate:delegate inContext:_ctx]]; [ms appendFormat:@"", [self level]]; [ms appendString:[super toXhtmlInContext:_ctx]]; return ms; } @end /* StructuredTextHeader(StructuredText_XHTML) */ @implementation StructuredTextParagraph(StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)_ctx { id delegate; delegate = [StructuredTextRenderingDelegate_XHTML delegate]; return [self textParsedWithDelegate:delegate inContext:_ctx]; } @end /* StructuredTextParagraph (StructuredText_XHTML) */ @implementation StructuredTextList(StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)_ctx { NSString *result; NSString *elemText; elemText = [[self elements] toXhtmlInContext:_ctx]; switch ([self typology]) { case StructuredTextList_BULLET: { result = [NSString stringWithFormat:@"
    %@
", elemText]; break; } case StructuredTextList_ENUMERATED: { result = [NSString stringWithFormat:@"
    %@
", elemText]; break; } case StructuredTextList_DEFINITION: { result = [NSString stringWithFormat:@"
%@
", elemText]; break; } default: { result = @""; break; } } return result; } @end /* StructuredTextList(StructuredText_XHTML) */ @implementation StructuredTextListItem(StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)_ctx { NSString *result; NSString *textParsed; NSString *elemText; elemText = [[self elements] toXhtmlInContext:_ctx]; textParsed = [self textParsedWithDelegate: [StructuredTextRenderingDelegate_XHTML delegate] inContext:_ctx]; switch ([[self list] typology]) { case StructuredTextList_BULLET: { result = [NSString stringWithFormat:@"
  • %@%@
  • ", textParsed, elemText]; break; } case StructuredTextList_ENUMERATED: { result = [NSString stringWithFormat:@"
  • %@%@
  • ", textParsed, elemText]; break; } case StructuredTextList_DEFINITION: { result = [NSString stringWithFormat:@"
    %@
    %@
    ", [self titleParsedWithDelegate: [StructuredTextRenderingDelegate_XHTML delegate] inContext:_ctx], textParsed]; break; } default: { result = @""; break; } } return result; } @end /* StructuredTextListItem(StructuredText_XHTML) */ @implementation StructuredTextLiteralBlock(StructuredText_XHTML) - (NSString *)toXhtmlInContext:(NSDictionary *)_ctx { return [NSString stringWithFormat: @"
    %@
    ", [self text]]; } @end /* StructuredTextLiteralBlock(StructuredText_XHTML) */ SOPE/sope-xml/STXSaxDriver/ExtraSTX/NSString+STX.m0000644000000000000000000000337115004363604020422 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSString+STX.h" #include "common.h" @implementation NSString(STX) - (StructuredText *)structuredText { return [[[StructuredText alloc] initWithString:self] autorelease]; } - (NSString *)unescapedString { NSMutableString *result; NSString *text; int i, start, length; NSRange range; result = [NSMutableString stringWithCapacity:[self length]]; text = self; length = [text length]; for (i = start = 0; i < length; i++) { unichar c; c = [text characterAtIndex:i]; if (c == '\\') { if (i - start > 0) { range.location = start; range.length = i - start; [result appendString:[text substringWithRange:range]]; } if (i + 1 < length) { c = [text characterAtIndex:i + 1]; if (c == '\\') { start = ++i; } } } } if (i - start > 0) { range.location = start; range.length = i - start; [result appendString:[text substringWithRange:range]]; } return result; } @end /* NSString(STX) */ SOPE/sope-xml/STXSaxDriver/ExtraSTX/README0000644000000000000000000000211515004363604016736 0ustar rootroot How to use ========== 1. get a string in structured text format: NSString *s = "a\nb\nc" 2. parse it into "StructuredText" object: StructuredText *stx = [s structuredText]; or: StructuredText *stx = [[StructuredText alloc] initWithString:s]; 3. render the object, eg using -toXhtmlInContext: Defaults ======== STXDebugEnabled YES|NO Links ===== http://www.zope.org/Members/millejoh/structuredText http://plone.org/documentation/howto/FrontPage/UsingStructuredText Classes ======= NSObject StructuredLine StructuredStack StructuredText StructuredTextRenderingDelegate StructuredTextRenderingDelegate_XHTML NSString(NSString_StructuredText_Extra) NSArray(StructuredText_XHTML) StructuredText(StructuredText_XHTML) StructuredTextDocument(StructuredText_XHTML) StructuredTextBodyElement(StructuredText_XHTML) StructuredTextHeader(StructuredText_XHTML) StructuredTextParagraph(StructuredText_XHTML) StructuredTextList(StructuredText_XHTML) StructuredTextListItem(StructuredText_XHTML) StructuredTextLiteralBlock(StructuredText_XHTML) SOPE/sope-xml/STXSaxDriver/ExtraSTX/NSString+STX.h0000644000000000000000000000177615004363604020424 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NSString_STX_H__ #define __NSString_STX_H__ #import #import "StructuredText.h" @interface NSString(STX) - (StructuredText *)structuredText; - (NSString *)unescapedString; @end #endif /* __NSString_STX_H__ */ SOPE/sope-xml/STXSaxDriver/ExtraSTX/StructuredTextRenderingDelegate.h0000644000000000000000000000442315004363604024535 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __StructuredTextRenderingDelegate_H__ #define __StructuredTextRenderingDelegate_H__ #import @class NSString, NSDictionary; @protocol StructuredTextRenderingDelegate - (void)appendText:(NSString *)_txt inContext:(NSDictionary *)_ctx; - (void)beginItalicsInContext:(NSDictionary *)_ctx; - (void)endItalicsInContext:(NSDictionary *)_ctx; - (void)beginUnderlineInContext:(NSDictionary *)_ctx; - (void)endUnderlineInContext:(NSDictionary *)_ctx; - (void)beginBoldInContext:(NSDictionary *)_ctx; - (void)endBoldInContext:(NSDictionary *)_ctx; - (void)beginPreformattedInContext:(NSDictionary *)_ctx; - (void)endPreformattedInContext:(NSDictionary *)_ctx; - (void)beginParagraphInContext:(NSDictionary *)_ctx; - (void)endParagraphInContext:(NSDictionary *)_ctx; - (NSString *)insertLink:(NSString *)_txt withUrl:(NSString *)anUrl target:(NSString *)aTarget inContext:(NSDictionary *)_ctx; - (NSString *)insertEmail:(NSString *)_txt withAddress:(NSString *)anAddress inContext:(NSDictionary *)_ctx; - (NSString *)insertImage:(NSString *)_txt withUrl:(NSString *)anUrl inContext:(NSDictionary *)_ctx; - (NSString *)insertExtrapolaLink:(NSString *)_txt parameters:(NSDictionary *)someParameters withTarget:(NSString *)aTarget inContext:(NSDictionary *)_ctx; - (NSString *)insertDynamicKey:(NSString *)_txt inContext:(NSDictionary *)_ctx; - (NSString *)insertPreprocessedTextForKey:(NSString *)aKey inContext:(NSDictionary *)_ctx; @end #endif /* __StructuredTextRenderingDelegate_H__ */ SOPE/sope-xml/STXSaxDriver/ExtraSTX/StructuredStack.m0000644000000000000000000000603515004363604021373 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "StructuredStack.h" #include "common.h" @implementation StructuredStack - (void)dealloc { [self->_stack release]; [super dealloc]; } /* accessors */ - (NSMutableArray *)stack { if (self->_stack == nil) // TODO: find a proper capacity self->_stack = [[NSMutableArray alloc] initWithCapacity:16]; return _stack; } /* operations */ - (void)removeAllObjects { [[self stack] removeAllObjects]; [self first]; } - (void)push:(id)anObject { NSMutableArray *stack; if (anObject == nil) return; stack = [self stack]; [stack addObject:anObject]; if (![self cursorFollowsFIFO]) return; self->start = NO; self->pos = ([stack count] - 1); } - (id)pop { NSMutableArray *stack; int count; id object; object = nil; stack = [self stack]; count = [stack count]; if (count > 0) { object = [stack objectAtIndex:--count]; [stack removeLastObject]; } if ([self cursorFollowsFIFO]) { start = NO; pos = count - 1; } return object; } - (void)first { pos = 0; start = YES; } - (void)last { pos = [[self stack] count]; start = NO; } /* enumerator */ - (id)nextObject { NSMutableArray *stack; int count; stack = [self stack]; count = [stack count]; if (count == 0 || pos >= count) { return nil; } if (self->start) { self->start = NO; } else { pos++; if (pos >= count) return nil; } return [stack objectAtIndex:pos]; } - (id)currentObject { NSMutableArray *stack; int count; stack = [self stack]; count = [stack count]; if (count == 0 || pos >= count) return nil; self->start = NO; return [[self stack] objectAtIndex:pos]; } - (id)prevObject { NSMutableArray *stack; id result; stack = [self stack]; result = ((start || pos == 0) && [stack count]) ? nil : [stack objectAtIndex:--pos]; return result; } - (void)setCursorFollowsFIFO:(BOOL)aValue { self->cursorFIFO = aValue; } - (BOOL)cursorFollowsFIFO { return self->cursorFIFO; } - (id)objectRelativeToCursorAtIndex:(int)anIndex { NSMutableArray *stack; int i, count; stack = [self stack]; count = [stack count]; i = pos + anIndex; if (count == 0 || i < 0 || i >= count) return nil; return [[self stack] objectAtIndex:i]; } @end /* StructuredStack */ SOPE/sope-xml/STXSaxDriver/ExtraSTX/StructuredLine.m0000644000000000000000000000477215004363604021223 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "StructuredLine.h" #include "common.h" @implementation StructuredLine - (id)initWithString:(NSString *)aString level:(int)aLevel { if ((self = [super init])) { [self setText:aString]; level = aLevel; } return self; } - (void)dealloc { [self->_text release]; [self->_originalText release]; [super dealloc]; } /* accessors */ - (NSString *)text { NSMutableString *result; NSArray *components; int i, count; if (self->_text) return self->_text; result = [NSMutableString stringWithCapacity:16]; components = [_originalText componentsSeparatedByString:@"\n"]; count = [components count]; for (i = 0; i < count; i++) { NSString *s; if (i > 0) [result appendString:@" "]; s = [components objectAtIndex:i]; s = [s stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]]; [result appendString:s]; } self->_text = [result copy]; return self->_text; } - (NSString *)originalText { return self->_originalText; } - (void)setText:(NSString *)aString { BOOL running = YES; int i, length; NSString *ptr; numberOfSpaces = 0; length = [aString length]; for (i = 0; i < length; i++) { switch (([aString characterAtIndex:i])) { case ' ': case 0x09: break; default: running = NO; break; } if (!running) break; } if (running) return; numberOfSpaces = i; ptr = _originalText; self->_originalText = [aString retain]; [ptr release]; [self->_text release]; self->_text = nil; } - (void)setLevel:(int)aLevel { level = aLevel; } - (int)level { return level; } - (int)numberOfSpacesAtBeginning { return numberOfSpaces; } @end /* StructuredLine */ SOPE/sope-xml/STXSaxDriver/ExtraSTX/StructuredText.h0000644000000000000000000000454115004363604021245 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __StructuredText_H__ #define __StructuredText_H__ #import #include "StructuredTextDocument.h" @class NSString, NSMutableString; @class StructuredLine, StructuredStack; @class StructuredTextHeader, StructuredTextParagraph, StructuredTextList; @class StructuredTextListItem, StructuredTextLiteralBlock; #define StructuredTextParserLine_Header 0 #define StructuredTextParserLine_Paragraph 1 #define StructuredTextParserLine_List 2 #define StructuredTextParserLine_LiteralBlock 3 @interface StructuredText : NSObject { NSString *_text; StructuredTextDocument *_document; StructuredStack *_stack; StructuredStack *_paragraphs; #if DISABLE_BUG_FIX int currentHeaderLevel; #endif } + (StructuredTextDocument *)parseText:(NSString *)_txt; - (id)initWithString:(NSString *)_str; /* accessors */ - (NSString *)text; - (StructuredTextDocument *)document; - (StructuredStack *)stack; - (StructuredStack *)paragraphs; /* parsing */ - (void)parse; - (NSUInteger)lineType:(StructuredLine *)_line; - (void)separateIntoBlocks; - (void)adjustLineLevels; - (void)buildDocument; - (BOOL)checkForHeader:(StructuredLine *)_line; - (BOOL)checkForListItem:(StructuredLine *)_line; - (BOOL)checkForPreformattedStatement:(StructuredLine *)_line; - (BOOL)checkForPreformattedBlock:(StructuredLine *)_line; - (StructuredTextHeader *)buildHeader; - (StructuredTextParagraph *)buildParagraph; - (StructuredTextLiteralBlock *)buildLiteralBlock; - (StructuredTextList *)buildList; - (NSUInteger)listItemTypology:(StructuredLine *)_line; @end #endif /* __StructuredText_H__ */ SOPE/sope-xml/STXSaxDriver/ExtraSTX/COPYRIGHT0000644000000000000000000000203515004363604017352 0ustar rootroot Structured Text Code Copyright (C) 2004 eXtrapola Srl Contact: marco.barulli@extrapola.com Statement by Extrapola SRL (Marco Barulli) ========================================== I'm glad to confirm that eXtrapola Srl, as the copyright holder on the StructuredText code sent to the OpenGroupware.org project and initially written by Mirko Viviani and Giulio Cesare Solaroli, hereby states that the code is licensed and can be used under the terms of the Lesser General Public License. Statement by Mirko Viviani ========================== Mirko Viviani, as the original author of the StructuredText framework sent to the OpenGroupware.org project, hereby states that the code is licensed and can be used under the terms of the Lesser General Public License. Statement by Giulio Cesare Solaroli =================================== I, as one of the original author on the StructuredText code sent to the OpenGroupware.org project, hereby states that the code is licensed and can be used under the terms of the Lesser General Public License. SOPE/sope-xml/STXSaxDriver/ExtraSTX/StructuredText.m0000644000000000000000000003054015004363604021250 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "StructuredText.h" #include "StructuredLine.h" #include "StructuredStack.h" #include "StructuredTextHeader.h" #include "StructuredTextParagraph.h" #include "StructuredTextList.h" #include "StructuredTextListItem.h" #include "StructuredTextLiteralBlock.h" #include "common.h" #include @implementation StructuredText - (id)initWithString:(NSString *)_str { if ((self = [super init])) { self->_text = [_str copy]; } return self; } - (void)dealloc { [self->_text release]; [self->_document release]; [self->_stack release]; [self->_paragraphs release]; [super dealloc]; } /* factory */ + (StructuredTextDocument *)parseText:(NSString *)aText { StructuredText *text; // TODO: shouldn't we release the object? text = [[StructuredText alloc] initWithString:aText]; return [text document]; } /* accessors */ - (NSString *)text { return _text; } - (StructuredTextDocument *)document { if (self->_document) return self->_document; self->_document = [[StructuredTextDocument alloc] init]; [self parse]; return _document; } - (StructuredStack *)stack { if (self->_stack == nil) self->_stack = [[StructuredStack alloc] init]; return self->_stack; } - (StructuredStack *)paragraphs { if (self->_paragraphs == nil) self->_paragraphs = [[StructuredStack alloc] init]; return self->_paragraphs; } - (void)parse { #if DISABLE_BUG_FIX currentHeaderLevel = 1; #endif [self separateIntoBlocks]; [self adjustLineLevels]; [self buildDocument]; } - (void)separateIntoBlocks { NSArray *lines; StructuredStack *pars; NSString *text, *currentLine, *trimmedLine; NSMutableString *buf; NSCharacterSet *set; NSUInteger i, count; set = [NSCharacterSet characterSetWithCharactersInString:@"\r"]; buf = [NSMutableString stringWithCapacity:256]; text = [self text]; pars = [self paragraphs]; lines = [text componentsSeparatedByString:@"\n"]; count = [lines count]; for (i = 0; i < count; i++) { currentLine = [lines objectAtIndex:i]; currentLine = [currentLine stringByTrimmingCharactersInSet:set]; trimmedLine = [currentLine stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]]; if ([trimmedLine length] > 0) { if ([buf length] > 0) [buf appendString:@"\n"]; [buf appendString:currentLine]; } else { if ([buf length] > 0) { StructuredLine *sl; sl = [[StructuredLine alloc] initWithString:[NSString stringWithString:buf] level:0];; [pars push:sl]; // TODO: shouldn't we release the object? } [buf setString:@""]; } } if ([buf length] > 0) { StructuredLine *sl; sl = [[StructuredLine alloc] initWithString:[NSString stringWithString:buf] level:0]; [pars push:sl]; // TODO: shouldn't we release the object? } } - (void)adjustLineLevels { StructuredStack *paragraphs; StructuredStack *stack; StructuredLine *line; int level = 0; stack = [self stack]; [stack setCursorFollowsFIFO:YES]; paragraphs = [self paragraphs]; [paragraphs first]; while ((line = [paragraphs nextObject])) { StructuredLine *tmpLine; while ((tmpLine = [stack currentObject])) { if ([line numberOfSpacesAtBeginning]>[tmpLine numberOfSpacesAtBeginning]) break; [stack pop]; level--; } if (!tmpLine) level = 0; switch ([self lineType:line]) { case StructuredTextParserLine_Header: [line setLevel:level++]; [stack push:line]; break; case StructuredTextParserLine_Paragraph: case StructuredTextParserLine_LiteralBlock: [line setLevel:level]; break; case StructuredTextParserLine_List: { [line setLevel:level++]; [stack push:line]; break; } } } [stack removeAllObjects]; } - (void)buildDocument { StructuredTextDocument *document; StructuredStack *paragraphs; StructuredStack *stack, *objectStack; StructuredLine *line; document = [self document]; stack = [self stack]; [stack setCursorFollowsFIFO:YES]; paragraphs = [self paragraphs]; [paragraphs first]; objectStack = [[StructuredStack alloc] init]; [objectStack setCursorFollowsFIFO:YES]; while ((line = [paragraphs currentObject])) { StructuredLine *tmpLine; id object = nil; switch ([self lineType:line]) { case StructuredTextParserLine_Header: object = [self buildHeader]; #if DISABLE_BUG_FIX currentHeaderLevel++; #endif break; case StructuredTextParserLine_Paragraph: object = [self buildParagraph]; //NSLog(@"par %@", [object text]); break; case StructuredTextParserLine_LiteralBlock: object = [self buildLiteralBlock]; break; case StructuredTextParserLine_List: object = [self buildList]; break; } if (object != nil) { StructuredTextBodyElement *body; body = [objectStack currentObject]; if (body && [body respondsToSelector:@selector(addElement:)]) [body addElement:object]; else [document addBodyElement:object]; if ([object isKindOfClass:[StructuredTextHeader class]] /* || [object isKindOfClass:[StructuredTextList class]] */) { while ((tmpLine = [stack currentObject])) { if ([line level] > [tmpLine level]) break; [stack pop]; [objectStack pop]; #if DISABLE_BUG_FIX { id currentObject = [objectStack pop]; if ([currentObject isKindOfClass:[StructuredTextHeader class]]) currentHeaderLevel--; } #endif } [objectStack push:object]; [stack push:line]; } } [paragraphs nextObject]; } [objectStack release]; } - (NSUInteger)lineType:(StructuredLine *)aLine { if ([self checkForListItem:aLine]) return StructuredTextParserLine_List; if ([self checkForHeader:aLine]) { return [self checkForPreformattedStatement:aLine] ? StructuredTextParserLine_Paragraph : StructuredTextParserLine_Header; } if ([self checkForPreformattedBlock:aLine]) return StructuredTextParserLine_LiteralBlock; return StructuredTextParserLine_Paragraph; } - (BOOL)checkForHeader:(StructuredLine *)aLine { StructuredLine *nextLine; nextLine = [[self paragraphs] objectRelativeToCursorAtIndex:1]; if (nextLine == nil) return NO; if ([nextLine numberOfSpacesAtBeginning]>[aLine numberOfSpacesAtBeginning]) return YES; return NO; } - (BOOL)checkForListItem:(StructuredLine *)aLine { return ([self listItemTypology:aLine] == NSNotFound) ? NO : YES; } - (BOOL)checkForPreformattedStatement:(StructuredLine *)aLine { NSString *s; if (aLine == nil) return NO; s = [aLine text]; s = [s stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]]; return [s hasSuffix:@"::"]; } - (BOOL)checkForPreformattedBlock:(StructuredLine *)aLine { id stmt; stmt = [[self paragraphs] objectRelativeToCursorAtIndex:-1]; return [self checkForPreformattedStatement:stmt] ? YES : NO; } - (StructuredTextHeader *)buildHeader { StructuredTextHeader *result; StructuredLine *line; line = [[self paragraphs] currentObject]; #if DISABLE_BUG_FIX result = [[StructuredTextHeader alloc] initWithString:[line text] level:currentHeaderLevel]; #else result = [[StructuredTextHeader alloc] initWithString:[line text] level:([line level] + 1)]; #endif return [result autorelease]; } - (StructuredTextParagraph *)buildParagraph { StructuredTextParagraph *result; StructuredLine *line; NSString *text; line = [[self paragraphs] currentObject]; text = [line text]; if ([[text stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]] hasSuffix:@"::"]) { NSUInteger length; length = [text length]; text = [text substringToIndex:length - 2]; } result = [[StructuredTextParagraph alloc] initWithString:text]; return [result autorelease]; } - (StructuredTextLiteralBlock *)buildLiteralBlock { StructuredTextLiteralBlock *result; StructuredLine *line; NSString *s; line = [[self paragraphs] currentObject]; s = [[line originalText] stringByAppendingString:@"\n"]; result = [[StructuredTextLiteralBlock alloc] initWithString:s]; return [result autorelease]; } - (StructuredTextList *)buildList { StructuredTextList *result; StructuredLine *line, *prevLine = nil; StructuredTextListItem *item = nil; StructuredStack *paragraphs; NSUInteger type; result = nil; paragraphs = [self paragraphs]; line = [paragraphs currentObject]; while (line != nil) { NSString *text, *title; text = [line text]; title = nil; type = [self listItemTypology:line]; if (type == NSNotFound) { [paragraphs prevObject]; break; } if (!result) result = [[StructuredTextList alloc] initWithTypology:type]; else if ([result typology] != type) break; if (prevLine) { if ([line level] > [prevLine level]) { if (item) { [item addElement:[self buildList]]; line = [paragraphs currentObject]; continue; } } else if ([line level] < [prevLine level]) { return result; } } switch (type) { case StructuredTextList_BULLET: text = [text substringFromIndex:2]; break; case StructuredTextList_DEFINITION: { NSArray *components; NSUInteger i, count; components = [text componentsSeparatedByString:@" -- "]; count = [components count]; title = [components objectAtIndex:0]; if (count > 2) { NSMutableString *buffer; buffer = [NSMutableString stringWithCapacity:(count * 8)]; for (i = 1; i < count; i++) { if (i > 1) { [buffer appendString:@" -- "]; } [buffer appendString:[components objectAtIndex:i]]; } text = buffer; } else text = [components objectAtIndex:1]; break; } case StructuredTextList_ENUMERATED: { NSRange range; range = [text rangeOfString:@" "]; if (range.length > 0) text = [text substringFromIndex:range.location + 1]; break; } } item = [[StructuredTextListItem alloc] initWithTitle:title text:text]; [result addElement:item]; [item release]; prevLine = line; line = [paragraphs nextObject]; } return [result autorelease]; } - (NSUInteger)listItemTypology:(StructuredLine *)aLine { NSString *text; NSUInteger type = NSNotFound; NSUInteger i, h, length; NSRange range; text = [aLine text]; if ([text hasPrefix:@"* "]) return StructuredTextList_BULLET; range = [text rangeOfString:@" -- "]; if (range.length > 0 && range.length == 4) return StructuredTextList_DEFINITION; for (i = h = 0, length = [text length]; i < length; i++) { if (!isdigit([text characterAtIndex:i])) break; h++; } if (h > 0) type = StructuredTextList_ENUMERATED; return type; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if (self->_text) [ms appendFormat:@" text-len=%"PRIuPTR, [self->_text length]]; if (self->_document) [ms appendFormat:@" document=%@", self->_document]; #if DISABLE_BUG_FIX [ms appendFormat:@" headerlevel=%i", self->currentHeaderLevel]; #endif [ms appendString:@">"]; return ms; } @end /* StructuredText */ SOPE/sope-xml/STXSaxDriver/ExtraSTX/StructuredLine.h0000644000000000000000000000226515004363604021211 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import @class NSString; @interface StructuredLine : NSObject { NSString *_text; NSString *_originalText; int numberOfSpaces; int level; } - (id)initWithString:(NSString *)aString level:(int)level; /* accessors */ - (NSString *)text; - (NSString *)originalText; - (void)setText:(NSString *)aString; - (int)level; - (void)setLevel:(int)aLevel; - (int)numberOfSpacesAtBeginning; @end SOPE/sope-xml/STXSaxDriver/fhs.make0000644000000000000000000000137415004363604016021 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib64/ else FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib/ endif FHS_SAX_DIR=$(FHS_LIB_DIR)sope-$(SOPE_MAJOR_VERSION).$(SOPE_MINOR_VERSION)/saxdrivers/ fhs-sax-dirs :: $(MKDIRS) $(FHS_SAX_DIR) move-bundles-to-fhs :: fhs-sax-dirs @echo "moving bundles $(BUNDLE_INSTALL_DIR) to $(FHS_SAX_DIR) .." for i in $(BUNDLE_NAME); do \ j="$(FHS_SAX_DIR)/$${i}$(BUNDLE_EXTENSION)"; \ if test -d $$j; then rm -r $$j; fi; \ mv "$(BUNDLE_INSTALL_DIR)/$${i}$(BUNDLE_EXTENSION)" $$j; \ done move-to-fhs :: move-bundles-to-fhs after-install :: move-to-fhs endif SOPE/sope-xml/STXSaxDriver/StructuredTextBodyElement+SAX.m0000644000000000000000000000406415004363604022347 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "StructuredTextBodyElement.h" #include "StructuredTextParagraph.h" #include "StructuredTextList.h" #include "StructuredTextListItem.h" #include "StructuredTextLiteralBlock.h" #include "StructuredTextHeader.h" #include "STXSaxDriver.h" #include "common.h" @implementation StructuredTextBodyElement(SAX) @end /* StructuredTextBodyElement(SAX) */ @implementation StructuredTextParagraph(SAX) - (void)produceSaxEventsOnSTXSaxDriver:(STXSaxDriver *)_sax { [_sax produceSaxEventsForParagraph:self]; } @end /* StructuredTextParagraph(SAX) */ @implementation StructuredTextList(SAX) - (void)produceSaxEventsOnSTXSaxDriver:(STXSaxDriver *)_sax { [_sax produceSaxEventsForList:self]; } @end /* StructuredTextList(SAX) */ @implementation StructuredTextListItem(SAX) - (void)produceSaxEventsOnSTXSaxDriver:(STXSaxDriver *)_sax { [_sax produceSaxEventsForListItem:self]; } @end /* StructuredTextListItem(SAX) */ @implementation StructuredTextLiteralBlock(SAX) - (void)produceSaxEventsOnSTXSaxDriver:(STXSaxDriver *)_sax { [_sax produceSaxEventsForLiteralBlock:self]; } @end /* StructuredTextLiteralBlock(SAX) */ @implementation StructuredTextHeader(SAX) - (void)produceSaxEventsOnSTXSaxDriver:(STXSaxDriver *)_sax { [_sax produceSaxEventsForHeader:self]; } @end /* StructuredTextHeader(SAX) */ SOPE/sope-xml/STXSaxDriver/COPYING.LIB0000644000000000000000000006130315004363604016040 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-xml/STXSaxDriver/README0000644000000000000000000000561015004363604015257 0ustar rootrootNote: this is the initial release, it should contain some bugs ;-) STXSaxDriver ============ This project contains a skyrix-xml/SaxObjC SAX driver bundle which can process so called "structured text" files, or in short "STX". The parsing events are reported as XHTML tags. Example: ---snip--- * item A * item B ---snap--- will be reported as SAX events similar to such an HTML file: ---snip---
    • item A
    • item B
    ---snap--- The basis for this driver bundle, the StructuredText framework, was initially written by Mirko Viviani and Giulio Cesare Solaroli and sponsored by eXtrapola Srl. Note that the "original" StructuredText framework is much more capable and generic than what this SAX driver provides. On the pro side, your applications do not need to care about the actual tag format if you use SaxObjC. Your applications can use either, XHTML, HTML, PYX or STX files using the available SaxObjC drivers without any additional work. Supported MIME Types ==================== Not sure what the correct MIME type for structured text is supposed to be, for now we register this driver for the "text/structured" MIME type. How to try ========== Just use the saxxml or domxml tools which are part of skyrix-xml, eg: saxxml -XMLReader STXSaxDriver data/hhtest1.stx This will print the XHTML representation of the STX file on stdout. STX Functionality which is implemented ====================================== Guilio writes: ---snip--- Anyway, we used this document as "reference": http://plone.org/documentation/howto/FrontPage/UsingStructuredText of the construct defined there, we have skipped just the table construct. But we have added a few thinks: - it is possible to use quotes in link url (es: if you have "Link":http://www.url.com, the comma will end up into the link; to avoid this, we can parse a string like that: "Link":'http://www.url.com', and the comma will be left out of the link). - link target: they are not a first class citizen (specially in XHTML), but sometime they are very usefull. To define a target, you can add it after a link: "Link":'http://www.url.com'::'target'. Also the target can be quoted in order to avoid problems with punctuation. - Image link: in order to create a link around an image, we have defined the following sintax: ["Alt text":http://www.url.com/image.gif]:'http://www.url.com'. Here too, quoting and target are supported. ---snap--- Defaults ======== STXDebugEnabled YES|NO STXSaxDriverDebugEnabled YES|NO Structured Text Links ===================== http://www.zope.org/Members/millejoh/structuredText http://plone.org/documentation/howto/FrontPage/UsingStructuredText Classes ======= NSObject STXSaxDriver < SaxXMLReader > NSObject StructuredLine StructuredStack StructuredText StructuredTextRenderingDelegate StructuredTextRenderingDelegate_XHTML NSString(STX) SOPE/sope-xml/STXSaxDriver/STXSaxDriver.m0000644000000000000000000003715115004363604017070 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "STXSaxDriver.h" #include "StructuredText.h" #include "StructuredTextList.h" #include "StructuredTextListItem.h" #include "StructuredTextLiteralBlock.h" #include "StructuredTextHeader.h" #include "StructuredTextParagraph.h" #include #include "common.h" static NSString *SaxDeclHandlerProperty = @"http://xml.org/sax/properties/declaration-handler"; static NSString *SaxLexicalHandlerProperty = @"http://xml.org/sax/properties/lexical-handler"; @interface NSObject(SAX) - (void)produceSaxEventsOnSTXSaxDriver:(STXSaxDriver *)_sax; @end @implementation STXSaxDriver static BOOL debugOn = NO; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; debugOn = [ud boolForKey:@"STXSaxDriverDebugEnabled"]; } - (id)init { if ((self = [super init])) { self->attrs = [[SaxAttributes alloc] init]; } return self; } - (void)dealloc { [self->context release]; [self->attrs release]; [self->lexicalHandler release]; [self->contentHandler release]; [self->errorHandler release]; [self->entityResolver release]; [super dealloc]; } /* properties */ - (void)setProperty:(NSString *)_name to:(id)_value { if ([_name isEqualToString:SaxLexicalHandlerProperty]) { [self->lexicalHandler autorelease]; self->lexicalHandler = [_value retain]; return; } if ([_name isEqualToString:SaxDeclHandlerProperty]) { return; } [SaxNotRecognizedException raise:@"PropertyException" format:@"don't know property %@", _name]; } - (id)property:(NSString *)_name { if ([_name isEqualToString:SaxLexicalHandlerProperty]) return self->lexicalHandler; if ([_name isEqualToString:SaxDeclHandlerProperty]) return nil; [SaxNotRecognizedException raise:@"PropertyException" format:@"don't know property %@", _name]; return nil; } /* features */ - (void)setFeature:(NSString *)_name to:(BOOL)_value { return; #if 0 // be tolerant [SaxNotRecognizedException raise:@"FeatureException" format:@"don't know feature %@", _name]; #endif } - (BOOL)feature:(NSString *)_name { return NO; } /* handlers */ - (void)setContentHandler:(id)_handler { [self->contentHandler autorelease]; self->contentHandler = [_handler retain]; } - (id)contentHandler { return self->contentHandler; } - (void)setLexicalHandler:(id)_handler { [self->lexicalHandler autorelease]; self->lexicalHandler = [_handler retain]; } - (id)lexicalHandler { return self->lexicalHandler; } - (void)setDTDHandler:(id)_handler { } - (id)dtdHandler { return nil; } - (void)setErrorHandler:(id)_handler { [self->errorHandler autorelease]; self->errorHandler = [_handler retain]; } - (id)errorHandler { return self->errorHandler; } - (void)setEntityResolver:(id)_handler { [self->entityResolver autorelease]; self->entityResolver = [_handler retain]; } - (id)entityResolver { return self->entityResolver; } /* support */ - (void)_beginTag:(NSString *)_tag { [self->contentHandler startElement:_tag namespace:XMLNS_XHTML rawName:_tag attributes:nil /* id */]; } - (void)_endTag:(NSString *)_tag { [self->contentHandler endElement:_tag namespace:XMLNS_XHTML rawName:_tag]; } - (void)_characters:(NSString *)_chars { unichar *buf; NSUInteger len; if ((len = [_chars length]) == 0) // TODO: may or may not be correct return; buf = calloc(len + 4, sizeof(unichar)); // TODO: cache/reuse buffer [_chars getCharacters:buf]; [self->contentHandler characters:buf length:len]; if (buf) free(buf); } /* STX delegate */ - (void)appendText:(NSString *)_txt inContext:(NSDictionary *)_ctx { [self _characters:_txt]; } - (void)beginItalicsInContext:(NSDictionary *)_ctx { [self _beginTag:@"em"]; } - (void)endItalicsInContext:(NSDictionary *)_ctx { [self _endTag:@"em"]; } - (void)beginUnderlineInContext:(NSDictionary *)_ctx { [self _beginTag:@"u"]; } - (void)endUnderlineInContext:(NSDictionary *)_ctx { [self _endTag:@"u"]; } - (void)beginBoldInContext:(NSDictionary *)_ctx { [self _beginTag:@"strong"]; } - (void)endBoldInContext:(NSDictionary *)_ctx { [self _endTag:@"strong"]; } - (void)beginPreformattedInContext:(NSDictionary *)_ctx { [self _beginTag:@"pre"]; } - (void)endPreformattedInContext:(NSDictionary *)_ctx { [self _endTag:@"pre"]; } - (void)beginParagraphInContext:(NSDictionary *)_ctx { [self _beginTag:@"p"]; } - (void)endParagraphInContext:(NSDictionary *)_ctx { [self _endTag:@"p"]; } - (NSString *)insertLink:(NSString *)_txt withUrl:(NSString *)_url target:(NSString *)_target inContext:(NSDictionary *)_ctx { // TODO: need to generate SaxAttributes here [self->attrs clear]; [self->attrs addAttribute:@"href" uri:XMLNS_XHTML rawName:@"href" type:@"CDATA" value:_url]; if ([_target length] > 0) { [self->attrs addAttribute:@"target" uri:XMLNS_XHTML rawName:@"target" type:@"CDATA" value:_target]; } [self->contentHandler startElement:@"a" namespace:XMLNS_XHTML rawName:@"a" attributes:self->attrs]; [self _characters:_txt]; [self _endTag:@"a"]; // if we return nil, the content will be generated as if it didn't match // if we return an empty string, a zero-length string is reported return @""; } - (NSString *)insertEmail:(NSString *)_txt withAddress:(NSString *)_link inContext:(NSDictionary *)_ctx { // TODO: check&implement #if 0 [NSString stringWithFormat:@"%@", anAddress, _txt]; #endif return _txt; } - (NSString *)insertImage:(NSString *)_title withUrl:(NSString *)_src inContext:(NSDictionary *)_ctx { // TODO: check&implement #if 0 [NSString stringWithFormat:@"", anUrl, _txt]; #endif return _title; } - (NSString *)insertExtrapolaLink:(NSString *)_txt parameters:(NSDictionary *)_paras withTarget:(NSString *)_target inContext:(NSDictionary *)_ctx { // TODO: do we want to support that? if (debugOn) NSLog(@"insert extrapola link: %@", _txt); [self _characters:_txt]; return nil; } - (NSString *)insertDynamicKey:(NSString *)_k inContext:(NSDictionary *)_ctx { // TODO: what to do here? return [_ctx objectForKey:_k]; } - (NSString *)insertPreprocessedTextForKey:(NSString *)_k inContext:(NSDictionary *)_ctx { // TODO: what to do here? return [_ctx objectForKey:_k]; } /* generating element events */ - (void)produceSaxEventsForParagraph:(StructuredTextParagraph *)_p { NSString *s; if (debugOn) NSLog(@" produce SAX events for paragraph: %@", _p); s = [_p textParsedWithDelegate:(id)self inContext:self->context]; if ([s length] > 0) [self _characters:s]; } - (void)produceSaxEventsForHeader:(StructuredTextHeader *)_h { NSString *tagName, *s; if (debugOn) NSLog(@" produce SAX events for header: %@", _h); switch ([_h level]) { case 1: tagName = @"h1"; break; case 2: tagName = @"h2"; break; case 3: tagName = @"h3"; break; case 4: tagName = @"h4"; break; case 5: tagName = @"h5"; break; case 6: tagName = @"h6"; break; default: tagName = [@"h" stringByAppendingFormat:@"%d", [_h level]]; break; } [self _beginTag:tagName]; if ((s = [_h textParsedWithDelegate:(id)self inContext:self->context])) [self _characters:s]; [self _endTag:tagName]; [self produceSaxEventsForElements:[_h elements]]; } - (void)produceSaxEventsForList:(StructuredTextList *)_list { NSString *tagName; if (debugOn) NSLog(@" produce SAX events for list: %@", _list); switch ([_list typology]) { case StructuredTextList_BULLET: tagName = @"ul"; break; case StructuredTextList_ENUMERATED: tagName = @"ol"; break; case StructuredTextList_DEFINITION: tagName = @"dl"; break; default: tagName = nil; } [self _beginTag:tagName]; [self produceSaxEventsForElements:[_list elements]]; [self _endTag:tagName]; } - (void)produceSaxEventsForListItem:(StructuredTextListItem *)_item { NSString *s; int typology; if (debugOn) NSLog(@" produce SAX events for item: %@", _item); typology = [[_item list] typology]; if (typology == StructuredTextList_DEFINITION) { [self _beginTag:@"dt"]; if ((s = [_item titleParsedWithDelegate:(id)self inContext:self->context])) [self _characters:s]; [self _endTag:@"dt"]; } switch (typology) { case StructuredTextList_BULLET: [self _beginTag:@"li"]; break; case StructuredTextList_ENUMERATED: [self _beginTag:@"li"]; break; case StructuredTextList_DEFINITION: [self _beginTag:@"dd"]; break; } if ((s = [_item textParsedWithDelegate:(id)self inContext:self->context])) { if (debugOn) NSLog(@" chars: %"PRIuPTR, [s length]); [self _characters:s]; } if (debugOn) NSLog(@" elems: %"PRIuPTR, [[_item elements] count]); [self produceSaxEventsForElements:[_item elements]]; switch (typology) { case StructuredTextList_BULLET: [self _endTag:@"li"]; break; case StructuredTextList_ENUMERATED: [self _endTag:@"li"]; break; case StructuredTextList_DEFINITION: [self _endTag:@"dd"]; break; } } - (void)produceSaxEventsForLiteralBlock:(StructuredTextLiteralBlock *)_block { [self _beginTag:@"pre"]; [self _characters:[_block text]]; [self _endTag:@"pre"]; } /* generating events */ - (void)produceSaxEventsForElement:(id)_element { if (debugOn) NSLog(@" produce SAX events for element: %@", _element); if (_element == nil) return; if ([_element respondsToSelector:@selector(produceSaxEventsOnSTXSaxDriver:)]) [_element produceSaxEventsOnSTXSaxDriver:self]; else { NSLog(@"Note: cannot handle STX element: %@", _element); } } - (void)produceSaxEventsForElements:(NSArray *)_elems { unsigned int i, c; if (debugOn) NSLog(@" produce SAX events for elements: %"PRIuPTR, [_elems count]); for (i = 0, c = [_elems count]; i < c; i++) { id currentObject; currentObject = [_elems objectAtIndex:i]; if (debugOn) NSLog(@" element[%d]/%d: %@", i, c, currentObject); [self produceSaxEventsForElement:currentObject]; } } - (void)produceSaxEventsForStructuredTextDocument:(StructuredTextDocument *)_d{ if (debugOn) NSLog(@" produce SAX events for document: %@", _d); [self produceSaxEventsForElements:[_d bodyElements]]; } - (void)produceSaxEventsForStructuredText:(StructuredText *)_stx systemId:(NSString *)_sysId { if (debugOn) NSLog(@"produce SAX events for: %@", _stx); [self->contentHandler startDocument]; [self produceSaxEventsForStructuredTextDocument:[_stx document]]; [self->contentHandler endDocument]; } /* parsing */ - (void)parseFromString:(NSString *)_str systemId:(NSString *)_sysId { StructuredText *stx; if (_sysId == nil) _sysId = @""; stx = [[[StructuredText alloc] initWithString:_str] autorelease]; if (debugOn) NSLog(@"%s: %@: %@", __PRETTY_FUNCTION__, _sysId, stx); [self produceSaxEventsForStructuredText:stx systemId:_sysId]; } - (void)parseFromData:(NSData *)_data systemId:(NSString *)_sysId { NSString *s; if (_sysId == nil) _sysId = @""; s = [[NSString alloc] initWithData:_data encoding:NSISOLatin1StringEncoding]; s = [s autorelease]; [self parseFromString:s systemId:_sysId]; } - (void)parseFromNSURL:(NSURL *)_url systemId:(NSString *)_sysId { NSData *data; if (_sysId == nil) _sysId = [_url absoluteString]; if ((data = [_url resourceDataUsingCache:NO]) == nil) { SaxParseException *e; NSDictionary *ui; ui = [[NSDictionary alloc] initWithObjectsAndKeys: _url ? _url : (NSURL *)@"", @"url", _sysId ? _sysId : (NSString *)@"", @"publicId", self, @"parser", nil]; e = (id)[SaxParseException exceptionWithName:@"SaxIOException" reason:@"could not retrieve URL content" userInfo:ui]; [ui release]; ui = nil; [self->errorHandler fatalError:e]; return; } [self parseFromData:data systemId:_sysId]; } - (void)parseFromSource:(id)_source systemId:(NSString *)_sysId { if (_source == nil) { /* no source ??? */ SaxParseException *e; NSDictionary *ui; ui = [[NSDictionary alloc] initWithObjectsAndKeys: _sysId ? _sysId : (NSString *)@"", @"publicId", self, @"parser", nil]; e = (id)[SaxParseException exceptionWithName:@"SaxIOException" reason:@"missing source for parsing!" userInfo:ui]; [ui release]; ui = nil; [self->errorHandler fatalError:e]; return; } if ([_source isKindOfClass:[NSString class]]) { [self parseFromString:_source systemId:_sysId]; return; } if ([_source isKindOfClass:[NSURL class]]) { [self parseFromNSURL:_source systemId:_sysId]; return; } if ([_source isKindOfClass:[NSData class]]) { [self parseFromData:_source systemId:_sysId]; return; } { SaxParseException *e; NSDictionary *ui; ui = [[NSDictionary alloc] initWithObjectsAndKeys: _source ? _source : (id)@"", @"source", _sysId ? _sysId : (NSString *)@"", @"publicId", self, @"parser", nil]; e = (id)[SaxParseException exceptionWithName:@"SaxIOException" reason:@"can not handle data-source" userInfo:ui]; [ui release]; ui = nil; [self->errorHandler fatalError:e]; return; } } - (void)parseFromSource:(id)_source { [self parseFromSource:_source systemId:nil]; } - (void)parseFromSystemId:(NSString *)_sysId { NSURL *url; if ([_sysId length] == 0) { SaxParseException *e; NSDictionary *ui; ui = [NSDictionary dictionaryWithObjectsAndKeys:self, @"parser", nil]; e = (id)[SaxParseException exceptionWithName:@"SaxIOException" reason:@"missing system-id for parsing!" userInfo:ui]; [self->errorHandler fatalError:e]; return; } if ([_sysId rangeOfString:@"://"].length == 0) { /* not a URL */ if (![_sysId isAbsolutePath]) _sysId = [[NSFileManager defaultManager] currentDirectoryPath]; url = [[[NSURL alloc] initFileURLWithPath:_sysId] autorelease]; } else url = [NSURL URLWithString:_sysId]; [self parseFromSource:url systemId:_sysId]; } @end /* STXSaxDriver */ SOPE/sope-xml/STXSaxDriver/GNUmakefile.postamble0000644000000000000000000000037015004363604020434 0ustar rootroot# compilation settings ifneq ($(GNUSTEP_BUILD_DIR),) after-all :: @(cp bundle-info.plist \ $(GNUSTEP_BUILD_DIR)/$(BUNDLE_NAME)$(BUNDLE_EXTENSION)) else after-all :: @(cd $(BUNDLE_NAME)$(BUNDLE_EXTENSION);\ cp ../bundle-info.plist .) endif SOPE/sope-xml/STXSaxDriver/Version0000644000000000000000000000004515004363604015744 0ustar rootroot# Version file SUBMINOR_VERSION:=15 SOPE/sope-xml/STXSaxDriver/data/0000755000000000000000000000000015004363604015306 5ustar rootrootSOPE/sope-xml/STXSaxDriver/data/znektest1.stx0000644000000000000000000000014115004363604017772 0ustar rootrootThe *test 3* URL should appear here "test 3":http://www.example.org/test3 and not anywhere else. SOPE/sope-xml/STXSaxDriver/data/hhtest1-expect.pyx0000644000000000000000000000050215004363604020713 0ustar rootroot(p -jasdhf sdajfh asdfh asdfh ajasdhfj hasdjkfh jkasdf asdf jasd fhjasdhf jkasdhf )p (em -asdklf )em (strong -klasdf )strong (u -asf )u (p -asdkfj kl;asdfk asdjfjasdhf asdfkj daskjf asdkj flkasdf asdfkj )p (ul (li (a Ahref http://www.skyrix.de/ -SKYRiX )a )li (li (a Ahref http://www.opengroupware.org/ -OGo )a )li )ul SOPE/sope-xml/STXSaxDriver/data/hhtest3.stx0000644000000000000000000000003415004363604017425 0ustar rootroot1 sdkfj 2 ksdafj 3 asldfk SOPE/sope-xml/STXSaxDriver/data/hhtest3-expect.pyx0000644000000000000000000000006715004363604020723 0ustar rootroot(ol (li -sdkfj )li (li -ksdafj )li (li -asldfk )li )ol SOPE/sope-xml/STXSaxDriver/data/hhtest2.stx0000644000000000000000000000041215004363604017424 0ustar rootrootjasdhf sdajfh asdfh asdfh ajasdhfj hasdjkfh jkasdf asdf jasd fhjasdhf jkasdhf asdkfj asdf asdf asdkfj kl;asdfk asdjfjasdhf asdfkj daskjf asdkj flkasdf asdfkj *asdklf* **klasdf** _asf_ * "SKYRiX":http://www.skyrix.de/ * "OGo":http://www.opengroupware.org/ SOPE/sope-xml/STXSaxDriver/data/hhtest1.stx0000644000000000000000000000036315004363604017430 0ustar rootrootjasdhf sdajfh asdfh asdfh ajasdhfj hasdjkfh jkasdf asdf jasd fhjasdhf jkasdhf asdkfj kl;asdfk asdjfjasdhf asdfkj daskjf asdkj flkasdf asdfkj *asdklf* **klasdf** _asf_ * "SKYRiX":http://www.skyrix.de/ * "OGo":http://www.opengroupware.org/ SOPE/sope-xml/STXSaxDriver/data/extra_test2-expect.pyx0000644000000000000000000000270715004363604021610 0ustar rootroot(p -Municipia aggrega 12099 lettori in diverse comunita che accedono alla versione completa del magazine e ad utili servizi di personalizzazione. )p -Leggi le Faq! (p -Vuoi saperne di piu? Leggi le Faq!":{url = article; action= ciao;} )p (p -Richiedi l'accesso a una comunita di Municipia )p (ul (li -COM-P.A. -COM-P.A.":{url = article; action= ciao;} )li (li -Comune di Senigallia -Comune di Senigallia":{url = article; action= ciao;} )li (li -Comuneinlinea -Comuneinlinea":{url = article; action= ciao;} )li (li -Comunicatori Pubblici -Comunicatori Pubblici":{url = article; action= ciao;} )li (li -Findonline -Findonline":{url = article; action= ciao;} )li (li -Provincia Regionale di Messina -Provincia Regionale di Messina":{url = article; action= ciao;} )li (li -Provincia di Brescia -Provincia di Brescia":{url = article; action= ciao;} )li (li -Provincia di Milano -Provincia di Milano":{url = article; action= ciao;} )li (li -Provincia di Modena -Provincia di Modena":{url = article; action= ciao;} )li (li -Provincia di Napoli -Provincia di Napoli":{url = article; action= ciao;} )li (li -Provincia di Padova -Provincia di Padova":{url = article; action= ciao;} )li (li -Provincia di Pesaro-Urbino -Provincia di Pesaro-Urbino":{url = article; action= ciao;} )li (li -Provincia Autonoma di Trento -Provincia Autonoma di Trento":{url = article; action= ciao;} )li )ul -segnala una nuova comunita! (p -Oppure segnala una nuova comunita!":{url = article; action= ciao;} )p SOPE/sope-xml/STXSaxDriver/data/extra_test1-expect.pyx0000644000000000000000000000004015004363604021573 0ustar rootroot(ul (li - a )li (li - b )li )ul SOPE/sope-xml/STXSaxDriver/data/extra_test1.stx0000644000000000000000000000001415004363604020304 0ustar rootroot* a * bSOPE/sope-xml/STXSaxDriver/data/extra_test2.stx0000644000000000000000000000211115004363604020305 0ustar rootrootMunicipia aggrega 12099 lettori in diverse comunita che accedono alla versione completa del magazine e ad utili servizi di personalizzazione. Vuoi saperne di piu? "Leggi le Faq!":{url = article; action= ciao;} Richiedi l'accesso a una comunita di Municipia * "COM-P.A.":{url = article; action= ciao;} * "Comune di Senigallia":{url = article; action= ciao;} * "Comuneinlinea":{url = article; action= ciao;} * "Comunicatori Pubblici":{url = article; action= ciao;} * "Findonline":{url = article; action= ciao;} * "Provincia Regionale di Messina":{url = article; action= ciao;} * "Provincia di Brescia":{url = article; action= ciao;} * "Provincia di Milano":{url = article; action= ciao;} * "Provincia di Modena":{url = article; action= ciao;} * "Provincia di Napoli":{url = article; action= ciao;} * "Provincia di Padova":{url = article; action= ciao;} * "Provincia di Pesaro-Urbino":{url = article; action= ciao;} * "Provincia Autonoma di Trento":{url = article; action= ciao;} Oppure "segnala una nuova comunita!":{url = article; action= ciao;}SOPE/sope-xml/STXSaxDriver/STXSaxDriver.h0000644000000000000000000000465115004363604017062 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __ExtraSTX_STXSaxDriver_H__ #define __ExtraSTX_STXSaxDriver_H__ #import #include @class NSArray, NSDictionary; @class SaxAttributes; @class StructuredTextParagraph, StructuredTextList, StructuredTextListItem; @class StructuredTextLiteralBlock, StructuredTextHeader; @interface STXSaxDriver : NSObject < SaxXMLReader > { id contentHandler; id errorHandler; id lexicalHandler; id entityResolver; NSDictionary *context; SaxAttributes *attrs; } /* handlers */ - (void)setContentHandler:(id)_handler; - (void)setDTDHandler:(id)_handler; - (void)setErrorHandler:(id)_handler; - (void)setEntityResolver:(id)_handler; - (id)contentHandler; - (id)dtdHandler; - (id)errorHandler; - (id)entityResolver; /* parsing */ - (void)parseFromSource:(id)_source systemId:(NSString *)_sysId; /* generating events */ - (void)produceSaxEventsForParagraph:(StructuredTextParagraph *)_p; - (void)produceSaxEventsForList:(StructuredTextList *)_list; - (void)produceSaxEventsForListItem:(StructuredTextListItem *)_item; - (void)produceSaxEventsForLiteralBlock:(StructuredTextLiteralBlock *)_block; - (void)produceSaxEventsForHeader:(StructuredTextHeader *)_header; - (void)produceSaxEventsForElement:(id)_element; - (void)produceSaxEventsForElements:(NSArray *)_elems; @end #endif /* __ExtraSTX_STXSaxDriver_H__ */ SOPE/sope-xml/STXSaxDriver/COPYRIGHT0000644000000000000000000000216315004363604015672 0ustar rootrootStructured Text Code Copyright (C) 2004 eXtrapola Srl Contact: marco.barulli@extrapola.com SAX Driver Classes Copyright (C) 2004 Helge Hess Contact: helge.hess@opengroupware.org Statement by Extrapola SRL (Marco Barulli) ========================================== I'm glad to confirm that eXtrapola Srl, as the copyright holder on the StructuredText code sent to the OpenGroupware.org project and initially written by Mirko Viviani and Giulio Cesare Solaroli, hereby states that the code is licensed and can be used under the terms of the Lesser General Public License. Statement by Mirko Viviani ========================== Mirko Viviani, as the original author of the StructuredText framework sent to the OpenGroupware.org project, hereby states that the code is licensed and can be used under the terms of the Lesser General Public License. Statement by Giulio Cesare Solaroli =================================== I, as one of the original author on the StructuredText code sent to the OpenGroupware.org project, hereby states that the code is licensed and can be used under the terms of the Lesser General Public License. SOPE/sope-xml/STXSaxDriver/Model/0000755000000000000000000000000015004363604015435 5ustar rootrootSOPE/sope-xml/STXSaxDriver/Model/StructuredTextParagraph.m0000644000000000000000000000266015004363604022456 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "StructuredTextParagraph.h" #include "common.h" @implementation StructuredTextParagraph - (id)initWithString:(NSString *)_s { if ((self = [super init])) { self->_text = [_s retain]; } return self; } - (void)dealloc { [self->_text release]; [super dealloc]; } /* accessors */ - (NSString *)text { return self->_text; } /* processing */ - (NSString *)textParsedWithDelegate:(id)_del inContext:(NSDictionary *)_ctx { self->_delegate = _del; [self beginParagraphInContext:_ctx]; [self parseText:[self text] inContext:_ctx]; [self endParagraphInContext:_ctx]; return nil; } @end /* StructuredTextParagraph */ SOPE/sope-xml/STXSaxDriver/Model/GNUmakefile0000644000000000000000000000120115004363604017501 0ustar rootroot# # StructuredText.subproj makefile for StructuredText. # # Author: Mirko Viviani # # Date: 24 November 2003 # include ../../../config.make include $(GNUSTEP_MAKEFILES)/common.make SUBPROJECT_NAME = Model Model_PCH_FILE = common.h Model_OBJC_FILES = \ StructuredTextDocument.m \ StructuredTextBodyElement.m \ StructuredTextParagraph.m \ StructuredTextListItem.m \ StructuredTextList.m \ StructuredTextLiteralBlock.m \ StructuredTextHeader.m ADDITIONAL_INCLUDE_DIRS += \ -I. -I.. -I../ExtraSTX -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/subproject.make -include GNUmakefile.postamble SOPE/sope-xml/STXSaxDriver/Model/StructuredTextList.m0000644000000000000000000000236515004363604021466 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "StructuredTextList.h" #include "StructuredTextListItem.h" #include "common.h" @implementation StructuredTextList - (id)initWithTypology:(int)aValue { if ((self = [super init])) { self->typology = aValue; } return self; } /* accessors */ - (int)typology { return self->typology; } /* operations */ - (void)addElement:(StructuredTextListItem *)_item { if (_item == nil) return; [super addElement:_item]; [_item setList:self]; } @end /* StructuredTextList */ SOPE/sope-xml/STXSaxDriver/Model/StructuredTextBodyElement.h0000644000000000000000000000522015004363604022746 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __StructuredTextBodyElement_H__ #define __StructuredTextBodyElement_H__ #import #import #include "StructuredTextRenderingDelegate.h" @class NSMutableArray; @interface StructuredTextBodyElement : NSObject { NSMutableArray *_elements; id _delegate; /* non-retained */ BOOL runPreprocessor; } - (NSMutableArray *)elements; - (void)addElement:(StructuredTextBodyElement *)_element; - (NSString *)parseText:(NSString *)_str inContext:(NSDictionary *)_ctx; - (NSRange)findBoldSubstring:(NSString *)_str; - (NSRange)findItalicsSubstring:(NSString *)_str; - (NSRange)findUnderlineSubstring:(NSString *)_str; - (NSRange)findLinkImageSubstring:(NSString *)_str; - (NSRange)findLinkSubstring:(NSString *)_str; - (NSRange)findLinkTargetFromString:(NSString *)_str; - (NSRange)findDynamicKeySubstring:(NSString *)_str; - (void)appendText:(NSString *)_txt inContext:(NSDictionary *)_ctx; - (void)beginItalicsInContext:(NSDictionary *)_ctx; - (void)endItalicsInContext:(NSDictionary *)_ctx; - (void)beginUnderlineInContext:(NSDictionary *)_ctx; - (void)endUnderlineInContext:(NSDictionary *)_ctx; - (void)beginBoldInContext:(NSDictionary *)_ctx; - (void)endBoldInContext:(NSDictionary *)_ctx; - (void)beginPreformattedInContext:(NSDictionary *)_ctx; - (void)endPreformattedInContext:(NSDictionary *)_ctx; - (void)beginParagraphInContext:(NSDictionary *)_ctx; - (void)endParagraphInContext:(NSDictionary *)_ctx; - (NSString *)linkImage:(NSString *)_str inContext:(NSDictionary *)_ctx; - (NSString *)linkText:(NSString *)_str inContext:(NSDictionary *)_ctx; - (NSString *)linkTargetFromString:(NSString *)_str; - (NSString *)dynamicKeyText:(NSString *)aKey inContext:(NSDictionary *)_ctx; - (NSString *)preprocessText:(NSString *)_str inContext:(NSDictionary *)_ctx; @end #endif /* __StructuredTextBodyElement_H__ */ SOPE/sope-xml/STXSaxDriver/Model/common.h0000644000000000000000000000002715004363604017075 0ustar rootroot#include "../common.h" SOPE/sope-xml/STXSaxDriver/Model/README0000644000000000000000000000051215004363604016313 0ustar rootroot Notes ===== The central class containing the parsing code seems to be: StructuredTextBodyElement Classes ======= NSObject StructuredTextBodyElement StructuredTextHeader StructuredTextList StructuredTextListItem StructuredTextParagraph StructuredTextDocument StructuredTextLiteralBlock SOPE/sope-xml/STXSaxDriver/Model/StructuredTextDocument.m0000644000000000000000000000250615004363604022326 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "StructuredTextDocument.h" #include "StructuredTextBodyElement.h" #include "common.h" @implementation StructuredTextDocument - (void)dealloc { [self->_bodyElements release]; [super dealloc]; } /* accessors */ - (NSMutableArray *)bodyElements { if (self->_bodyElements == nil) self->_bodyElements = [[NSMutableArray alloc] init]; return self->_bodyElements; } /* operations */ - (void)addBodyElement:(StructuredTextBodyElement *)_body { if (_body == nil) return; [[self bodyElements] addObject:_body]; } @end /* StructuredTextDocument */ SOPE/sope-xml/STXSaxDriver/Model/StructuredTextListItem.m0000644000000000000000000000416715004363604022307 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "StructuredTextListItem.h" #include "StructuredTextList.h" #include "common.h" @interface NSObject(SetListPrivate) - (void)setList:(id)_list; @end @implementation StructuredTextListItem - (id)initWithTitle:(NSString *)_aTitle text:(NSString *)_aString { if ((self = [super init])) { self->_title = [_aTitle copy]; self->_text = [_aString copy]; } return self; } - (void)dealloc { [self->_title release]; [self->_text release]; [super dealloc]; } /* accessors */ - (NSString *)title { return self->_title; } - (NSString *)text { return self->_text; } - (void)setList:(StructuredTextList *)aList { self->_list = aList; } - (StructuredTextList *)list { return self->_list; } /* operations */ - (void)addElement:(StructuredTextBodyElement *)_item { if (_item == nil) return; [super addElement:_item]; if ([_item respondsToSelector:@selector(setList:)]) [_item setList:_list]; } /* parsing parts */ - (NSString *)titleParsedWithDelegate:(id)_d inContext:(NSDictionary *)_ctx { self->_delegate = _d; return [self parseText:[self title] inContext:_ctx]; } - (NSString *)textParsedWithDelegate:(id)_del inContext:(NSDictionary *)_ctx { self->_delegate = _del; return [self parseText:[self text] inContext:_ctx]; } @end /* StructuredTextListItem */ SOPE/sope-xml/STXSaxDriver/Model/StructuredTextList.h0000644000000000000000000000242015004363604021451 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __StructuredTextList_H__ #define __StructuredTextList_H__ #include "StructuredTextBodyElement.h" #define StructuredTextList_BULLET 0 #define StructuredTextList_ENUMERATED 1 #define StructuredTextList_DEFINITION 2 @class StructuredTextListItem; @interface StructuredTextList : StructuredTextBodyElement { int typology; } - (id)initWithTypology:(int)aValue; /* accessors */ - (int)typology; /* operations */ - (void)addElement:(StructuredTextListItem *)anItem; @end #endif /* __StructuredTextList_H__ */ SOPE/sope-xml/STXSaxDriver/Model/StructuredTextHeader.m0000644000000000000000000000424015004363604021735 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "StructuredTextHeader.h" #include "common.h" @implementation StructuredTextHeader - (id)initWithString:(NSString *)_str level:(int)_level { if ((self = [super init])) { self->_text = [_str copy]; self->level = _level; } return self; } - (void)dealloc { [self->_text release]; [super dealloc]; } /* accessors */ - (NSString *)text { return self->_text; } - (int)level { return self->level; } /* operations */ - (NSString *)textParsedWithDelegate:(id)_del inContext:(NSDictionary *)_ctx { self->_delegate = _del; return [self parseText:[self text] inContext:_ctx]; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; /* header specific */ if (self->_text) [ms appendFormat:@" text-len=%"PRIuPTR, [self->_text length]]; if (self->level) [ms appendFormat:@" level=%i", self->level]; /* common stuff */ if (self->_elements) [ms appendFormat:@" #elements=%"PRIuPTR, [self->_elements count]]; if (self->_delegate) { [ms appendFormat:@" delegate=0x%p<%@>", self->_delegate, NSStringFromClass([(id)self->_delegate class])]; } if (self->runPreprocessor) [ms appendFormat:@" run-preprocessor"]; [ms appendString:@">"]; return ms; } @end /* StructuredTextHeader */ SOPE/sope-xml/STXSaxDriver/Model/StructuredTextBodyElement.m0000644000000000000000000005632415004363604022766 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "StructuredTextBodyElement.h" #include "NSString+STX.h" #include "common.h" #define ST_ESCAPE_CHAR '\\' #define ST_UNDERLINE_CHAR '_' #define ST_DYNAMICKEY_CHAR '@' #define ST_ITALICS_CHAR '*' #define ST_LINK_CHAR '"' #define ST_LINKIMAGE_CHAR '[' static NSString *preprocessorTag = @"##"; @implementation StructuredTextBodyElement static BOOL debugOn = NO; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; debugOn = [ud boolForKey:@"STXDebugEnabled"]; } - (id)init { if ((self = [super init])) { self->runPreprocessor = YES; } return self; } - (void)dealloc { [self->_elements release]; [super dealloc]; } /* accessors */ - (NSMutableArray *)elements { if (_elements == nil) _elements = [[NSMutableArray alloc] init]; return _elements; } - (void)addElement:(StructuredTextBodyElement *)anElement { if (anElement == nil) return; [[self elements] addObject:anElement]; } /* operations */ - (NSString *)parseText:(NSString *)_str inContext:(NSDictionary *)_ctx { // TODO: too big a method NSMutableString *result; NSString *text; NSRange range, rangeOut; int i, length, start; if (debugOn) NSLog(@"PARSE TEXT: '%@' (delegate=0x%p)", _str, self->_delegate); _str = [self preprocessText:_str inContext:_ctx]; if (debugOn) NSLog(@" preprocessed: '%@'", _str); result = [NSMutableString stringWithCapacity:[_str length]]; text = _str; for (i = start = 0, length = [text length]; i < length; i++) { unichar c; c = [text characterAtIndex:i]; switch (c) { case ST_ESCAPE_CHAR: if (i - start > 0) { range.location = start; range.length = (i - start); [self appendText:[text substringWithRange:range] inContext:_ctx]; } start = ++i; break; case '\'': if (i - start > 0) { range.location = start; range.length = i - start; [self appendText:[text substringWithRange:range] inContext:_ctx]; } if (i + 1 < length) { c = [_str characterAtIndex:i + 1]; if (c == '\'') { start = ++i; break; } } range.location = i + 1; range.length = length - range.location; rangeOut = [text rangeOfString:@"'" options:0 range:range]; if (rangeOut.length > 0) { NSString *s; range.location = i + 1; range.length = rangeOut.location - range.location; start = i = rangeOut.location + 1; s = [[text substringWithRange:range] unescapedString]; [self beginPreformattedInContext:_ctx]; [self appendText:s inContext:_ctx]; [self endPreformattedInContext:_ctx]; } else { start = i; } break; case ST_UNDERLINE_CHAR: if (i - start > 0) { range.location = start; range.length = i - start; start = i; [self appendText:[text substringWithRange:range] inContext:_ctx]; } range = [self findUnderlineSubstring:[text substringFromIndex:i + 1]]; if (range.length > 0) { NSString *s; range.location = i + 1; i += range.length + 1; start = i + 1; s = [[text substringWithRange:range] unescapedString]; [self beginUnderlineInContext:_ctx]; s = [self parseText:s inContext:_ctx]; [self appendText:s inContext:_ctx]; [self endUnderlineInContext:_ctx]; } break; case ST_DYNAMICKEY_CHAR: if (i - start > 0) { range.location = start; range.length = i - start; start = i; [self appendText:[text substringWithRange:range] inContext:_ctx]; } range = [self findDynamicKeySubstring:[text substringFromIndex:i + 1]]; if (range.length > 0) { NSString *s; range.location = i + 1; i += range.length + 1; start = i + 1; s = [self parseText:[text substringWithRange:range] inContext:_ctx]; [self appendText:[self dynamicKeyText:s inContext:_ctx] inContext:_ctx]; } break; case ST_ITALICS_CHAR: { // italics and bold if (i - start > 0) { range.location = start; range.length = i - start; start = i; [self appendText:[text substringWithRange:range] inContext:_ctx]; } if (i + 1 < length) { c = [text characterAtIndex:i + 1]; if (c == ST_ITALICS_CHAR) { range = [self findBoldSubstring:[text substringFromIndex:i + 2]]; if (range.length > 0) { NSString *s; range.location = i + 2; i += range.length + 3; start = i + 1; s = [[text substringWithRange:range] unescapedString]; [self beginBoldInContext:_ctx]; s = [self parseText:s inContext:_ctx]; [self appendText:s inContext:_ctx]; [self endBoldInContext:_ctx]; } } else { range = [self findItalicsSubstring:[text substringFromIndex:i + 1]]; if (range.length > 0) { NSString *s; range.location = i + 1; i += range.length + 1; start = i + 1; s = [[text substringWithRange:range] unescapedString]; [self beginItalicsInContext:_ctx]; s = [self parseText:s inContext:_ctx]; [self appendText:s inContext:_ctx]; [self endItalicsInContext:_ctx]; } } } break; } case ST_LINKIMAGE_CHAR: // links if (i - start > 0) { range.location = start; range.length = i - start; start = i; [self appendText:[text substringWithRange:range] inContext:_ctx]; } range = [self findLinkImageSubstring:[text substringFromIndex:i + 1]]; if (range.length > 0) { NSString *s; range.location = i + 1; i += range.length; start = i + 1; s = [self linkImage:[text substringWithRange:range] inContext:_ctx]; [self appendText:s inContext:_ctx]; } break; case ST_LINK_CHAR: // links if (i - start > 0) { range.location = start; range.length = i - start; start = i; [self appendText:[text substringWithRange:range] inContext:_ctx]; } range = [self findLinkSubstring:[text substringFromIndex:(i + 1)]]; if (range.length > 0) { NSString *s; range.location = i + 1; i += range.length; start = i + 1; s = [self linkText:[text substringWithRange:range] inContext:_ctx]; [self appendText:s inContext:_ctx]; if (debugOn) NSLog(@"found link substring: '%@'", s); } break; } } if (i - start > 0) { range.location = start; range.length = i - start; [self appendText:[text substringWithRange:range] inContext:_ctx]; } if (debugOn) NSLog(@" result: '%@'", result); return result; } - (void)appendText:(NSString *)_txt inContext:(NSDictionary *)_ctx { [self->_delegate appendText:_txt inContext:_ctx]; } - (void)beginItalicsInContext:(NSDictionary *)_ctx { [self->_delegate beginItalicsInContext:_ctx]; } - (void)endItalicsInContext:(NSDictionary *)_ctx { [self->_delegate endItalicsInContext:_ctx]; } - (void)beginUnderlineInContext:(NSDictionary *)_ctx { [self->_delegate beginUnderlineInContext:_ctx]; } - (void)endUnderlineInContext:(NSDictionary *)_ctx { [self->_delegate endUnderlineInContext:_ctx]; } - (void)beginBoldInContext:(NSDictionary *)_ctx { [self->_delegate beginBoldInContext:_ctx]; } - (void)endBoldInContext:(NSDictionary *)_ctx { [self->_delegate endBoldInContext:_ctx]; } - (void)beginPreformattedInContext:(NSDictionary *)_ctx { [self->_delegate beginPreformattedInContext:_ctx]; } - (void)endPreformattedInContext:(NSDictionary *)_ctx { [self->_delegate endPreformattedInContext:_ctx]; } - (void)beginParagraphInContext:(NSDictionary *)_ctx { [self->_delegate beginParagraphInContext:_ctx]; } - (void)endParagraphInContext:(NSDictionary *)_ctx { [self->_delegate endParagraphInContext:_ctx]; } - (NSRange)findMarkerSubstring:(NSString *)_str withMarker:(unichar)aMarker markerLength:(int)markLength { NSRange range; int i, h, length; length = [_str length]; markLength--; for (i = 0; i < length; i++) { unichar c; c = [_str characterAtIndex:i]; if (c == aMarker && i + markLength < length) { BOOL foundMarker = YES; for (h = i + 1; h <= i + markLength; h++) { c = [_str characterAtIndex:h]; if (c != aMarker) { foundMarker = NO; break; } } if (foundMarker) { range.location = 0; range.length = i; return range; } } else if (c == ST_ESCAPE_CHAR) { i++; } } range.location = NSNotFound; range.length = 0; return range; } /* find markers */ - (NSRange)findBoldSubstring:(NSString *)_str { return [self findMarkerSubstring:_str withMarker:ST_ITALICS_CHAR markerLength:2]; } - (NSRange)findItalicsSubstring:(NSString *)_str { return [self findMarkerSubstring:_str withMarker:ST_ITALICS_CHAR markerLength:1]; } - (NSRange)findUnderlineSubstring:(NSString *)_str { return [self findMarkerSubstring:_str withMarker:ST_UNDERLINE_CHAR markerLength:1]; } /* operations */ - (NSRange)_findLinkBlockTargetSubstring:(NSString *)_str { NSRange range, rangeTarget; int length; unichar c; length = [_str length]; if (debugOn) NSLog(@" find link block target: '%@'", _str); c = [_str characterAtIndex:0]; if (c == ':' && 1 < length) { c = [_str characterAtIndex:1]; range.location = 2; range.length = length - range.location; if (c == '\'') { range = [_str rangeOfString:@"'" options:0 range:range]; if (range.length == 0) return range; range.length = range.location + 1; if (range.length < length) { rangeTarget = [self findLinkTargetFromString: [_str substringFromIndex:range.length]]; if (rangeTarget.length > 0) range.length += rangeTarget.length; } } else if (c == '{') { range = [_str rangeOfString:@"}" options:0 range:range]; if (range.length == 0) return range; range.length = range.location + 1; if (range.length < length) { rangeTarget = [self findLinkTargetFromString: [_str substringFromIndex:range.length]]; if (rangeTarget.length > 0) range.length += rangeTarget.length; } } else { range = [_str rangeOfString:@" " options:0 range:range]; range.length = (range.length == 0) ? length : range.location; } range.location = 0; if (debugOn) NSLog(@" range(0,%"PRIuPTR")", range.length); return range; } range.location = NSNotFound; range.length = 0; if (debugOn) NSLog(@" not found."); return range; } - (NSRange)findLinkImageSubstring:(NSString *)_str { NSRange range; int i, length; for (i = 0, length = [_str length]; i < length; i++) { unichar c; c = [_str characterAtIndex:i]; if (!(c == ']' && i + 1 < length)) continue; range = [self _findLinkBlockTargetSubstring: [_str substringFromIndex:i + 1]]; if (range.length > 0) { range.length += (range.location + i + 1); range.location = 0; } return range; } range.location = NSNotFound; range.length = 0; return range; } - (NSRange)findLinkSubstring:(NSString *)_str { NSRange range; int i, length; length = [_str length]; if (debugOn) NSLog(@"find link substring: '%@'(%d)", _str, length); for (i = 0; i < length; i++) { unichar c; c = [_str characterAtIndex:i]; if (!(c == ST_LINK_CHAR && ((i + 1) < length))) continue; range = [self _findLinkBlockTargetSubstring: [_str substringFromIndex:i + 1]]; if (range.length > 0) { range.length += (range.location + i + 1); range.location = 0; } return range; } range.location = NSNotFound; range.length = 0; return range; } - (NSRange)findLinkTargetFromString:(NSString *)_str { int i, length; BOOL tag = NO; NSRange range; for (i = 0, length = [_str length]; i < length; i++) { unichar c; c = [_str characterAtIndex:i]; if (!tag && c == ':' && i + 1 < length) { c = [_str characterAtIndex:i + 1]; if (c == ':') { i++; tag = YES; } } else if (tag) { if (c == '\'') { range.location = i + 1; range.length = length - range.location; range = [_str rangeOfString:@"'" options:0 range:range]; if (range.length == 0) return range; length = range.location + 1; break; } else { range.location = i; range.length = length - i; range = [_str rangeOfString:@" " options:0 range:range]; if (range.length == 0) break; length = range.location; break; } } else { range.location = NSNotFound; range.length = 0; return range; } } range.location = 0; range.length = length; return range; } - (NSRange)findDynamicKeySubstring:(NSString *)_str { NSRange range; int i, length; for (i = 0, length = [_str length]; i < length; i++) { unichar c; c = [_str characterAtIndex:i]; if (c == ST_DYNAMICKEY_CHAR) { range.location = 0; range.length = i; return range; } } range.location = NSNotFound; range.length = 0; return range; } /* links */ - (NSString *)_linkBlockTarget:(NSString *)_str withName:(NSString *)aName isImage:(BOOL)isImage inContext:(NSDictionary *)_ctx { NSString *linkName = aName; NSRange range; int length; unichar c; NSArray *components; NSString *link, *linkType = nil, *target = nil; NSRange rangeOut; if (_delegate == nil) return _str; length = [_str length]; if (length < 2) return nil; c = [_str characterAtIndex:0]; if (c != ':') { if (debugOn) NSLog(@"no link in: '%@'", _str); return nil; } c = [_str characterAtIndex:1]; range.location = 2; range.length = length - range.location; if (c == '\'') { rangeOut = [_str rangeOfString:@"'" options:0 range:range]; if (rangeOut.length == 0) return nil; range.length = rangeOut.location - range.location; target = [self linkTargetFromString: [_str substringFromIndex:rangeOut.location + 1]]; } else if (c == '{') { rangeOut = [_str rangeOfString:@"}" options:0 range:range]; if (rangeOut.length == 0) return nil; range.location--; range.length = rangeOut.location - range.location + 1; linkType = @"ibn"; target = [self linkTargetFromString: [_str substringFromIndex:rangeOut.location + 1]]; } else { rangeOut = [_str rangeOfString:@"::" options:0 range:range]; range.location--; if (rangeOut.length == 0) { rangeOut = [_str rangeOfString:@" " options:0 range:range]; range.length = (rangeOut.length == 0) ? length - range.location : rangeOut.location - range.location; } else { range.length = rangeOut.location - range.location; target = [self linkTargetFromString: [_str substringFromIndex:rangeOut.location]]; } } link = [_str substringWithRange:range]; components = [link componentsSeparatedByString:@":"]; if (!linkType) linkType = [components objectAtIndex:0]; if (!isImage) { if ([linkType isEqualToString:@"mailto"]) { return [_delegate insertEmail:linkName withAddress:link inContext:_ctx]; } if ([linkType isEqualToString:@"img"]) { NSString *url; url = [link substringFromIndex:[linkType length] + 1]; return [_delegate insertImage:linkName withUrl:url inContext:_ctx]; } if ([linkType isEqualToString:@"ibn"]) { if (debugOn) NSLog(@"IBN link %@", linkName); return [_delegate insertExtrapolaLink:linkName parameters:[link propertyList] withTarget:target inContext:_ctx]; } if (debugOn) NSLog(@"link %@: %@", linkName, link); return [_delegate insertLink:linkName withUrl:link target:target inContext:_ctx]; } if (debugOn) NSLog(@"img %@: %@", linkName, link); return [_delegate insertImage:linkName withUrl:link inContext:_ctx]; } - (NSString *)linkImage:(NSString *)_str inContext:(NSDictionary *)_ctx { NSString *linkName = nil; NSRange range; int i, length, startOfTarget; if (_delegate == nil) return _str; length = [_str length]; if (length > 1) { unichar c; range.location = 0; range.length = length; range = [_str rangeOfString:@"]" options:0 range:range]; if (range.length == 0) return _str; startOfTarget = range.location + 1; for (i = 1; i < range.location; i++) { c = [_str characterAtIndex:i]; if (c == ST_LINK_CHAR && i + 1 < length) { range.location = 1; range.length = i - 1; linkName = [_str substringWithRange:range]; range.length = startOfTarget - (i + 2); range.location = i + 1; linkName = [self _linkBlockTarget:[_str substringWithRange:range] withName:linkName isImage:YES inContext:_ctx]; break; } } if (linkName) { NSString *result; result = [self _linkBlockTarget: [_str substringFromIndex:startOfTarget] withName:linkName isImage:NO inContext:_ctx]; if (result == nil) result = _str; return result; } } return _str; } - (NSString *)linkText:(NSString *)_str inContext:(NSDictionary *)_ctx { NSString *linkName; int i, length; if (_delegate == nil) return _str; for (i = 0, length = [_str length]; i < length; i++) { NSString *result; unichar c; c = [_str characterAtIndex:i]; if (!(c == ST_LINK_CHAR && (i + 1 < length))) continue; linkName = [_str substringToIndex:i]; result = [self _linkBlockTarget:[_str substringFromIndex:i + 1] withName:linkName isImage:NO inContext:_ctx]; return result ? result : _str; } return _str; } - (NSString *)linkTargetFromString:(NSString *)_str { int i, length, start; BOOL tag = NO; NSRange range; length = [_str length]; for (start = i = 0; i < length; i++) { unichar c; c = [_str characterAtIndex:i]; if (!tag && c == ':' && i + 1 < length) { c = [_str characterAtIndex:i + 1]; if (c == ':') { start = i + 2; i++; tag = YES; } } else if (c == '\'') { range.location = i + 1; range.length = length - range.location; range = [_str rangeOfString:@"'" options:0 range:range]; if (range.length == 0) break; length = range.location; start++; break; } else { break; } } range.location = start; range.length = length - range.location; if (range.length <= 0) { return nil; } return [_str substringWithRange:range]; } - (NSString *)dynamicKeyText:(NSString *)_str inContext:(NSDictionary *)_ctx { if (_delegate) return [_delegate insertDynamicKey:_str inContext:_ctx]; return _str; } - (NSString *)preprocessText:(NSString *)_str inContext:(NSDictionary *)_ctx { // TODO: breaks on libFoundation // TODO: need to find out what this is exactly supposed to do NSMutableString *result; NSRange rangeToCopy, range, rangeEnd; int length; if (debugOn) NSLog(@"preprocess: '%@'", _str); if (!self->runPreprocessor) return _str; self->runPreprocessor = NO; length = [_str length]; result = [NSMutableString stringWithCapacity:length]; range.location = 0; range.length = length; rangeEnd.location = 0; rangeEnd.length = length; rangeToCopy.location = 0; rangeToCopy.length = length; // TODO: the NSNotFound check might make trouble on libFoundation for (; range.location != NSNotFound && range.location < length;) { range = [_str rangeOfString:preprocessorTag options:0 range:range]; if (range.length == 0) { if (rangeEnd.location == 0) return _str; rangeToCopy.location = rangeEnd.location + 2; rangeToCopy.length = (length - rangeToCopy.location); [result appendString:[_str substringWithRange:rangeToCopy]]; continue; } rangeToCopy.location = rangeEnd.location; if (rangeEnd.location > 0) rangeToCopy.location += 2; rangeEnd.location = range.location + 2; rangeEnd.length = length - rangeEnd.location; rangeEnd = [_str rangeOfString:preprocessorTag options:0 range:rangeEnd]; if (rangeEnd.length > 0) { NSRange keyRange; NSString *text; rangeToCopy.length = (range.location - rangeToCopy.location); if (rangeToCopy.length > 0) { NSString *s; s = [_str substringWithRange:rangeToCopy]; [result appendString:s]; } keyRange.location = range.location + 2; keyRange.length = rangeEnd.location - keyRange.location; text = [_delegate insertPreprocessedTextForKey: [_str substringWithRange:keyRange] inContext:_ctx]; if (text) [result appendString:text]; range.location = rangeEnd.location + 2; range.length = length - range.location; self->runPreprocessor = YES; } else { range.location = NSNotFound; rangeToCopy.length = length - rangeToCopy.location; [result appendString:[_str substringWithRange:rangeToCopy]]; } } return result; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if (self->_elements) [ms appendFormat:@" #elements=%"PRIuPTR, [self->_elements count]]; if (self->_delegate) { [ms appendFormat:@" delegate=0x%p<%@>", self->_delegate, NSStringFromClass([(id)self->_delegate class])]; } if (self->runPreprocessor) [ms appendFormat:@" run-preprocessor"]; [ms appendString:@">"]; return ms; } @end /* StructuredTextBodyElement */ SOPE/sope-xml/STXSaxDriver/Model/StructuredTextLiteralBlock.h0000644000000000000000000000172715004363604023116 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import @class NSString; @interface StructuredTextLiteralBlock : NSObject { NSString *_text; } - (id)initWithString:(NSString *)aString; /* accessors */ - (NSString *)text; @end SOPE/sope-xml/STXSaxDriver/Model/StructuredTextLiteralBlock.m0000644000000000000000000000222015004363604023110 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "StructuredTextLiteralBlock.h" #include "common.h" @implementation StructuredTextLiteralBlock - (id)initWithString:(NSString *)_str { if ((self = [super init])) { self->_text = [_str copy]; } return self; } - (void)dealloc { [self->_text release]; [super dealloc]; } /* accessors */ - (NSString *)text { return self->_text; } @end /* StructuredTextLiteralBlock */ SOPE/sope-xml/STXSaxDriver/Model/COPYRIGHT0000644000000000000000000000203415004363604016727 0ustar rootroot Structured Text Code Copyright (C) 2004 eXtrapola Srl Contact: marco.barulli@extrapola.com Statement by Extrapola SRL (Marco Barulli) ========================================== I'm glad to confirm that eXtrapola Srl, as the copyright holder on the StructuredText code sent to the OpenGroupware.org project and initially written by Mirko Viviani and Giulio Cesare Solaroli, hereby states that the code is licensed and can be used under the terms of the Lesser General Public License. Statement by Mirko Viviani ========================== Mirko Viviani, as the original author of the StructuredText framework sent to the OpenGroupware.org project, hereby states that the code is licensed and can be used under the terms of the Lesser General Public License. Statement by Giulio Cesare Solaroli =================================== I, as one of the original author on the StructuredText code sent to the OpenGroupware.org project, hereby states that the code is licensed and can be used under the terms of the Lesser General Public License. SOPE/sope-xml/STXSaxDriver/Model/StructuredTextHeader.h0000644000000000000000000000226015004363604021730 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "StructuredTextBodyElement.h" @class NSString, NSDictionary; @interface StructuredTextHeader : StructuredTextBodyElement { NSString *_text; int level; } - (id)initWithString:(NSString *)aString level:(int)aLevel; /* accessors */ - (NSString *)text; - (int)level; /* operations */ - (NSString *)textParsedWithDelegate:(id)_dele inContext:(NSDictionary *)aContext; @end SOPE/sope-xml/STXSaxDriver/Model/StructuredTextDocument.h0000644000000000000000000000202615004363604022316 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import @class NSMutableArray; @class StructuredTextBodyElement; @interface StructuredTextDocument : NSObject { NSMutableArray *_bodyElements; } - (NSMutableArray *)bodyElements; - (void)addBodyElement:(StructuredTextBodyElement *)aBody; @end SOPE/sope-xml/STXSaxDriver/Model/StructuredTextListItem.h0000644000000000000000000000310115004363604022265 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __StructuredTextListItem_H__ #define __StructuredTextListItem_H__ #include "StructuredTextBodyElement.h" @class NSString, NSDictionary; @class StructuredTextList; @interface StructuredTextListItem : StructuredTextBodyElement { StructuredTextList *_list; // not retained NSString *_title; NSString *_text; } - (id)initWithTitle:(NSString *)aTitle text:(NSString *)aString; /* accessors */ - (NSString *)title; - (NSString *)text; - (void)setList:(StructuredTextList *)aList; - (StructuredTextList *)list; /* parsing */ - (NSString *)titleParsedWithDelegate:(id)_del inContext:(NSDictionary *)_ctx; - (NSString *)textParsedWithDelegate:(id)_del inContext:(NSDictionary *)_ctx; @end #endif /* __StructuredTextListItem_H__ */ SOPE/sope-xml/STXSaxDriver/Model/StructuredTextParagraph.h0000644000000000000000000000213715004363604022450 0ustar rootroot/* Copyright (C) 2004 eXtrapola Srl This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "StructuredTextBodyElement.h" @interface StructuredTextParagraph : StructuredTextBodyElement { NSString *_text; } - (id)initWithString:(NSString *)aString; /* accessors */ - (NSString *)text; /* parsing */ - (NSString *)textParsedWithDelegate:(id)_del inContext:(NSDictionary *)aContext; @end SOPE/sope-xml/STXSaxDriver/TODO0000644000000000000000000000053415004363604015067 0ustar rootrootTODO ==== - find out proper MIME types for STX - check why data/hhtest2.stx fails - further cleanup of the sources to OGo styleguides - remove unused classes - complete support for missing STX model classes in the SAX driver? - document the exact set of STX grammar which is supported - check for memory leaks (see TODO comments in sources) SOPE/sope-xml/STXSaxDriver/GNUmakefile.preamble0000644000000000000000000000145515004363604020242 0ustar rootroot# compilation settings ifeq ($(frameworks),yes) BUNDLE_INSTALL_DIR := $(FRAMEWORK_INSTALL_DIR)/SaxObjC.framework/Resources/SaxDrivers/ endif STXSaxDriver_INCLUDE_DIRS += \ -I. \ -I./Model/ \ -I./ExtraSTX/ \ -I.. # dependencies ifneq ($(frameworks),yes) STXSaxDriver_BUNDLE_LIBS += -lSaxObjC else STXSaxDriver_BUNDLE_LIBS += -framework SaxObjC endif # library/framework search pathes DEP_DIRS = ../SaxObjC ifneq ($(frameworks),yes) ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),\ -L$(GNUSTEP_BUILD_DIR)/$(dir)/$(GNUSTEP_OBJ_DIR_NAME)) else ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir)) endif ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) SYSTEM_LIB_DIR += -L/usr/local/lib64 -L/usr/lib64 else SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib endif SOPE/sope-xml/ChangeLogSaxDriver/0000755000000000000000000000000015004363604015546 5ustar rootrootSOPE/sope-xml/ChangeLogSaxDriver/bundle-info.plist0000644000000000000000000000067115004363604021031 0ustar rootroot{ CVS = "$Id: bundle-info.plist 429 2004-12-08 22:36:03Z znek $"; //bundleHandler = NSObject; requires = { bundleManagerVersion = 1; classes = ( { name = NSObject; } ); }; provides = { SAXDrivers = ( { name = ChangeLogSaxDriver; sourceTypes = ( "application/x-changelog" ); }, ); classes = ( { name = ChangeLogSaxDriver; }, ); }; } SOPE/sope-xml/ChangeLogSaxDriver/ChangeLogSaxDriver.h0000644000000000000000000000265115004363604021402 0ustar rootroot/* Copyright (C) 2004 Marcus Mueller This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __ChangeLogSaxDriver_ChangeLogSaxDriver_H_ #define __ChangeLogSaxDriver_ChangeLogSaxDriver_H_ #import #include @interface ChangeLogSaxDriver : NSObject < SaxXMLReader > { @private id contentHandler; id errorHandler; /* features */ BOOL fNamespaces; BOOL fNamespacePrefixes; NSString *namespace; /* internal */ NSMutableString *currentLog; struct { unsigned hasLog : 1; unsigned hasEntry : 1; } flags; } @end #endif /* __ChangeLogSaxDriver_ChangeLogSaxDriver_H_ */ SOPE/sope-xml/ChangeLogSaxDriver/ChangeLogSaxDriver.m0000644000000000000000000002646315004363604021416 0ustar rootroot/* Copyright (C) 2004 Marcus Mueller This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ChangeLogSaxDriver.h" #include "NSString+Extensions.h" #include "NSCalendarDate+Extensions.h" #include "common.h" @interface ChangeLogSaxDriver(PrivateAPI) - (NSString *)_namespace; - (void)_writeString:(NSString *)_s; - (void)_processLine:(NSString *)_line; - (void)_parseFromString:(NSString *)_str systemId:(NSString *)_sysId; - (void)_beginEntryWithDate:(NSCalendarDate *)_date; - (void)_endEntry; - (void)_beginLogs; - (void)_endLogs; - (void)_beginLog; - (void)_appendLog:(NSString *)_s; - (void)_endLog; @end @implementation ChangeLogSaxDriver static NSCharacterSet *wsSet = nil; static NSCharacterSet *wsnlSet = nil; + (void)initialize { static BOOL didInit = NO; if(didInit) return; didInit = YES; wsSet = [[NSCharacterSet whitespaceCharacterSet] retain]; wsnlSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] retain]; } - (void)dealloc { [self->contentHandler release]; [self->errorHandler release]; [self->namespace release]; [super dealloc]; } /* properties */ - (void)setProperty:(NSString *)_name to:(id)_value { return; [SaxNotRecognizedException raise:@"PropertyException" format:@"don't know property %@", _name]; } - (id)property:(NSString *)_name { return nil; [SaxNotRecognizedException raise:@"PropertyException" format:@"don't know property %@", _name]; return nil; } /* features */ - (void)setFeature:(NSString *)_name to:(BOOL)_value { if ([_name isEqualToString:@"http://xml.org/sax/features/namespaces"]) { self->fNamespaces = _value; return; } if ([_name isEqualToString: @"http://xml.org/sax/features/namespace-prefixes"]) { self->fNamespacePrefixes = _value; return; } [SaxNotRecognizedException raise:@"FeatureException" format:@"don't know feature %@", _name]; } - (BOOL)feature:(NSString *)_name { if ([_name isEqualToString:@"http://xml.org/sax/features/namespaces"]) return self->fNamespaces; if ([_name isEqualToString: @"http://xml.org/sax/features/namespace-prefixes"]) return self->fNamespacePrefixes; if ([_name isEqualToString: @"http://www.skyrix.com/sax/features/predefined-namespaces"]) return NO; [SaxNotRecognizedException raise:@"FeatureException" format:@"don't know feature %@", _name]; return NO; } /* handlers */ /* - (void)setDocumentHandler:(id)_handler { SaxDocumentHandlerAdaptor *a; a = [[SaxDocumentHandlerAdaptor alloc] initWithDocumentHandler:_handler]; [self setContentHandler:a]; [a release]; } */ - (void)setDTDHandler:(id)_handler { } - (id)dtdHandler { return nil; } - (void)setErrorHandler:(id)_handler { ASSIGN(self->errorHandler, _handler); } - (id)errorHandler { return self->errorHandler; } - (void)setEntityResolver:(id)_handler { } - (id)entityResolver { return nil; } - (void)setContentHandler:(id)_handler { ASSIGN(self->contentHandler, _handler); } - (id)contentHandler { return self->contentHandler; } /* parsing ... */ - (void)parseFromSource:(id)_source systemId:(NSString *)_sysId { NSAutoreleasePool *pool; pool = [[NSAutoreleasePool alloc] init]; if ([_source isKindOfClass:[NSData class]]) { NSString *s; s = [[NSString alloc] initWithData:_source encoding:[NSString defaultCStringEncoding]]; [self _parseFromString:s systemId:_sysId]; [s release]; } else if ([_source isKindOfClass:[NSURL class]]) { [self parseFromSystemId:_source]; } else if ([_source isKindOfClass:[NSString class]]) { if (_sysId == nil) _sysId = @""; [self _parseFromString:_source systemId:_sysId]; } else { SaxParseException *e; NSDictionary *ui; ui = [NSDictionary dictionaryWithObjectsAndKeys: _source ? _source : @"", @"source", self, @"parser", nil]; e = (id)[SaxParseException exceptionWithName:@"SaxIOException" reason:@"can't handle data-source" userInfo:ui]; [self->errorHandler fatalError:e]; } [pool release]; } - (void)parseFromSource:(id)_source { [self parseFromSource:_source systemId:@""]; } - (void)parseFromSystemId:(NSString *)_sysId { NSAutoreleasePool *pool; NSString *str; NSURL *url; pool = [[NSAutoreleasePool alloc] init]; url = [NSURL URLWithString:_sysId]; str = [NSString stringWithContentsOfURL:url]; [self _parseFromString:str systemId:_sysId]; [pool release]; } /* Private API */ - (void)_parseFromString:(NSString *)_s systemId:(NSString *)_sysId { static SaxAttributes *versionAttr = nil; NSArray *lines; unsigned i, count; self->currentLog = [[NSMutableString alloc] initWithCapacity:200]; self->flags.hasLog = NO; self->flags.hasEntry = NO; if (versionAttr == nil) { versionAttr = [[SaxAttributes alloc] init]; [versionAttr addAttribute:@"version" uri:[self _namespace] rawName:@"version" type:@"CDATA" value:@"1.0"]; } lines = [_s componentsSeparatedByString:@"\n"]; count = [lines count]; [self->contentHandler startDocument]; [self->contentHandler startElement:@"changelog" namespace:[self _namespace] rawName:@"changelog" attributes:versionAttr]; for(i = 0; i < count; i++) { [self _processLine:[lines objectAtIndex:i]]; } [self _endEntry]; [self->contentHandler endElement:@"changelog" namespace:[self _namespace] rawName:@"changelog"]; [self->contentHandler endDocument]; [self->currentLog release]; } - (void)_processLine:(NSString *)_line { if([_line length] > 0) { unichar first; NSCalendarDate *date; NSString *author; first = [_line characterAtIndex:0]; if(!(first == '*' || first == '-' || [wsSet characterIsMember:first]) && [_line parseDate:&date andAuthor:&author]) { SaxAttributes *authorAttrs; NSString *realName, *email; /* entry start */ [self _beginEntryWithDate:date]; /* author */ [author getRealName:&realName andEmail:&email]; if(!email) email = @""; authorAttrs = [[SaxAttributes alloc] init]; [authorAttrs addAttribute:@"email" uri:[self _namespace] rawName:@"email" type:@"CDATA" value:email]; [self->contentHandler startElement:@"author" namespace:[self _namespace] rawName:@"author" attributes:authorAttrs]; [authorAttrs release]; [self _writeString:realName]; [self->contentHandler endElement:@"author" namespace:[self _namespace] rawName:@"author"]; } else { /* strip leading whitespace and "*" from line */ _line = [_line stringByTrimmingLeadSpaces]; if([_line length] > 0) { first = [_line characterAtIndex:0]; if(first == '*') { /* new log line */ [self _beginLog]; _line = [_line substringFromIndex:1]; _line = [_line stringByTrimmingLeadSpaces]; } [self _appendLog:_line]; } } } } - (void)_beginEntryWithDate:(NSCalendarDate *)_date { SaxAttributes *entryAttrs; [self _endEntry]; /* date */ entryAttrs = [[SaxAttributes alloc] init]; [entryAttrs addAttribute:@"date" uri:[self _namespace] rawName:@"date" type:@"CDATA" value:[_date w3OrgDateTimeRepresentation]]; [self->contentHandler startElement:@"entry" namespace:[self _namespace] rawName:@"entry" attributes:entryAttrs]; [entryAttrs release]; self->flags.hasEntry = YES; } - (void)_endEntry { if(self->flags.hasEntry) { [self _endLogs]; [self->contentHandler endElement:@"entry" namespace:[self _namespace] rawName:@"entry"]; self->flags.hasEntry = NO; } } - (void)_beginLogs { if(!self->flags.hasLog) { [self->contentHandler startElement:@"logs" namespace:[self _namespace] rawName:@"logs" attributes:nil]; self->flags.hasLog = YES; } } - (void)_endLogs { if(self->flags.hasLog) { [self _endLog]; [self->contentHandler endElement:@"logs" namespace:[self _namespace] rawName:@"logs"]; self->flags.hasLog = NO; } } - (void)_beginLog { [self _beginLogs]; [self _endLog]; } - (void)_appendLog:(NSString *)_s { unsigned loc; if([_s length] == 0) return; loc = [self->currentLog length]; if(loc > 0) { unichar last; last = [self->currentLog characterAtIndex:loc - 1]; if(![wsnlSet characterIsMember:last]) { [self->currentLog appendString:@" "]; } } [self->currentLog appendString:_s]; } - (void)_endLog { NSRange r; r = NSMakeRange(0, [self->currentLog length]); if(r.length == 0) return; [self _beginLogs]; [self->contentHandler startElement:@"log" namespace:[self _namespace] rawName:@"log" attributes:nil]; [self _writeString:self->currentLog]; [self->contentHandler endElement:@"log" namespace:[self _namespace] rawName:@"log"]; [self->currentLog deleteCharactersInRange:r]; } - (NSString *)_namespace { if(!self->namespace) return @""; return self->namespace; } - (void)_writeString:(NSString *)_s { unsigned len; if ((len = [_s length]) == 0) return; if (len == 1) { unichar c[2]; [_s getCharacters:&(c[0])]; c[1] = '\0'; [self->contentHandler characters:&(c[0]) length:1]; } else { unichar *ca; ca = calloc(len + 1, sizeof(unichar)); [_s getCharacters:ca]; ca[len] = 0; [self->contentHandler characters:ca length:len]; if (ca) free(ca); } } @end /* ChangeLogSaxDriver */ SOPE/sope-xml/ChangeLogSaxDriver/GNUmakefile0000644000000000000000000000101715004363604017617 0ustar rootroot# GNUstep makefile include ../../config.make include $(GNUSTEP_MAKEFILES)/common.make -include ../../Version -include ./Version BUNDLE_NAME = ChangeLogSaxDriver BUNDLE_EXTENSION = .sax BUNDLE_INSTALL_DIR = ${SOPE_SAXDRIVERS}/ ChangeLogSaxDriver_OBJC_FILES = \ ChangeLogSaxDriver.m \ NSString+Extensions.m \ NSCalendarDate+Extensions.m ChangeLogSaxDriver_RESOURCE_FILES = bundle-info.plist default.locale -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/bundle.make -include GNUmakefile.postamble SOPE/sope-xml/ChangeLogSaxDriver/ChangeLog0000644000000000000000000000056715004363604017330 0ustar rootroot2005-08-16 Helge Hess * v4.5.1 * install into SaxObjC framework Resources when being used with OSX * ChangeLogSaxDriver.m: fixed a gcc 4.0 warning 2004-12-14 Marcus Mueller * ChangeLogSaxDriver.xcode: minor fixes 2004-12-07 Marcus Mueller * ChangeLog: created (v4.5.0) SOPE/sope-xml/ChangeLogSaxDriver/common.h0000644000000000000000000000205415004363604017210 0ustar rootroot/* Copyright (C) 2004 Marcus Mueller This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __ChangeLogSaxDriver_common_H_ #define __ChangeLogSaxDriver_common_H_ #import #include #include #include #endif /* __ChangeLogSaxDriver_common_H_ */ SOPE/sope-xml/ChangeLogSaxDriver/AUTHORS0000644000000000000000000000005315004363604016614 0ustar rootrootMarcus Mueller SOPE/sope-xml/ChangeLogSaxDriver/COPYING0000644000000000000000000005530315004363604016607 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS SOPE/sope-xml/ChangeLogSaxDriver/fhs.make0000644000000000000000000000121215004363604017161 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib/ FHS_SAX_DIR=$(FHS_LIB_DIR)sope-$(MAJOR_VERSION).$(MINOR_VERSION)/saxdrivers/ fhs-sax-dirs :: $(MKDIRS) $(FHS_SAX_DIR) move-bundles-to-fhs :: fhs-sax-dirs @echo "moving bundles $(BUNDLE_INSTALL_DIR) to $(FHS_SAX_DIR) .." for i in $(BUNDLE_NAME); do \ j="$(FHS_SAX_DIR)/$${i}$(BUNDLE_EXTENSION)"; \ if test -d $$j; then rm -r $$j; fi; \ mv "$(BUNDLE_INSTALL_DIR)/$${i}$(BUNDLE_EXTENSION)" $$j; \ done move-to-fhs :: move-bundles-to-fhs after-install :: move-to-fhs endif SOPE/sope-xml/ChangeLogSaxDriver/README0000644000000000000000000000337515004363604016436 0ustar rootrootOverview ======== ChangeLogSaxDriver is a SAX driver for reading, well, ChangeLogs. Generated XML ============= A ChangeLog like this: --- snip --- 2004-11-22 Helge Hess * v4.5.97 * WOContext.m: move some categories into main class implementation * WORequestHandler.m: bind default logger to WODebuggingEnabled 2004-11-21 Helge Hess * WODirectActionRequestHandler.m: minor code cleanups (v4.5.96) --- snap --- gets tranformed into this: --- snip --- Helge Hess v4.5.97 WOContext.m: move some categories into main class implementation WORequestHandler.m: bind default logger to WODebuggingEnabled "Helge Hess" WODirectActionRequestHandler.m: minor code cleanups (v4.5.96) --- snap --- Notes ===== The generated date stamps follow the w3.org recommendation at http://www.w3.org/TR/NOTE-datetime. Specifically, this is the format described as "complete date plus hours, minutes and seconds", with timezone set to 'Zulu' (GMT). If the original format didn't contain timezone information, the resulting timezone is set to GMT. If the original format didn't contain time information, the resulting time information is set to 12:00:00. SOPE/sope-xml/ChangeLogSaxDriver/NSString+Extensions.h0000644000000000000000000000226615004363604021567 0ustar rootroot/* Copyright (C) 2004 Marcus Mueller This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __ChangeLogSaxDriver_NSString_Extensions_H_ #define __ChangeLogSaxDriver_NSString_Extensions_H_ #import @interface NSString (ChangeLogSaxDriverExtensions) - (BOOL)parseDate:(NSCalendarDate **)_date andAuthor:(NSString **)_author; - (void)getRealName:(NSString **)_realName andEmail:(NSString **)_email; @end #endif /* __ChangeLogSaxDriver_NSString_Extensions_H_ */ SOPE/sope-xml/ChangeLogSaxDriver/GNUmakefile.postamble0000644000000000000000000000015715004363604021610 0ustar rootroot# aftermath after-all :: @(cp bundle-info.plist \ $(GNUSTEP_BUILD_DIR)/$(BUNDLE_NAME)$(BUNDLE_EXTENSION)) SOPE/sope-xml/ChangeLogSaxDriver/Version0000644000000000000000000000004415004363604017114 0ustar rootroot# Version file SUBMINOR_VERSION:=1 SOPE/sope-xml/ChangeLogSaxDriver/version.plist0000644000000000000000000000072315004363604020312 0ustar rootroot BuildVersion 12 CFBundleVersion 1.0 ProductBuildVersion 7K571 ProjectName DevToolsWizardTemplates SourceVersion 3870000 SOPE/sope-xml/ChangeLogSaxDriver/COPYRIGHT0000644000000000000000000000010615004363604017036 0ustar rootrootCopyright (C) 2004 Marcus Mueller Contact: znek@mulle-kybernetik.com SOPE/sope-xml/ChangeLogSaxDriver/NSCalendarDate+Extensions.h0000644000000000000000000000241115004363604022620 0ustar rootroot/* Copyright (C) 2004 Marcus Mueller This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __ChangeLogSaxDriver_NSCalendarDate_Extensions_H_ #define __ChangeLogSaxDriver_NSCalendarDate_Extensions_H_ #import @interface NSCalendarDate (ChangeLogSaxDriverExtensions) /* see http://www.w3.org/TR/NOTE-datetime */ /* this is Complete date plus hours, minutes and seconds, with timezone set to 'Zulu', i.e. 1994-11-05T13:15:30Z */ - (NSString *)w3OrgDateTimeRepresentation; @end #endif /* __ChangeLogSaxDriver_NSCalendarDate_Extensions_H_ */ SOPE/sope-xml/ChangeLogSaxDriver/default.locale0000644000000000000000000000072215004363604020354 0ustar rootroot{ NSLocaleCode = "en"; /* ISO 639-1 */ NSLanguageCode = "eng"; /* ISO 639-2 */ NSParentContext = ""; NSMonthNameArray = (January, February, March, April, May, June, July, August, September, October, November, December); NSShortMonthNameArray = (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec); NSShortWeekDayNameArray = (Sun, Mon, Tue, Wed, Thu, Fri, Sat); NSWeekDayNameArray = (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday); } SOPE/sope-xml/ChangeLogSaxDriver/GNUmakefile.preamble0000644000000000000000000000153715004363604021414 0ustar rootroot# compilation settings ifeq ($(frameworks),yes) BUNDLE_INSTALL_DIR := $(FRAMEWORK_INSTALL_DIR)/SaxObjC.framework/Resources/SaxDrivers/ endif SOPE_ROOT=../.. SOPE_OBJ_ROOT=$(GNUSTEP_BUILD_DIR)/$(SOPE_ROOT) ADDITIONAL_INCLUDE_DIRS += \ -I$(SOPE_ROOT)/sope-xml \ -I$(SOPE_ROOT)/sope-core/NGExtensions # dependencies ifneq ($(frameworks),yes) BUNDLE_LIBS += -lSaxObjC $(libxml_LIBS) else BUNDLE_LIBS += -framework SaxObjC $(libxml_LIBS) endif ADDITIONAL_BUNDLE_LIBS += $(BUNDLE_LIBS) # library/framework search pathes DEP_DIRS = ../SaxObjC ../../sope-core/NGExtensions ifneq ($(frameworks),yes) ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),\ -L$(GNUSTEP_BUILD_DIR)/$(dir)/$(GNUSTEP_OBJ_DIR_NAME)) else ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir)) endif SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib SOPE/sope-xml/ChangeLogSaxDriver/Info.plist0000644000000000000000000000134515004363604017521 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable ChangeLogSaxDriver CFBundleIconFile CFBundleIdentifier com.mulle-kybernetik.znek.ChangeLogSaxDriver CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleSignature ???? CFBundleVersion 4.5 NSPrincipalClass SOPE/sope-xml/ChangeLogSaxDriver/NSCalendarDate+Extensions.m0000644000000000000000000000265015004363604022632 0ustar rootroot/* Copyright (C) 2004 Marcus Mueller This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSCalendarDate+Extensions.h" @implementation NSCalendarDate (ChangeLogSaxDriverExtensions) /* set to 'Zulu', i.e. 1994-11-05T13:15:30Z */ - (NSString *)w3OrgDateTimeRepresentation { static NSTimeZone *zulu = nil; NSCalendarDate *date; NSString *desc; if(!zulu) zulu = [[NSTimeZone timeZoneForSecondsFromGMT:0] retain]; date = [self copy]; [date setTimeZone:zulu]; desc = [NSString stringWithFormat:@"%04d-%02d-%02dT%02d:%02d:%02dZ", [date yearOfCommonEra], [date monthOfYear], [date dayOfMonth], [date hourOfDay], [date minuteOfHour], [date secondOfMinute]]; [date release]; return desc; } @end SOPE/sope-xml/ChangeLogSaxDriver/NSString+Extensions.m0000644000000000000000000001305115004363604021566 0ustar rootroot/* Copyright (C) 2004 Marcus Mueller This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSString+Extensions.h" #include "common.h" @implementation NSString (ChangeLogSaxDriverExtensions) typedef struct { unsigned minLength; unsigned offset; BOOL hasTime; BOOL hasTimeZone; NSString *format; } dateFormatTest; static dateFormatTest formats[] = { { 24, 4, YES, NO, @"%b %d %H:%M:%S %Y" }, { 10, 0, NO, NO, @"%Y-%m-%d" }, { 12, 0, NO, NO, @"%b %d, %Y" }, { 13, 0, NO, NO, @"%b %d, %Y" }, { 15, 5, NO, NO, @"%b %d %Y" }, { 16, 0, NO, NO, @"%a %b %d %Y" }, { 23, 3, YES, NO, @"%b %d %H:%M:%S %Y" }, { 24, 4, YES, NO, @"%d %b %Y %H:%M:%S" }, { 25, 4, YES, NO, @"%b %d %H:%M:%S %Y" }, { 25, 4, YES, NO, @"%B %d %H:%M:%S %Y" }, { 28, 4, YES, YES, @"%b %d %H:%M:%S %Z %Y" }, { 30, 0, YES, YES, @"%a %b %d %H:%M:%S %Z %Y" }, { 0, 0, NO, NO, nil } /* end marker */ }; typedef struct { unsigned minLength; unsigned start; unsigned stop; unsigned contAt; BOOL hasTime; BOOL hasTimeZone; NSString *format; } complexDateFormatTest; static complexDateFormatTest complexFormats[] = { { 28, 4, 20, 24, YES, NO, @"%b %d %H:%M:%S %Y" }, { 29, 4, 20, 25, YES, NO, @"%b %d %H:%M:%S %Y" }, { 29, 4, 20, 24, YES, NO, @"%b %d %H:%M:%S %Y" }, { 0, 0, 0, 0, NO, NO, nil } /* end marker */ }; - (BOOL)parseDate:(NSCalendarDate **)_date andAuthor:(NSString **)_author { static NSTimeZone *gmt = nil; static NSDictionary *locale = nil; NSString *s, *format; NSCalendarDate *date; NSRange r; unsigned i, endLoc, len; BOOL hasTime, hasTimeZone; if(!gmt) { NSBundle *bundle; NSString *path; gmt = [[NSTimeZone timeZoneForSecondsFromGMT:0] retain]; bundle = [NSBundle bundleForClass:[self class]]; path = [bundle pathForResource:@"default" ofType:@"locale"]; if(path != nil) { locale = [[NSDictionary dictionaryWithContentsOfFile:path] retain]; } } date = nil; endLoc = 0, i = 0; len = [self length]; /* perform basic tests */ while((endLoc = formats[i].minLength) != 0 && endLoc < len) { r = NSMakeRange(formats[i].offset, endLoc - formats[i].offset); s = [self substringWithRange:r]; format = formats[i].format; date = [NSCalendarDate dateWithString:s calendarFormat:format locale:locale]; if(date) { hasTime = formats[i].hasTime; hasTimeZone = formats[i].hasTimeZone; break; } i++; } if(!date) { /* perform complex tests */ i = 0; while((endLoc = complexFormats[i].minLength) != 0 && endLoc < len) { r = NSMakeRange(complexFormats[i].start, complexFormats[i].stop - complexFormats[i].start); s = [self substringWithRange:r]; r = NSMakeRange(complexFormats[i].contAt, endLoc - complexFormats[i].contAt); s = [NSString stringWithFormat:@"%@%@", s, [self substringWithRange:r]]; format = complexFormats[i].format; date = [NSCalendarDate dateWithString:s calendarFormat:format locale:locale]; if(date) { hasTime = complexFormats[i].hasTime; hasTimeZone = complexFormats[i].hasTimeZone; break; } i++; } } if(date) { if(!hasTimeZone && !hasTime) date = [NSCalendarDate dateWithYear:[date yearOfCommonEra] month:[date monthOfYear] day:[date dayOfMonth] hour:12 minute:0 second:0 timeZone:gmt]; else if(!hasTimeZone) [date setTimeZone:gmt]; else if(!hasTime) date = [date hour:12 minute:0]; *_author = [self substringFromIndex:endLoc]; } else { *_author = nil; } *_date = date; return (date != nil) ? YES : NO; } - (void)getRealName:(NSString **)_realName andEmail:(NSString **)_email { NSRange r; NSString *s; s = [self stringByTrimmingSpaces]; r = [s rangeOfString:@"<"]; if(r.length == 0) { *_realName = s; *_email = nil; return; } if(r.location != 0) { NSString *rn; rn = [s substringToIndex:r.location]; *_realName = [rn stringByTrimmingTailSpaces]; } else { *_realName = @""; } s = [s substringFromIndex:NSMaxRange(r)]; s = [s stringByTrimmingTailSpaces]; s = [s substringToIndex:[s length] - 1]; *_email = s; } @end SOPE/sope-xml/COPYING0000644000000000000000000006130315004363604013125 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-xml/README0000644000000000000000000000050615004363604012750 0ustar rootrootSKYRiX Libraries for XML Processing =================================== This directory contains libraries for processing XML files and other tagged file formats like HTML, iCalendar, PYX or STX using Objective-C. For more information, please follow up on the webpage: http://www.opengroupware.org/en/devs/sope/skyrix_xml/ SOPE/sope-xml/DOM/0000755000000000000000000000000015004363604012506 5ustar rootrootSOPE/sope-xml/DOM/NSObject+DOM.m0000644000000000000000000000206315004363604014747 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" @implementation NSObject(DOMNode) - (id)_domNodeBeforeNode:(id)_node { return nil; } - (id)_domNodeAfterNode:(id)_node { return nil; } - (void)_domNodeForgetParentNode:(id)_parent { } - (void)_domNodeRegisterParentNode:(id)_parent { } @end /* NSObject(DOMNode) */ SOPE/sope-xml/DOM/NSObject+StringValue.m0000644000000000000000000000226215004363604016574 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" @implementation NSObject(StringValue) - (NSString *)stringValue { return [self description]; } @end /* NSObject(StringValue) */ @implementation NSString(StringValue) - (NSString *)stringValue { return self; } @end /* NSObject(StringValue) */ @implementation NSMutableString(StringValue) - (NSString *)stringValue { return [[self copy] autorelease]; } @end /* NSObject(StringValue) */ SOPE/sope-xml/DOM/DOMCharacterData.m0000644000000000000000000000512215004363604015712 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMCharacterData.h" #include "common.h" @implementation NGDOMCharacterData - (id)initWithString:(NSString *)_s { if ((self = [super init])) { self->data = [_s copy]; } return self; } - (void)dealloc { [self->data release]; [super dealloc]; } /* attributes */ - (void)setData:(NSString *)_data { id old = self->data; self->data = [_data copy]; [old release]; } - (NSString *)data { return self->data; } - (NSUInteger)length { return [self->data length]; } /* operations */ - (NSString *)substringData:(NSUInteger)_offset count:(NSUInteger)_count { NSRange r; r.location = _offset; r.length = _count; return [[self data] substringWithRange:r]; } - (void)appendData:(NSString *)_data { id old; old = self->data; self->data = old ? [old stringByAppendingString:_data] : _data; [old release]; } - (void)insertData:(NSString *)_data offset:(NSUInteger)_offset { [self doesNotRecognizeSelector:_cmd]; } - (void)deleteData:(NSUInteger)_offset count:(NSUInteger)_count { NSRange r; id new, old; r.location = _offset; r.length = _count; new = [self->data substringWithRange:r]; old = self->data; self->data = [new copy]; [old release]; } - (void)replaceData:(NSUInteger)_offset count:(NSUInteger)_c with:(NSString *)_s { [self doesNotRecognizeSelector:_cmd]; } /* parent node */ - (void)_domNodeRegisterParentNode:(id)_parent { self->parent = _parent; } - (void)_domNodeForgetParentNode:(id)_parent { if (_parent == self->parent) /* the node's parent was deallocated */ self->parent = nil; } - (id)parentNode { return self->parent; } /* QPValues */ - (NSException *)setQueryPathValue:(id)_value { [self setData:[_value stringValue]]; return nil; } - (id)queryPathValue { return [self data]; } @end /* NGDOMCharacterData(QPValues) */ SOPE/sope-xml/DOM/DOMTreeWalker.h0000644000000000000000000000355215004363604015271 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMTreeWalker_H__ #define __DOMTreeWalker_H__ #import #include @class NSArray; @interface NGDOMTreeWalker : NSObject { id root; unsigned long whatToShow; id filter; BOOL expandEntityReferences; id currentNode; /* cache state */ NSArray *visibleChildren; } /* attributes */ - (id)root; - (unsigned long)whatToShow; - (id)filter; - (BOOL)expandEntityReferences; - (void)setCurrentNode:(id)_node; - (id)currentNode; /* operations */ - (id)parentNode; - (id)firstChild; - (id)lastChild; - (id)previousSibling; - (id)nextSibling; - (id)previousNode; - (id)nextNode; @end @interface NGDOMTreeWalker(PrivateCtors) /* use DOMDocument(DocumentTraversal) for constructing DOMTreeWalker's ! */ - (id)initWithRootNode:(id)_rootNode whatToShow:(unsigned long)_whatToShow filter:(id)_filter expandEntityReferences:(BOOL)_flag; @end #endif /* __DOMTreeWalker_H__ */ SOPE/sope-xml/DOM/DOMBuilderFactory.m0000644000000000000000000000554515004363604016153 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMBuilderFactory.h" #include #include #include #include "common.h" @implementation DOMBuilderFactory static id factory = nil; + (id)standardDOMBuilderFactory { if (factory == nil) factory = [[self alloc] init]; return factory; } /* primary method */ - (id)createDOMBuilderWithXmlReader:(id)_r { DOMSaxBuilder *builder; if (_r == nil) return nil; builder = [[DOMSaxBuilder alloc] initWithXMLReader:_r]; return [builder autorelease]; } /* reader constructors */ - (SaxXMLReaderFactory *)readerFactory { return [SaxXMLReaderFactory standardXMLReaderFactory]; } - (id)createDOMBuilder { id reader; if ((reader = [[self readerFactory] createXMLReader]) == nil) { NSLog(@"%s:%i: could not create default DOM builder " @"because no SAX default reader could be constructed.", __PRETTY_FUNCTION__, __LINE__); return nil; } return [self createDOMBuilderWithXmlReader:reader]; } - (id)createDOMBuilderWithName:(NSString *)_name { id reader; if ((reader = [[self readerFactory] createXMLReaderWithName:_name]) == nil) { NSLog(@"%s:%i: could not create DOM builder '%@' " @"because no SAX reader named '%@' could be constructed.", __PRETTY_FUNCTION__, __LINE__, _name, _name); return nil; } return [self createDOMBuilderWithXmlReader:reader]; } - (id)createDOMBuilderForMimeType:(NSString *)_mtype { id reader; reader = [[self readerFactory] createXMLReaderForMimeType:_mtype]; if (reader == nil) { NSLog(@"%s:%i: could not create DOM builder for MIME type '%@' " @"because no SAX proper reader could be constructed.", __PRETTY_FUNCTION__, __LINE__, _mtype); return nil; } return [self createDOMBuilderWithXmlReader:reader]; } - (NSArray *)availableDOMBuilders { return [NSArray arrayWithObject:@"DOMSaxBuilder"]; } @end /* DOMBuilderFactory */ SOPE/sope-xml/DOM/DOMBuilderFactory.h0000644000000000000000000000303715004363604016140 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMBuilderFactory_H__ #define __DOMBuilderFactory_H__ #import #include /* To get a reader for HTML files: reader = [factory createDOMBuilderForMimeType:@"text/html"]; for XML files: reader = [factory createDOMBuilderForMimeType:@"text/xml"]; a specific reader: reader = [factory createDOMBuilderWithName:@"libxmlSAXDriver"]; */ @class NSDictionary; @interface DOMBuilderFactory : NSObject { } + (id)standardDOMBuilderFactory; - (id)createDOMBuilder; - (id)createDOMBuilderWithName:(NSString *)_name; - (id)createDOMBuilderForMimeType:(NSString *)_mtype; - (NSArray *)availableDOMBuilders; @end #endif /* __DOMBuilderFactory_H__ */ SOPE/sope-xml/DOM/DOMImplementation.h0000644000000000000000000000313215004363604016203 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMImplementation_H__ #define __DOMImplementation_H__ #import @class NSString; @interface NGDOMImplementation : NSObject { Class elementClass; Class textNodeClass; Class attrClass; } - (id)createDocumentWithName:(NSString *)_qname namespaceURI:(NSString *)_uri documentType:(id)_doctype; - (id)createDocumentType:(NSString *)_qname publicId:(NSString *)_pubId systemId:(NSString *)_sysId; @end @interface NGDOMImplementation(PrivateClassRegistry) - (Class)domElementClass; - (Class)domElementNSClass; - (Class)domDocumentFragmentClass; - (Class)domTextNodeClass; - (Class)domCommentClass; - (Class)domCDATAClass; - (Class)domProcessingInstructionClass; - (Class)domAttributeClass; - (Class)domAttributeNSClass; - (Class)domEntityReferenceClass; @end #endif /* __DOMImplementation_H__ */ SOPE/sope-xml/DOM/DOMNode.m0000644000000000000000000001733015004363604014115 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include "common.h" NSString *DOMNodeName(id _node) { switch ([_node nodeType]) { case DOM_ATTRIBUTE_NODE: return [(id)_node name]; case DOM_CDATA_SECTION_NODE: return @"#cdata-section"; case DOM_COMMENT_NODE: return @"#comment"; case DOM_DOCUMENT_NODE: return @"#document"; case DOM_DOCUMENT_FRAGMENT_NODE: return @"#document-fragment"; case DOM_ELEMENT_NODE: return [(id)_node tagName]; case DOM_PROCESSING_INSTRUCTION_NODE: return [(id)_node target]; case DOM_TEXT_NODE: return @"#text"; case DOM_DOCUMENT_TYPE_NODE: case DOM_ENTITY_NODE: case DOM_ENTITY_REFERENCE_NODE: case DOM_NOTATION_NODE: default: NSLog(@"ERROR: unknown node type %i !", [_node nodeType]); return nil; } } NSString *DOMNodeValue(id _node) { switch ([_node nodeType]) { case DOM_ATTRIBUTE_NODE: return [_node value]; case DOM_CDATA_SECTION_NODE: case DOM_COMMENT_NODE: case DOM_TEXT_NODE: return [(id)_node data]; case DOM_DOCUMENT_NODE: case DOM_DOCUMENT_FRAGMENT_NODE: case DOM_ELEMENT_NODE: return nil; case DOM_PROCESSING_INSTRUCTION_NODE: return [(id)_node data]; case DOM_DOCUMENT_TYPE_NODE: case DOM_ENTITY_NODE: case DOM_ENTITY_REFERENCE_NODE: case DOM_NOTATION_NODE: default: NSLog(@"ERROR: unknown node type %i !", [_node nodeType]); return nil; } } @implementation NGDOMNode - (void)_domNodeRegisterParentNode:(id)_parent { } - (void)_domNodeForgetParentNode:(id)_parent { } /* owner */ - (IDOMDocument)ownerDocument { id node; for (node = [self parentNode]; node; node = [node parentNode]) { if ([node nodeType] == DOM_DOCUMENT_NODE) return node; if ([node nodeType] == DOM_DOCUMENT_FRAGMENT_NODE) return node; } return nil; } /* attributes */ - (DOMNodeType)nodeType { return DOM_UNKNOWN_NODE; } - (NSString *)nodeName { return DOMNodeName(self); } - (NSString *)nodeValue { return DOMNodeValue(self); } - (id)subclassResponsibility:(SEL)_sel { [self doesNotRecognizeSelector:_sel]; return nil; } - (NSString *)localName { /* introduced in DOM level 2 */ return [self subclassResponsibility:_cmd]; } - (NSString *)namespaceURI { /* introduced in DOM level 2 */ return [self subclassResponsibility:_cmd]; } - (void)setPrefix:(NSString *)_prefix { /* introduced in DOM level 2 */ [self subclassResponsibility:_cmd]; } - (NSString *)prefix { /* introduced in DOM level 2 */ return [self subclassResponsibility:_cmd]; } /* element attributes */ - (id)attributes { /* returns a NamedNodeList */ return [self subclassResponsibility:_cmd]; } /* modification */ - (BOOL)_isValidChildNode:(id)_node { return NO; } - (id)removeChild:(id)_node { return nil; } - (id)appendChild:(id)_node { return nil; } /* navigation */ - (id)parentNode { return [self subclassResponsibility:_cmd]; } - (id)previousSibling { NGDOMNode *parent; if ((parent = (NGDOMNode *)[self parentNode]) == nil) return nil; if (parent == nil) return nil; if (![parent respondsToSelector:@selector(_domNodeBeforeNode:)]) return nil; return [parent _domNodeBeforeNode:self]; } - (id)nextSibling { NGDOMNode *parent; if ((parent = (NGDOMNode *)[self parentNode]) == nil) return nil; if (parent == nil) return nil; if (![parent respondsToSelector:@selector(_domNodeBeforeNode:)]) return nil; return [parent _domNodeAfterNode:self]; } - (id)childNodes { return nil; } - (BOOL)hasChildNodes { return NO; } - (id)firstChild { return nil; } - (id)lastChild { return nil; } /* key/value coding */ - (id)valueForUndefinedKey:(NSString *)_key { /* default is to raise an exception, we just return nil */ return nil; } /* description */ - (NSString *)description { return [NSString stringWithFormat: @"<0x%p[%@]: name=%@ parent=%@ type=%i #children=%"PRIuPTR">", self, NSStringFromClass([self class]), [self nodeName], [[self parentNode] nodeName], [self nodeType], [self hasChildNodes] ? [[self childNodes] length] : 0]; } @end /* NGDOMNode */ #include "DOMXMLOutputter.h" #include "DOMCharacterData.h" @implementation NGDOMNode(Additions) - (NSString *)nodeTypeString { switch ([self nodeType]) { case DOM_ATTRIBUTE_NODE: return @"attribute"; case DOM_CDATA_SECTION_NODE: return @"cdata-section"; case DOM_COMMENT_NODE: return @"comment"; case DOM_DOCUMENT_NODE: return @"document"; case DOM_DOCUMENT_FRAGMENT_NODE: return @"document-fragment"; case DOM_ELEMENT_NODE: return @"element"; case DOM_PROCESSING_INSTRUCTION_NODE: return @"processing-instruction"; case DOM_TEXT_NODE: return @"text"; case DOM_DOCUMENT_TYPE_NODE: return @"document-type"; case DOM_ENTITY_NODE: return @"entity"; case DOM_ENTITY_REFERENCE_NODE: return @"entity-reference"; case DOM_NOTATION_NODE: return @"notation"; default: return @"unknown"; } } - (NSString *)xmlStringValue { DOMXMLOutputter *out; NSMutableString *s; NSString *r; s = [[NSMutableString alloc] initWithCapacity:1024]; out = [[DOMXMLOutputter alloc] init]; [out outputNode:self to:s]; [out release]; r = [s copy]; [s release]; return [r autorelease]; } - (NSData *)xmlDataValue { return [[self xmlStringValue] dataUsingEncoding:NSUTF8StringEncoding]; } - (NSString *)textValue { NSMutableString *s; s = [NSMutableString stringWithCapacity:256]; switch ([self nodeType]) { case DOM_ELEMENT_NODE: case DOM_DOCUMENT_NODE: case DOM_ATTRIBUTE_NODE: if ([self hasChildNodes]) { id children; unsigned i, count; children = [self childNodes]; for (i = 0, count = [children count]; i < count; i++) { NSString *cs; cs = [[children objectAtIndex:i] textValue]; if (cs) [s appendString:cs]; } } break; case DOM_TEXT_NODE: case DOM_COMMENT_NODE: case DOM_CDATA_SECTION_NODE: [s appendString:[(id)self data]]; break; default: return nil; } return [[s copy] autorelease]; } @end /* NGDOMNode(Additions) */ @implementation NSArray(DOMNodeList) - (unsigned)length { return [self count]; } @end /* NSObject(DOMNodeList) */ SOPE/sope-xml/DOM/DOMEntity.h0000644000000000000000000000221715004363604014475 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMEntity_H__ #define __DOMEntity_H__ #include @class NSString; @interface NGDOMEntity : NGDOMNodeWithChildren { } /* attributes */ - (NSString *)publicId; - (NSString *)systemId; - (NSString *)notationName; /* node */ @end @interface NGDOMEntity(PrivateCtors) /* use DOMDocument for constructing DOMEntity's ! */ @end #endif /* __DOMEntity_H__ */ SOPE/sope-xml/DOM/DOMSaxBuilder.h0000644000000000000000000000230715004363604015263 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMSaxBuilder_H__ #define __DOMSaxBuilder_H__ #import #include @class NSString, NSData; @interface DOMSaxBuilder : NSObject < DOMBuilder > { id parser; id sax; } - (id)initWithXMLReader:(id)_saxParser; - (id)initWithXMLReaderForMimeType:(id)_mimeType; - (id)buildFromContentsOfFile:(NSString *)_path; - (id)buildFromData:(NSData *)_data; @end #endif /* __DOMSaxBuilder_H__ */ SOPE/sope-xml/DOM/DOMEntity.m0000644000000000000000000000336415004363604014506 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMEntity.h" #include "common.h" @implementation NGDOMEntity /* attributes */ - (NSString *)publicId { [self doesNotRecognizeSelector:_cmd]; return nil; } - (NSString *)systemId { [self doesNotRecognizeSelector:_cmd]; return nil; } - (NSString *)notationName { [self doesNotRecognizeSelector:_cmd]; return nil; } /* node */ - (DOMNodeType)nodeType { return DOM_ENTITY_NODE; } - (BOOL)_isValidChildNode:(id)_node { switch ([_node nodeType]) { case DOM_ELEMENT_NODE: case DOM_PROCESSING_INSTRUCTION_NODE: case DOM_COMMENT_NODE: case DOM_TEXT_NODE: case DOM_CDATA_SECTION_NODE: case DOM_ENTITY_REFERENCE_NODE: return YES; default: return NO; } } - (id)attributes { return nil; } /* parent node */ - (id)parentNode { return nil; } - (id)nextSibling { return nil; } - (id)previousSibling { return nil; } @end /* NGDOMEntity */ SOPE/sope-xml/DOM/DOMDocumentBuilder.h0000644000000000000000000000170115004363604016303 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMDocumentBuilder_H__ #define __DOMDocumentBuilder_H__ #include @protocol DOMDocumentBuilder @end #endif /* __DOMDocumentBuilder_H__ */ SOPE/sope-xml/DOM/DOMBuilder.h0000644000000000000000000000243215004363604014606 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMBuilder_H__ #define __DOMBuilder_H__ #import #include /* A protocol which defines the behaviour of DOM builders (classes which build DOM trees from some kind of resource). */ @protocol DOMBuilder /* parsing */ - (id)buildFromSource:(id)_source; - (id)buildFromSource:(id)_source systemId:(NSString *)_sysId; - (id)buildFromSystemId:(NSString *)_sysId; @end #endif /* __DOMBuilder_H__ */ SOPE/sope-xml/DOM/DOMTreeWalker.m0000644000000000000000000001614515004363604015300 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "common.h" @implementation NGDOMTreeWalker - (id)initWithRootNode:(id)_rootNode whatToShow:(unsigned long)_whatToShow filter:(id)_filter expandEntityReferences:(BOOL)_flag { NSAssert(_rootNode, @"missing root-node !"); if ((self = [super init])) { self->root = [_rootNode retain]; self->whatToShow = _whatToShow; self->filter = [_filter retain]; self->expandEntityReferences = _flag; [self setCurrentNode:_rootNode]; } return self; } - (void)dealloc { [self->visibleChildren release]; [self->currentNode release]; [self->root release]; [self->filter release]; [super dealloc]; } /* attributes */ - (id)root { return self->root; } - (unsigned long)whatToShow { return self->whatToShow; } - (id)filter { return self->filter; } - (BOOL)expandEntityReferences { return self->expandEntityReferences; } - (void)setCurrentNode:(id)_node { if (_node == self->currentNode) /* same node */ return; ASSIGN(self->currentNode, _node); /* clear state caches */ [self->visibleChildren release]; self->visibleChildren = nil; } - (id)currentNode { return self->currentNode; } /* internals */ - (BOOL)_shouldShowNode:(id)_node { if (self->whatToShow == DOM_SHOW_ALL) return YES; switch([_node nodeType]) { case DOM_ATTRIBUTE_NODE: return (self->whatToShow & DOM_SHOW_ATTRIBUTE) != 0 ? YES : NO; case DOM_CDATA_SECTION_NODE: return (self->whatToShow & DOM_SHOW_CDATA_SECTION) != 0 ? YES : NO; case DOM_COMMENT_NODE: return (self->whatToShow & DOM_SHOW_COMMENT) != 0 ? YES : NO; case DOM_DOCUMENT_NODE: return (self->whatToShow & DOM_SHOW_DOCUMENT) != 0 ? YES : NO; case DOM_DOCUMENT_FRAGMENT_NODE: return (self->whatToShow & DOM_SHOW_DOCUMENT_FRAGMENT) != 0 ? YES : NO; case DOM_ELEMENT_NODE: return (self->whatToShow & DOM_SHOW_ELEMENT) != 0 ? YES : NO; case DOM_PROCESSING_INSTRUCTION_NODE: return (self->whatToShow & DOM_SHOW_PROCESSING_INSTRUCTION) != 0 ? YES:NO; case DOM_TEXT_NODE: return (self->whatToShow & DOM_SHOW_TEXT) != 0 ? YES : NO; case DOM_DOCUMENT_TYPE_NODE: return (self->whatToShow & DOM_SHOW_DOCUMENT_TYPE) != 0 ? YES : NO; case DOM_ENTITY_NODE: return (self->whatToShow & DOM_SHOW_ENTITY) != 0 ? YES : NO; case DOM_ENTITY_REFERENCE_NODE: return (self->whatToShow & DOM_SHOW_ENTITY_REFERENCE) != 0 ? YES : NO; case DOM_NOTATION_NODE: return (self->whatToShow & DOM_SHOW_NOTATION) != 0 ? YES : NO; default: return YES; } } - (BOOL)_isVisibleNode:(id)_node { if (![self _shouldShowNode:_node]) return NO; if (self->filter) return [self->filter acceptNode:_node] == DOM_FILTER_ACCEPT ? YES : NO; return YES; } - (unsigned short)_navTypeOfNode:(id)_node { if (![self _shouldShowNode:_node]) return DOM_FILTER_SKIP; if (self->filter) return [self->filter acceptNode:_node] == DOM_FILTER_ACCEPT ? YES : NO; return DOM_FILTER_ACCEPT; } - (NSArray *)_ensureVisibleChildren { static NSArray *emptyArray = nil; id children; unsigned count; if (self->visibleChildren) return self->visibleChildren; children = [[self currentNode] childNodes]; if ((count = [children count]) > 0) { unsigned i; NSMutableArray *ma; ma = [[NSMutableArray alloc] initWithCapacity:(count + 1)]; for (i = 0; i < count; i++) { id childNode; childNode = [children objectAtIndex:i]; if ([self _isVisibleNode:childNode]) [ma addObject:childNode]; } self->visibleChildren = [ma copy]; [ma release]; ma = nil; } else { if (emptyArray == nil) emptyArray = [[NSArray alloc] init]; self->visibleChildren = [emptyArray retain]; } return self->visibleChildren; } - (BOOL)_hasVisibleChildren { return [[self _ensureVisibleChildren] count] > 0 ? YES : NO; } - (id)_visibleChildren { return [self _ensureVisibleChildren]; } - (id)_firstVisibleChild { NSArray *a = [self _ensureVisibleChildren]; if ([a count] == 0) return nil; return [a objectAtIndex:0]; } - (id)_lastVisibleChild { NSArray *a = [self _ensureVisibleChildren]; unsigned count; if ((count = [a count]) == 0) return nil; return [a objectAtIndex:(count - 1)]; } - (id)_visibleParentNode { id node; for (node = [[self currentNode] parentNode]; node; node =[node parentNode]) { if ([self _isVisibleNode:node]) return node; if (node == [self root]) /* do not step above root */ break; } return nil; } - (id)_nextVisibleSibling { id node; for (node = [(id)[self currentNode] nextSibling]; node != nil; node = [node nextSibling]) { if ([self _isVisibleNode:node]) return node; } return nil; } - (id)_previousVisibleSibling { id node; for (node = [(id)[self currentNode] previousSibling]; node != nil; node = [node previousSibling]) { if ([self _isVisibleNode:node]) return node; } return nil; } /* operations */ - (id)parentNode { id parent; if ((parent = [self _visibleParentNode])) { [self setCurrentNode:parent]; return parent; } else return nil; } - (id)firstChild { if ([self _hasVisibleChildren]) { id child; child = [self _firstVisibleChild]; [self setCurrentNode:child]; return child; } else return nil; } - (id)lastChild { if ([self _hasVisibleChildren]) { id child; child = [self _lastVisibleChild]; [self setCurrentNode:child]; return child; } else return nil; } - (id)previousSibling { id node; if ((node = [self _previousVisibleSibling])) { [self setCurrentNode:node]; return node; } else return nil; } - (id)nextSibling { id node; if ((node = [self _nextVisibleSibling])) { [self setCurrentNode:node]; return node; } else return nil; } - (id)previousNode { [self doesNotRecognizeSelector:_cmd]; return nil; } - (id)nextNode { [self doesNotRecognizeSelector:_cmd]; return nil; } @end /* NGDOMTreeWalker */ SOPE/sope-xml/DOM/EDOM.h0000644000000000000000000000174315004363604013410 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOM_EDOM_H__ #define __DOM_EDOM_H__ /* Extended Objective-C specific DOM stuff */ #include #include #include #endif /* __DOM_EDOM_H__ */ SOPE/sope-xml/DOM/NSObject+StringValue.h0000644000000000000000000000175515004363604016575 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOM_NSObject_StringValue_H__ #define __DOM_NSObject_StringValue_H__ #import @interface NSObject(StringValue) - (NSString *)stringValue; @end #endif /* __DOM_NSObject_StringValue_H__ */ SOPE/sope-xml/DOM/DOMNamedNodeMap.h0000644000000000000000000000155715004363604015517 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMNamedNodeMap_H__ #define __DOMNamedNodeMap_H__ #endif /* __DOMNamedNodeMap_H__ */ SOPE/sope-xml/DOM/GNUmakefile0000644000000000000000000000412715004363604014564 0ustar rootroot# GNUstep makefile include ../../config.make include ../common.make ifneq ($(frameworks),yes) LIBRARY_NAME = libDOM else FRAMEWORK_NAME = DOM DOM_RESOURCE_FILES += Version endif libDOM_PCH_FILE = common.h DOM_PCH_FILE = common.h LDOM_HEADER_FILES += \ DOM.h \ DOMProtocols.h \ DOMAttribute.h \ DOMCDATASection.h \ DOMCharacterData.h \ DOMComment.h \ DOMDocument.h \ DOMDocumentFragment.h \ DOMDocumentType.h \ DOMElement.h \ DOMEntity.h \ DOMEntityReference.h \ DOMImplementation.h \ DOMNode.h \ DOMNotation.h \ DOMProcessingInstruction.h \ DOMBuilder.h \ DOMBuilderFactory.h \ EDOM_HEADER_FILES += \ EDOM.h \ DOMNode+Enum.h \ DOMNode+QueryPath.h \ DOMQueryPathExpression.h \ libDOM_HEADER_FILES = \ $(LDOM_HEADER_FILES) \ $(EDOM_HEADER_FILES) \ DOMSaxBuilder.h \ DOMSaxHandler.h \ DOMText.h \ DOMXMLOutputter.h \ DOMPYXOutputter.h \ DOMNodeWalker.h \ DOMNamedNodeMap.h \ DOM_CORE_OBJC_FILES = \ NSObject+StringValue.m \ DOMAttribute.m \ DOMCDATASection.m \ DOMCharacterData.m \ DOMComment.m \ DOMDocument.m \ DOMElement.m \ DOMEntity.m \ DOMEntityReference.m \ DOMImplementation.m \ DOMNode.m \ DOMNodeWithChildren.m \ DOMNotation.m \ DOMProcessingInstruction.m \ DOMText.m \ DOMDocument+factory.m \ DOMDocumentType.m \ DOM+JS.m \ DOMBuilderFactory.m \ EDOM_OBJC_FILES = \ DOMNode+Enum.m \ DOMNode+QueryPath.m \ DOMQueryPathExpression.m \ NSObject+QPEval.m \ DOMNode+QPEval.m \ DOM_TRAVERSAL_OBJC_FILES = \ DOMTreeWalker.m \ DOMNodeFilter.m \ DOMNodeIterator.m \ libDOM_OBJC_FILES = \ DOMSaxBuilder.m \ DOMSaxHandler.m \ DOMXMLOutputter.m \ DOMPYXOutputter.m \ DOMNodeWalker.m \ NSObject+DOM.m \ $(EDOM_OBJC_FILES) \ $(DOM_CORE_OBJC_FILES) \ $(DOM_TRAVERSAL_OBJC_FILES) \ # building -include GNUmakefile.preamble ifneq ($(FHS_INSTALL_ROOT),) GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include endif ifneq ($(frameworks),yes) include $(GNUSTEP_MAKEFILES)/library.make else include $(GNUSTEP_MAKEFILES)/framework.make endif -include GNUmakefile.postamble SOPE/sope-xml/DOM/DOMDocument.m0000644000000000000000000002213215004363604015002 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include "DOMSaxBuilder.h" #include "DOMNode+QueryPath.h" #include "common.h" //#define PROF_DEALLOC 1 @implementation NGDOMDocument + (id)documentFromData:(NSData *)_data { id builder; builder = [[[DOMSaxBuilder alloc] init] autorelease]; return [builder buildFromData:_data]; } + (id)documentFromString:(NSString *)_string { return [self documentFromData: [_string dataUsingEncoding:NSISOLatin1StringEncoding]]; } + (id)documentFromURI:(NSString *)_uri { id builder; builder = [[[DOMSaxBuilder alloc] init] autorelease]; return [builder buildFromContentsOfFile:_uri]; } - (id)initWithName:(NSString *)_qname namespaceURI:(NSString *)_uri documentType:(id)_doctype dom:(NGDOMImplementation *)_dom { self->dom = [_dom retain]; self->qname = [_qname copy]; self->uri = [_uri copy]; self->doctype = [_doctype retain]; return self; } - (void)dealloc { #if PROF_DEALLOC NSDate *start = [NSDate date]; #endif [self->errors release]; [self->warnings release]; [self->dom release]; [self->qname release]; [self->uri release]; [self->doctype release]; [super dealloc]; #if PROF_DEALLOC printf("%s: %.3fs\n", __PRETTY_FUNCTION__, [NSDate timeIntervalSinceDate:start]); #endif } /* errors/warnings */ - (void)addErrors:(NSArray *)_errors { if (self->errors == nil) self->errors = [_errors copy]; else { NSArray *tmp; tmp = self->errors; self->errors = [[tmp arrayByAddingObjectsFromArray:_errors] copy]; [tmp release]; } } - (void)addWarnings:(NSArray *)_errors { if (self->warnings == nil) self->warnings = [_errors copy]; else { NSArray *tmp; tmp = self->warnings; self->warnings = [[tmp arrayByAddingObjectsFromArray:_errors] copy]; [tmp release]; } } /* attributes */ - (id)doctype { return self->doctype; } - (NGDOMImplementation *)implementation { return self->dom; } - (id)documentElement { id children; unsigned i, count; if ((children = [self childNodes]) == nil) return nil; for (i = 0, count = [children count]; i < count; i++) { id node; node = [children objectAtIndex:i]; if ([node nodeType] == DOM_ELEMENT_NODE) return node; } return nil; } /* node */ - (BOOL)_isValidChildNode:(id)_node { switch ([_node nodeType]) { case DOM_ELEMENT_NODE: case DOM_PROCESSING_INSTRUCTION_NODE: case DOM_COMMENT_NODE: case DOM_DOCUMENT_TYPE_NODE: return YES; default: return NO; } } - (DOMNodeType)nodeType { return DOM_DOCUMENT_NODE; } - (id)attributes { return nil; } - (IDOMDocument)ownerDocument { return nil; } - (id)parentNode { /* document cannot be nested */ return nil; } - (id)nextSibling { /* document cannot be nested */ return nil; } - (id)previousSibling { /* document cannot be nested */ return nil; } - (void)_walk_getElementsByTagName:(id)_walker { id node; node = [_walker currentNode]; if ([node nodeType] != DOM_ELEMENT_NODE) return; if (![[node tagName] isEqualToString: [(NSArray *)[_walker context] objectAtIndex:0]]) /* tagname doesn't match */ return; [[(NSArray *)[_walker context] objectAtIndex:1] addObject:node]; } - (void)_walk_getElementsByTagNameAddAll:(id)_walker { id node; node = [_walker currentNode]; if ([node nodeType] != DOM_ELEMENT_NODE) return; [(NSMutableArray *)[_walker context] addObject:node]; } - (id)getElementsByTagName:(NSString *)_tagName { /* introduced in DOM2, should return a *live* list ! */ NSMutableArray *array; NGDOMNodePreorderWalker *walker; SEL sel; id ctx; if (![self hasChildNodes]) return nil; if (_tagName == nil) return nil; array = [NSMutableArray arrayWithCapacity:4]; if ([_tagName isEqualToString:@"*"]) { _tagName = nil; ctx = array; sel = @selector(_walk_getElementsByTagNameAddAll:); } else { ctx = [NSArray arrayWithObjects:_tagName, array, nil]; sel = @selector(_walk_getElementsByTagName:); } walker = [[NGDOMNodePreorderWalker alloc] initWithTarget:self selector:sel context:ctx]; [walker walkNode:self]; [walker release]; walker = nil; return [[array copy] autorelease]; } - (id)getElementsByTagName:(NSString *)_tagName namespaceURI:(NSString *)_uri { [self doesNotRecognizeSelector:_cmd]; return nil; } - (id)getElementById:(NSString *)_eid { /* Introduced in DOM2 Note: The DOM implementation must have information that says which attributes are of type ID. Attributes with the name "ID" are not of type ID unless so defined. Implementations that do not know whether attributes are of type ID or not are expected to return null. */ return nil; } /* factory */ - (Class)domElementClass { return [self->dom domElementClass]; } - (Class)domElementNSClass { return [self->dom domElementNSClass]; } - (Class)domDocumentFragmentClass { return [self->dom domDocumentFragmentClass]; } - (Class)domTextNodeClass { return [self->dom domTextNodeClass]; } - (Class)domCommentClass { return [self->dom domCommentClass]; } - (Class)domCDATAClass { return [self->dom domCDATAClass]; } - (Class)domProcessingInstructionClass { return [self->dom domProcessingInstructionClass]; } - (Class)domAttributeClass { return [self->dom domAttributeClass]; } - (Class)domAttributeNSClass { return [self->dom domAttributeNSClass]; } - (Class)domEntityReferenceClass { return [self->dom domEntityReferenceClass]; } - (id)createElement:(NSString *)_tagName { id elem; elem = [[[self domElementClass] alloc] initWithTagName:_tagName]; return [elem autorelease]; } - (id)createElement:(NSString *)_tagName namespaceURI:(NSString *)_uri { id elem; elem = [[[self domElementNSClass] alloc] initWithTagName:_tagName namespaceURI:_uri]; return [elem autorelease]; } - (id)createDocumentFragment { id elem; elem = [[[self domDocumentFragmentClass] alloc] init]; return [elem autorelease]; } - (id)createTextNode:(NSString *)_data { id elem; elem = [[[self domTextNodeClass] alloc] initWithString:_data]; return [elem autorelease]; } - (id)createComment:(NSString *)_data { id elem; elem = [[[self domCommentClass] alloc] initWithString:_data]; return [elem autorelease]; } - (id)createCDATASection:(NSString *)_data { id elem; elem = [[[self domCDATAClass] alloc] initWithString:_data]; return [elem autorelease]; } - (id)createProcessingInstruction: (NSString *)_target data:(NSString *)_data { id elem; elem = [[[self domProcessingInstructionClass] alloc] initWithTarget:_target data:_data]; return [elem autorelease]; } - (id)createAttribute:(NSString *)_name { id elem; elem = [[[self domAttributeClass] alloc] initWithName:_name]; return [elem autorelease]; } - (id)createAttribute:(NSString *)_name namespaceURI:(NSString *)_uri { id elem; elem = [[[self domAttributeNSClass] alloc] initWithName:_name namespaceURI:_uri]; return [elem autorelease]; } - (id)createEntityReference:(NSString *)_name { id elem; elem = [[[self domEntityReferenceClass] alloc] initWithName:_name]; return [elem autorelease]; } /* QPValues */ - (NSException *)setQueryPathValue:(id)_value { return [NSException exceptionWithName:@"QueryPathEvalException" reason:@"cannot set query-path value on DOMDocument !" userInfo:nil]; } - (id)queryPathValue { return [self documentElement]; } /* Key/Value Coding */ - (id)valueForKey:(NSString *)_key { if ([_key hasPrefix:@"/"]) return [self lookupQueryPath:_key]; return [super valueForKey:_key]; } @end /* NGDOMDocument */ SOPE/sope-xml/DOM/DOMQueryPathExpression.h0000644000000000000000000000446715004363604017234 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMQueryPathExpression_H__ #define __DOMQueryPathExpression_H__ #import @class NSString, NSArray; @interface DOMQueryPathExpression : NSObject /* Syntax: First the QueryPath is separated into path components, then the path components are evaluated: '-' - placed in front of the path component, makes the search flat '/' - select DOM root node (usually the document-element) '.' - select current node '..' - select DOM parent node '*' - select all child elements (either deep or non-deep) '!x' - evaluate keypath 'x' on node '?x' - lookup processing instruction 'x' (either deep or non-deep) '@x' - lookup attribute 'x', if x is '*', select all attributes (the map) x may contain a ':' for namespace queries any other string: select a child-node with the string as the name. Samples: "./head/title" - lookup the 'title' node contained in the 'head' child node "./@name" - lookup the 'name' attribute of the current node "./?blah" - lookup the PI 'blah' starting with the current node "./!values" - call 'valueForKey:@"values"' on the current node "/-title" - flat search for 'title' element */ + (id)queryPathWithString:(NSString *)_string; + (id)queryPathWithComponents:(NSArray *)_string; + (NSArray *)queryPathComponentsOfString:(NSString *)_path; - (id)evaluateWithNode:(id)_node; // DEPRECATED !!! - (id)evaluateWithNodeList:(id)_nodeList; @end #endif /* __DOMQueryPathExpression_H__ */ SOPE/sope-xml/DOM/DOMSaxBuilder.m0000644000000000000000000001055315004363604015272 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMSaxBuilder.h" #include "DOMSaxHandler.h" #include "DOMAttribute.h" #include "DOMDocument.h" #include "common.h" #include @implementation DOMSaxBuilder - (id)initWithXMLReader:(id)_saxParser { if (_saxParser == nil) { [self release]; return nil; } ASSIGN(self->parser, _saxParser); self->sax = [[DOMSaxHandler alloc] init]; [self->parser setContentHandler:self->sax]; [self->parser setDTDHandler:self->sax]; [self->parser setErrorHandler:self->sax]; [self->parser setProperty:@"http://xml.org/sax/properties/declaration-handler" to:self->sax]; [self->parser setProperty:@"http://xml.org/sax/properties/lexical-handler" to:self->sax]; return self; } - (id)initWithXMLReaderForMimeType:(id)_mimeType { id reader; reader = [[SaxXMLReaderFactory standardXMLReaderFactory] createXMLReaderForMimeType:_mimeType]; if (reader == nil) { NSLog(@"%s: could not find a SAX driver bundle for type '%@' !\n", __PRETTY_FUNCTION__, _mimeType); [self release]; return nil; } return [self initWithXMLReader:reader]; } - (id)init { id reader; reader = [[SaxXMLReaderFactory standardXMLReaderFactory] createXMLReader]; if (reader == nil) { NSLog(@"%s: could not load a SAX driver bundle !\n", __PRETTY_FUNCTION__); [self release]; return nil; } return [self initWithXMLReader:reader]; } - (void)dealloc { [self->parser release]; [self->sax release]; [super dealloc]; } /* DOM building */ - (id)_docAfterParsing { id doc; doc = [[self->sax document] retain]; [(id)doc addErrors:[self->sax errors]]; [(id)doc addWarnings:[self->sax warnings]]; [self->sax clear]; return [doc autorelease]; } - (id)buildFromData:(NSData *)_data { NSAutoreleasePool *pool; id doc; if (_data == nil) { NSLog(@"missing data .."); return nil; } NSAssert(self->sax, @"missing sax handler .."); NSAssert(self->parser, @"missing XML parser .."); pool = [[NSAutoreleasePool alloc] init]; { [self->parser parseFromSource:_data]; doc = [[self _docAfterParsing] retain]; } [pool release]; #if DEBUG NSAssert(self->sax, @"missing sax handler .."); NSAssert(self->parser, @"missing XML parser .."); #endif return [doc autorelease]; } - (id)buildFromContentsOfFile:(NSString *)_path { NSAutoreleasePool *pool; id doc; if ([_path length] == 0) return nil; pool = [[NSAutoreleasePool alloc] init]; { _path = [@"file://" stringByAppendingString:_path]; [self->parser parseFromSystemId:_path]; doc = [[self _docAfterParsing] retain]; } [pool release]; return [doc autorelease]; } - (id)buildFromSource:(id)_source systemId:(NSString *)_sysId { NSAutoreleasePool *pool; id doc; if (_source == nil) return nil; pool = [[NSAutoreleasePool alloc] init]; { [self->parser parseFromSource:_source systemId:_sysId]; doc = [[self _docAfterParsing] retain]; } [pool release]; return [doc autorelease]; } - (id)buildFromSource:(id)_source { return [self buildFromSource:_source systemId:nil]; } - (id)buildFromSystemId:(NSString *)_sysId { NSAutoreleasePool *pool; id doc; if ([_sysId length] == 0) return nil; pool = [[NSAutoreleasePool alloc] init]; { [self->parser parseFromSystemId:_sysId]; doc = [[self _docAfterParsing] retain]; } [pool release]; return [doc autorelease]; } @end /* DOMSaxBuilder */ SOPE/sope-xml/DOM/ChangeLog0000644000000000000000000001500315004363604014257 0ustar rootroot2006-09-20 Helge Hess * DOMPYXOutputter.m, DOMXMLOutputter.m: use -UTF8String instead of -cString on Apple machines to avoid a warning (v4.9.24) 2006-09-20 Helge Hess * GNUmakefile.preamble: filter out -O% flags for files using exception handlers, enable -O2 per default (v4.5.23) 2006-07-03 Helge Hess * fixed gcc 4.1 warnings, use %p for pointer formats (v4.5.22) 2006-06-04 Helge Hess * DOMElement.m: added missing -localName implementation (v4.5.21) 2005-08-17 Helge Hess * GNUmakefile: removed duplicate definition of EDOM.h (v4.5.20) 2005-08-07 Helge Hess * DOMDocumentFragment.m: fixed some prototypes (v4.5.19) 2005-07-30 Helge Hess * DOMElement.m: evaluate KVC keys starting with a slash '/' as query path expressions (by stripping of the slash!), return an attribute node for keys starting with '@' (v4.5.18) * v4.5.17 * DOMDocument.m: evaluate KVC keys starting with a slash '/' as query path expressions * DOMNode.m: changed to return 'nil' for unknown KVC keys instead of raising an exception 2005-05-03 Helge Hess * DOMTreeWalker.m: fixed a MacOSX 10.4 warning (v4.5.16) * renamed most implementations from DOMxx to NGDOMxx to avoid linking issues with Tiger WebKit (still incomplete). Note that protocols are still the same, so 'real' DOM apps will continue to work ;-) (v4.5.15) 2005-04-23 Helge Hess * fixed loads of @protocol related gcc 4.0 warnings (v4.5.14) 2004-12-14 Marcus Mueller * DOM.xcode: minor cleanup 2004-09-22 Marcus Mueller * DOM.xcode: minor fixes 2004-09-21 Marcus Mueller * DOM.xcode: Fixed dependencies to resemble the make process more closely. Our aim should be to stick to the make process as closely as possible, so we shouldn't introduce dependencies in non-toplevel projects. 2004-08-29 Helge Hess * added hack to install the project in FHS locations - the library, its headers, the tools and the resources will be installed in FHS_INSTALL_ROOT if specified (eg make FHS_INSTALL_ROOT=/usr/local) (v4.3.13) 2004-08-26 Marcus Mueller * DOM.xcode: new Xcode project 2004-08-25 Helge Hess * DOMSaxHandler.m: do not print DOM parsing errors per default (consumers need to check the errors array) (v4.3.12) 2004-08-20 Helge Hess * moved to SOPE 4.3 (v4.3.11) 2004-06-09 Helge Hess * v4.2.10 * GNUmakefile.preamble: added prebinding info * GNUmakefile: moved preamble stuff to GNUmakefile.preamble, also build DOM.framework on non-libFoundation systems 2004-05-05 Marcus Mueller * GNUmakefile.preamble: added support for building with GNUSTEP_BUILD_DIR environment variable set for recent gnustep-make package. (v4.2.9) 2004-02-27 Helge Hess * DOMElement.m: added -description method to _DOMElementAttrNamedNodeMap class (v4.2.8) 2003-11-19 Helge Hess * GNUmakefile: removed autodoc target 2003-10-30 Helge Hess * DOMDocument.m, DOMElement.m DOMQueryPathExpression.m: fixed some Xcode warnings (v4.2.7) 2003-07-18 Helge Hess * DOMNode.m, DOMXMLOutputter.m: removed a warning on gstep-base, patch provided by Filip Van Raemdonck (v4.2.6) 2003-01-07 Helge Hess * common.h: removed dependency on FoundationExt on MacOSX (v4.2.5) Thu Jan 2 10:49:31 2003 Helge Hess * changes for MacOSX, does not use RETAIN macros anymore (methods are used), -doesNotRecognizeSelector: instead of -notImplemented (v4.2.4) 2002-09-28 Helge Hess * removed some compilation warnings (v4.2.3) 2002-06-11 Helge Hess * track positional information in elements Sun May 5 18:40:10 2002 Helge Hess * added DOMBuilderFactory to create DOMBuilder instances Thu May 2 12:43:12 2002 Helge Hess * DOMXMLOutputter.m: added protocols to output methods * changed to use -rangeOfString: instead of -indexOfString: Thu Apr 4 18:12:17 2002 Martin Spindler * DOMSaxHandler.m: added SubHandler category Tue Feb 12 20:48:41 2002 Helge Hess * made independend from EOControl/NGExtensions Tue Nov 13 16:16:26 2001 Helge Hess * DOMSaxBuilder.m: added SAX errors to DOM document * DOMDocument.m: ivars for storing errors/warnings * DOMSaxHandler.m: track error messages Mon Oct 22 09:54:03 2001 Helge Hess * removed special namespace variants of DOMAttribute/DOMElement Mon Oct 1 15:59:16 2001 Helge Hess * DOMSaxBuilder.h: create DOM builder by MIME-type Fri Sep 28 16:17:17 2001 Helge Hess * DOMElement.m: added -getElementsByTagName: * DOM+JS.m: added JS bindings for DOM objects * DOMElement.m: added JS bindings to (private) AttrNamedNodeMap class * DOMProtocols.h: added ObjC protocols for DOM types Thu Aug 23 12:03:41 2001 Helge Hess * DOMSaxBuilder.m: clear sax handler after parsing * DOMSaxHandler.m added method to clear handler Sat Aug 11 13:56:47 2001 Helge Hess * DOMSaxHandler.m: changed to use less -autorelease calls Tue Jul 3 16:26:26 2001 Helge Hess * DOMElement.m: allow * pattern in -hasAttribute:namespaceURI: Thu Jun 7 19:48:41 2001 Helge Hess * DOMNode+QueryPath.m: improved query-path parsing (namespaces made possible), fixed deep child element search Thu Mar 8 12:33:27 2001 Helge Hess * DOMDocument.m: fixed bug Fri Mar 2 20:10:27 2001 Helge Hess * DOMElement.m: added ms patch Fri Feb 23 13:26:39 2001 Helge Hess * DOMElement.m: added ms bugfix * DOMAttribute.m: improved -description Fri Feb 2 10:08:32 2001 Helge Hess * DOMNode+QueryPath.m: added partial support for NS in paths SOPE/sope-xml/DOM/common.h0000644000000000000000000000226515004363604014154 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOM_common_H__ #define __DOM_common_H__ #include #import #ifndef ASSIGN # define ASSIGN(object, value) \ ({id __object = (id)object; \ id __value = (id)value; \ if (__value != __object) { if (__value) [__value retain]; \ if (__object) [__object release]; \ object = __value;}}) #endif #endif /* __DOM_common_H__ */ SOPE/sope-xml/DOM/DOMProcessingInstruction.m0000644000000000000000000000460415004363604017606 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMProcessingInstruction.h" #include "common.h" @implementation NGDOMProcessingInstruction - (id)initWithTarget:(NSString *)_target data:(NSString *)_data { if ((self = [super init])) { self->target = [_target copy]; self->data = [_data copy]; } return self; } - (void)dealloc { [self->target release]; [self->data release]; [super dealloc]; } /* attributes */ - (NSString *)target { return self->target; } - (void)setData:(NSString *)_data { id old = self->data; self->data = [_data copy]; [old release]; } - (NSString *)data { return self->data; } /* node */ - (DOMNodeType)nodeType { return DOM_PROCESSING_INSTRUCTION_NODE; } - (id)attributes { return nil; } - (BOOL)_isValidChildNode:(id)_node { return NO; } - (BOOL)hasChildNodes { /* PI's have no children ! */ return NO; } - (id)childNodes { /* PI's have no children ! */ return nil; } - (id)appendChild:(id)_node { /* PI's have no children ! */ return nil; } /* parent node */ - (void)_domNodeRegisterParentNode:(id)_parent { self->parent = _parent; } - (void)_domNodeForgetParentNode:(id)_parent { if (_parent == self->parent) /* the node's parent was deallocated */ self->parent = nil; } - (id)parentNode { return self->parent; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"<0x%p[%@]: target=%@ data='%@'>", self, NSStringFromClass([self class]), [self target], [self data]]; } @end /* NGDOMProcessingInstruction */ SOPE/sope-xml/DOM/DOMEntityReference.m0000644000000000000000000000272115004363604016321 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMEntityReference.h" #include "common.h" @implementation NGDOMEntityReference - (id)initWithName:(NSString *)_name { self->name = [_name copy]; return self; } - (void)dealloc { [self->name release]; [super dealloc]; } - (DOMNodeType)nodeType { return DOM_ENTITY_REFERENCE_NODE; } - (id)attributes { return nil; } /* parent node */ - (void)_domNodeRegisterParentNode:(id)_parent { self->parent = _parent; } - (void)_domNodeForgetParentNode:(id)_parent { if (_parent == self->parent) /* the node's parent was deallocated */ self->parent = nil; } - (id)parentNode { return self->parent; } @end /* NGDOMEntityReference */ SOPE/sope-xml/DOM/DOMPYXOutputter.m0000644000000000000000000001275415004363604015651 0ustar rootroot/* Copyright (C) 2000-2009 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMPYXOutputter.h" #include "DOMDocument.h" #include "DOMElement.h" #include "common.h" @interface NGDOMPYXOutputter(Privates) - (void)outputNode:(id)_node to:(id)_target; - (void)outputNodeList:(id)_nodeList to:(id)_target; @end @implementation NGDOMPYXOutputter - (void)write:(NSString *)s to:(id)_target { #ifndef __APPLE__ printf("%s", [s cString]); #else printf("%s", [s UTF8String]); #endif } - (BOOL)currentElementPreservesWhitespace { return NO; } - (void)outputAttributeNode:(id)_attrNode ofNode:(id)_node to:(id)_target { [self write:@"A" to:_target]; [self write:[_attrNode name] to:_target]; [self write:@" " to:_target]; [self write:[_attrNode nodeValue] to:_target]; [self write:@"\n" to:_target]; } - (void)outputAttributeNodes:(id)_nodes ofNode:(id)_node to:(id)_target { unsigned i, count; if ((count = [_nodes length]) == 0) return; for (i = 0; i < count; i++) { [self outputAttributeNode:[_nodes objectAtIndex:i] ofNode:_node to:_target]; } } - (void)outputTextNode:(id)_node to:(id)_target { NSString *s; unsigned len; s = [_node data]; if ((len = [s length]) == 0) return; if ([s rangeOfString:@"\n"].length != 0) { s = [[s componentsSeparatedByString:@"\n"] componentsJoinedByString:@"\\n"]; } [self write:@"-" to:_target]; [self write:s to:_target]; [self write:@"\n" to:_target]; } - (void)outputCommentNode:(id)_node to:(id)_target { [self write:@"" to:_target]; if (![self currentElementPreservesWhitespace]) [self write:@"\n" to:_target]; } - (void)outputElementNode:(id)_node to:(id)_target { NSString *tagName; // NSString *ns; /* needs to declare namespaces !!! */ tagName = [_node tagName]; if ([[_node prefix] length] > 0) { NSString *p = [_node prefix]; p = [p stringByAppendingString:@":"]; tagName = [p stringByAppendingString:tagName]; // ns = [NSString stringWithFormat:@" xmlns:%@=\"%@\"", // [_node prefix], // [_node namespaceURI]]; } // else if ([[_node namespaceURI] length] > 0) { // ns = [NSString stringWithFormat:@" xmlns=\"%@\"", [_node namespaceURI]]; // } // else // ns = nil; [self write:@"(" to:_target]; [self write:tagName to:_target]; [self write:@"\n" to:_target]; [self outputAttributeNodes:[_node attributes] ofNode:_node to:_target]; if ([_node hasChildNodes]) [self outputNodeList:[_node childNodes] to:_target]; [self write:@")" to:_target]; [self write:tagName to:_target]; [self write:@"\n" to:_target]; } - (void)outputCDATA:(id)_node to:(id)_target { NSString *s; s = [_node data]; if ([s rangeOfString:@"\n"].length != 0) { /* escape newlines */ s = [[s componentsSeparatedByString:@"\n"] componentsJoinedByString:@"\\n"]; } [self write:@"-" to:_target]; [self write:s to:_target]; [self write:@"\n" to:_target]; } - (void)outputPI:(id)_node to:(id)_target { [self write:@"?" to:_target]; [self write:[_node target] to:_target]; [self write:@" " to:_target]; [self write:[_node data] to:_target]; [self write:@"\n" to:_target]; } - (void)outputNode:(id)_node to:(id)_target { switch ([_node nodeType]) { case DOM_ELEMENT_NODE: [self outputElementNode:_node to:_target]; break; case DOM_CDATA_SECTION_NODE: [self outputCDATA:_node to:_target]; break; case DOM_PROCESSING_INSTRUCTION_NODE: [self outputPI:_node to:_target]; break; case DOM_TEXT_NODE: [self outputTextNode:_node to:_target]; break; case DOM_COMMENT_NODE: [self outputCommentNode:_node to:_target]; break; default: NSLog(@"cannot output node %@", _node); break; } } - (void)outputNodeList:(id)_nodeList to:(id)_target { id children; unsigned i, count; children = _nodeList; for (i = 0, count = [children count]; i < count; i++) [self outputNode:[children objectAtIndex:i] to:_target]; } - (void)outputDocument:(id)_document to:(id)_target { if (![_document hasChildNodes]) return; NS_DURING [self outputNodeList:[_document childNodes] to:_target]; NS_HANDLER #ifndef __APPLE__ fprintf(stderr, "%s\n", [[localException description] cString]); #else fprintf(stderr, "%s\n", [[localException description] UTF8String]); #endif #if DEBUG abort(); #endif NS_ENDHANDLER; } @end /* DOMPYXOutputter */ SOPE/sope-xml/DOM/DOMSaxHandler.h0000644000000000000000000000277515004363604015263 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMSaxHandler_H__ #define __DOMSaxHandler_H__ #include @class NSMutableArray; @interface DOMSaxHandler : SaxDefaultHandler { id locator; BOOL inDTD; BOOL inCDATA; int maxErrorCount; NSMutableArray *errors; NSMutableArray *warnings; NSMutableArray *fatals; /* dom */ id dom; id document; int errorCount; /* dom building */ id currentElement; /* */ unsigned tagDepth; } - (id)initWithDOMImplementation:(id)_domImpl; /* access result */ - (id)document; - (void)clear; - (int)maxErrorCount; - (int)errorCount; - (int)fatalErrorCount; - (int)warningCount; - (NSArray *)warnings; - (NSArray *)errors; - (NSArray *)fatalErrors; @end #endif /* __DOMSaxHandler_H__ */ SOPE/sope-xml/DOM/DOM+JS.m0000644000000000000000000003170615004363604013622 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include "NSObject+StringValue.h" #include "common.h" /* Differences to DOM JavaScript Differences are due to JavaScript bridge retain-cycle issues with parent properties (properties are cached by the JS engine, while function return values are not) ... Node: original property | SKYRiX function parentNode | getParentNode() childNodes | getChildNodes() firstChild | getFirstChild() lastChild | getLastChild() previousSibling | getPreviousSibling() nextSibling | getNextSibling() attributes | getAttributes() ownerDocument | getOwnerDocument() Attr: ownerElement | getOwnerElement() Document: original property | SKYRiX function documentElement | getDocumentElement() */ @implementation NGDOMImplementation(JSSupport) - (id)_jsfunc_createDocument:(NSArray *)_args { NSString *nsuri = nil, *qname = nil, *doctype = nil; unsigned count; count = [_args count]; if (count > 0) nsuri = [[_args objectAtIndex:0] stringValue]; if (count > 1) qname = [[_args objectAtIndex:1] stringValue]; if (count > 2) doctype = [[_args objectAtIndex:2] stringValue]; return [self createDocumentWithName:qname namespaceURI:nsuri documentType:doctype]; } - (id)_jsfunc_createDocumentType:(NSArray *)_args { NSString *qname = nil, *pubId = nil, *sysId = nil; unsigned count; count = [_args count]; if (count > 0) qname = [[_args objectAtIndex:0] stringValue]; if (count > 1) pubId = [[_args objectAtIndex:1] stringValue]; if (count > 2) sysId = [[_args objectAtIndex:2] stringValue]; return [self createDocumentType:qname publicId:pubId systemId:sysId]; } @end /* NGDOMImplementation(JSSupport) */ @implementation NGDOMDocument(JSSupport) - (id)_jsprop_doctype { return [self doctype]; } - (id)_jsprop_implementation { return [self implementation]; } - (id)_jsfunc_getDocumentElement:(NSArray *)_args { return [self documentElement]; } /* lookup */ - (id)_jsfunc_getElementsByTagName:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; if (count == 1) return [self getElementsByTagName:[[_args objectAtIndex:0] stringValue]]; else { return [self getElementsByTagName:[[_args objectAtIndex:1] stringValue] namespaceURI:[[_args objectAtIndex:0] stringValue]]; } } - (id)_jsfunc_getElementsByTagNameNS:(NSArray *)_args { return [self _jsfunc_getElementsByTagName:_args]; } - (id)_jsfunc_getElementById:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; return [self getElementById:[[_args objectAtIndex:0] stringValue]]; } /* factory */ - (id)_jsfunc_createElement:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; if (count == 1) return [self createElement:[[_args objectAtIndex:0] stringValue]]; else { return [self createElement:[[_args objectAtIndex:1] stringValue] namespaceURI:[[_args objectAtIndex:0] stringValue]]; } } - (id)_jsfunc_createElementNS:(NSArray *)_args { return [self _jsfunc_createElement:_args]; } - (id)_jsfunc_createDocumentFragment:(NSArray *)_args { return [self createDocumentFragment]; } - (id)_jsfunc_createTextNode:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; return [self createTextNode:[[_args objectAtIndex:0] stringValue]]; } - (id)_jsfunc_createComment:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; return [self createComment:[[_args objectAtIndex:0] stringValue]]; } - (id)_jsfunc_createCDATASection:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; return [self createCDATASection:[[_args objectAtIndex:0] stringValue]]; } - (id)_jsfunc_createProcessingInstruction:(NSArray *)_args { unsigned count; if ((count = [_args count]) < 2) return nil; return [self createProcessingInstruction: [[_args objectAtIndex:0] stringValue] data:[[_args objectAtIndex:1] stringValue]]; } - (id)_jsfunc_createAttribute:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; if (count == 1) return [self createAttribute:[[_args objectAtIndex:0] stringValue]]; else { return [self createAttribute:[[_args objectAtIndex:1] stringValue] namespaceURI:[[_args objectAtIndex:0] stringValue]]; } } - (id)_jsfunc_createAttributeNS:(NSArray *)_args { return [self _jsfunc_createAttribute:_args]; } - (id)_jsfunc_createEntityReference:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; return [self createEntityReference:[[_args objectAtIndex:0] stringValue]]; } @end /* NGDOMDocument(JSSupport) */ @implementation NGDOMNode(JSSupport) - (NSString *)_jsprop_nodeName { return [self nodeName]; } - (NSString *)_jsprop_nodeValue { return [self nodeValue]; } - (NSNumber *)_jsprop_nodeType { return [NSNumber numberWithShort:[self nodeType]]; } - (NSString *)_jsprop_namespaceURI { return [self namespaceURI]; } - (NSString *)_jsprop_prefix { return [self prefix]; } - (NSString *)_jsprop_localName { return [self localName]; } - (id)_jsfunc_getParentNode:(NSArray *)_args { return [self parentNode]; } - (id)_jsfunc_getChildNodes:(NSArray *)_args { return [self childNodes]; } - (id)_jsfunc_getFirstChild:(NSArray *)_args { return [self firstChild]; } - (id)_jsfunc_getLastChild:(NSArray *)_args { return [self lastChild]; } - (id)_jsfunc_getPreviousSibling:(NSArray *)_args { return [self previousSibling]; } - (id)_jsfunc_getNextSibling:(NSArray *)_args { return [self nextSibling]; } - (id)_jsfunc_getAttributes:(NSArray *)_args { return [self attributes]; } - (id)_jsfunc_getOwnerDocument:(NSArray *)_args { return [self ownerDocument]; } - (NSNumber *)_jsfunc_hasChildNodes:(NSArray *)_args { return [NSNumber numberWithBool:[self hasChildNodes]]; } - (id)_jsfunc_normalize:(NSArray *)_args { return nil; } - (id)_jsfunc_appendChild:(NSArray *)_args { unsigned i, count; id last = nil; for (i = 0, count = [_args count]; i < count; i++) last = [self appendChild:[_args objectAtIndex:i]]; return last; } - (id)_jsfunc_removeChild:(NSArray *)_args { unsigned i, count; id last = nil; for (i = 0, count = [_args count]; i < count; i++) last = [self removeChild:[_args objectAtIndex:i]]; return last; } // #warning some JS DOMNode API missing @end /* NGDOMNode(JSSupport) */ @implementation NGDOMCharacterData(JSSupport) - (void)_jsprop_data:(NSString *)_data { _data = [_data stringValue]; [self setData:_data]; } - (NSString *)_jsprop_data { return [self data]; } - (NSNumber *)_jsprop_length { return [NSNumber numberWithInt:[self length]]; } - (NSString *)_jsfunc_substringData:(NSArray *)_args { unsigned count; if ((count = [_args count]) < 2) return nil; return [self substringData:[[_args objectAtIndex:0] intValue] count:[[_args objectAtIndex:1] intValue]]; } - (id)_jsfunc_appendData:(NSArray *)_args { unsigned i, count; for (i = 0, count = [_args count]; i < count; i++) [self appendData:[[_args objectAtIndex:i] stringValue]]; return self; } - (id)_jsfunc_insertData:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; if (count == 1) [self insertData:[[_args objectAtIndex:0] stringValue] offset:0]; else { [self insertData:[[_args objectAtIndex:0] stringValue] offset:[[_args objectAtIndex:1] intValue]]; } return self; } - (id)_jsfunc_deleteData:(NSArray *)_args { unsigned count; if ((count = [_args count]) < 2) return nil; [self deleteData:[[_args objectAtIndex:0] intValue] count:[[_args objectAtIndex:1] intValue]]; return self; } - (id)_jsfunc_replaceData:(NSArray *)_args { unsigned count; if ((count = [_args count]) < 3) return nil; [self replaceData:[[_args objectAtIndex:0] intValue] count:[[_args objectAtIndex:1] intValue] with:[[_args objectAtIndex:2] stringValue]]; return self; } @end /* NGDOMCharacterData(JSSupport) */ @implementation NGDOMAttribute(JSSupport) - (NSString *)_jsprop_name { return [self name]; } - (NSNumber *)_jsprop_specified { return [NSNumber numberWithBool:[self specified]]; } - (void)_jsprop_value:(NSString *)_value { [self setValue:[_value stringValue]]; } - (NSString *)_jsprop_value { return [self value]; } - (id)_jsfunc_getOwnerElement:(NSArray *)_args { return [self ownerElement]; } @end /* NGDOMAttribute(JSSupport) */ @implementation NGDOMElement(JSSupport) - (NSString *)_jsprop_tagName { return [self tagName]; } /* attributes */ - (NSString *)_jsfunc_getAttribute:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; return [self attribute:[[_args objectAtIndex:0] stringValue]]; } - (NSString *)_jsfunc_getAttributeNS:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; return [self attribute:[[_args objectAtIndex:1] stringValue] namespaceURI:[[_args objectAtIndex:0] stringValue]]; } - (id)_jsfunc_setAttribute:(NSArray *)_args { unsigned count; if ((count = [_args count]) < 2) return nil; [self setAttribute:[[_args objectAtIndex:0] stringValue] value:[[_args objectAtIndex:1] stringValue]]; return self; } - (id)_jsfunc_setAttributeNS:(NSArray *)_args { unsigned count; if ((count = [_args count]) < 3) return nil; [self setAttribute:[[_args objectAtIndex:1] stringValue] namespaceURI:[[_args objectAtIndex:0] stringValue] value:[[_args objectAtIndex:2] stringValue]]; return self; } - (id)_jsfunc_removeAttribute:(NSArray *)_args { unsigned i, count; for (i = 0, count = [_args count]; i < count; i++) [self removeAttribute:[[_args objectAtIndex:i] stringValue]]; return self; } - (id)_jsfunc_removeAttributeNS:(NSArray *)_args { unsigned count; if ((count = [_args count]) < 2) return nil; [self removeAttribute:[[_args objectAtIndex:1] stringValue] namespaceURI:[[_args objectAtIndex:0] stringValue]]; return self; } - (id)_jsfunc_getAttributeNode:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; return [[self attributes] namedItem:[[_args objectAtIndex:0] stringValue]]; } - (id)_jsfunc_setAttributeNode:(NSArray *)_args { unsigned i, count; id last = nil; for (i = 0, count = [_args count]; i < count; i++) last = [self setAttributeNode:[_args objectAtIndex:i]]; return last; } - (id)_jsfunc_removeAttributeNode:(NSArray *)_args { unsigned i, count; id last = nil; for (i = 0, count = [_args count]; i < count; i++) last = [self removeAttributeNode:[_args objectAtIndex:i]]; return last; } /* lookup */ - (id)_jsfunc_getElementsByTagName:(NSArray *)_args { unsigned count; if ((count = [_args count]) < 1) return nil; if (count == 1) return [self getElementsByTagName:[[_args objectAtIndex:0] stringValue]]; else { return [self getElementsByTagName:[[_args objectAtIndex:1] stringValue] namespaceURI:[[_args objectAtIndex:0] stringValue]]; } } - (id)_jsfunc_getElementsByTagNameNS:(NSArray *)_args { unsigned count; if ((count = [_args count]) < 2) return nil; return [self getElementsByTagName:[[_args objectAtIndex:1] stringValue] namespaceURI:[[_args objectAtIndex:0] stringValue]]; } @end /* NGDOMElement(JSSupport) */ @implementation NGDOMDocumentType(JSSupport) - (NSString *)_jsprop_name { return [self name]; } - (NSString *)_jsprop_publicId { return [self publicId]; } - (NSString *)_jsprop_systemId { return [self systemId]; } - (NSString *)_jsprop_internalSubset { return [self internalSubset]; } @end /* NGDOMDocumentType(JSSupport) */ @implementation NGDOMProcessingInstruction(JSSupport) - (NSString *)_jsprop_target { return [self target]; } - (void)_jsprop_data:(NSString *)_data { [self setData:[_data stringValue]]; } - (NSString *)_jsprop_data { return [self data]; } @end /* NGDOMProcessingInstruction(JSSupport) */ SOPE/sope-xml/DOM/DOMNode.h0000644000000000000000000000302615004363604014105 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMNode_H__ #define __DOMNode_H__ #import #include @class NSMutableArray, NSData; @class NGDOMDocument; @interface NGDOMNode : NSObject < DOMNode > { } @end @interface NGDOMNode(Additions) - (NSString *)nodeTypeString; - (NSString *)xmlStringValue; - (NSData *)xmlDataValue; - (NSString *)textValue; @end @interface NGDOMNodeWithChildren : NGDOMNode { @private NSMutableArray *childNodes; } @end @interface NSObject(DOMNodePrivate) - (id)_domNodeBeforeNode:(id)_node; - (id)_domNodeAfterNode:(id)_node; - (void)_domNodeRegisterParentNode:(id)_parentNode; - (void)_domNodeForgetParentNode:(id)_parentNode; @end NSString *DOMNodeName(id _node); NSString *DOMNodeValue(id _node); #endif /* __DOMNode_H__ */ SOPE/sope-xml/DOM/DOMNode+QueryPath.m0000644000000000000000000000255715004363604016040 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMNode+QueryPath.h" #include "DOMQueryPathExpression.h" #include "common.h" @implementation NGDOMNode(QueryPath) - (id)lookupPathComponents:(NSArray *)_path { DOMQueryPathExpression *expr; if (_path == nil) return nil; expr = [DOMQueryPathExpression queryPathWithComponents:_path]; return [expr evaluateWithNode:self]; } - (id)lookupQueryPath:(NSString *)_path { DOMQueryPathExpression *expr; if (_path == nil) return nil; expr = [DOMQueryPathExpression queryPathWithString:_path]; return [expr evaluateWithNode:self]; } @end /* DOMNode(QueryPath) */ SOPE/sope-xml/DOM/COPYING0000644000000000000000000006130315004363604013544 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-xml/DOM/fhs.make0000644000000000000000000000172215004363604014127 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) FHS_INCLUDE_DIR=$(FHS_INSTALL_ROOT)/include/ FHS_BIN_DIR=$(FHS_INSTALL_ROOT)/bin/ ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib64/ else FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib/ endif fhs-header-dirs :: $(MKDIRS) $(FHS_INCLUDE_DIR)$(libDOM_HEADER_FILES_INSTALL_DIR) move-headers-to-fhs :: fhs-header-dirs @echo "moving headers to $(FHS_INCLUDE_DIR) .." mv $(GNUSTEP_HEADERS)$(libDOM_HEADER_FILES_INSTALL_DIR)/*.h \ $(FHS_INCLUDE_DIR)$(libDOM_HEADER_FILES_INSTALL_DIR)/ NONFHS_LIBDIR="$(GNUSTEP_LIBRARIES)/$(GNUSTEP_TARGET_LDIR)/" NONFHS_LIBNAME="$(LIBRARY_NAME)$(LIBRARY_NAME_SUFFIX)$(SHARED_LIBEXT)" move-libs-to-fhs :: @echo "moving libs to $(FHS_LIB_DIR) .." mv $(NONFHS_LIBDIR)/$(NONFHS_LIBNAME)* $(FHS_LIB_DIR)/ move-to-fhs :: move-headers-to-fhs move-libs-to-fhs after-install :: move-to-fhs endif SOPE/sope-xml/DOM/DOMNodeWithChildren.m0000644000000000000000000001026615004363604016423 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "common.h" @implementation NGDOMNodeWithChildren - (void)dealloc { [self->childNodes makeObjectsPerformSelector: @selector(_domNodeForgetParentNode:) withObject:nil]; [self->childNodes release]; [super dealloc]; } - (void)_ensureChildNodes { if (self->childNodes == nil) self->childNodes = [[NSMutableArray alloc] init]; } - (BOOL)_isValidChildNode:(id)_node { return YES; } /* navigation */ - (id)childNodes { [self _ensureChildNodes]; /* casting NSMutableArray to DOMNodeList */ return (id)self->childNodes; } - (BOOL)hasChildNodes { return [self->childNodes count] > 0 ? YES : NO; } - (id)firstChild { return [self->childNodes count] > 0 ? [self->childNodes objectAtIndex:0] : nil; } - (id)lastChild { NSUInteger count; return (count = [self->childNodes count]) > 0 ? [self->childNodes objectAtIndex:(count - 1)] : nil; } /* modification */ - (id)removeChild:(id)_node { NSUInteger idx; if (self->childNodes == nil) /* this node has no childnodes ! */ return nil; if ((idx = [self->childNodes indexOfObject:_node]) == NSNotFound) /* given node is not a child of this node ! */ return nil; [[_node retain] autorelease]; [self->childNodes removeObjectAtIndex:idx]; [(id)_node _domNodeForgetParentNode:self]; return _node; } - (id)appendChild:(id)_node { if (_node == nil) /* adding a 'nil' node ?? */ return nil; if ([_node nodeType] == DOM_DOCUMENT_FRAGMENT_NODE) { id fragNodes; NSUInteger i, count; NSMutableArray *cache; fragNodes = [_node childNodes]; if ((count = [fragNodes count]) == 0) /* no nodes to add */ return nil; /* copy to cache, since 'childNodes' result is 'live' and appendChild modifies the tree */ cache = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) [cache addObject:[fragNodes objectAtIndex:i]]; /* append nodes (in reverse order [array implementation is assumed]) .. */ for (i = count = [cache count]; i > 0; i--) [self appendChild:[cache objectAtIndex:(i - 1)]]; } else { id oldParent; if ((oldParent = [_node parentNode])) [oldParent removeChild:_node]; [self _ensureChildNodes]; [self->childNodes addObject:_node]; [(id)_node _domNodeRegisterParentNode:self]; } /* return the node 'added' */ return _node; } /* sibling navigation */ - (id)_domNodeBeforeNode:(id)_node { NSUInteger idx; if ((idx = [self->childNodes indexOfObject:_node]) == NSNotFound) /* given node isn't a child of this node */ return nil; if (idx == 0) /* given node is the first child */ return nil; return [self->childNodes objectAtIndex:(idx - 1)]; } - (id)_domNodeAfterNode:(id)_node { NSUInteger idx, count; if ((count = [self->childNodes count]) == 0) /* this node has no children at all .. */ return nil; if ((idx = [self->childNodes indexOfObject:_node]) == NSNotFound) /* given node isn't a child of this node */ return nil; if (idx == (count - 1)) /* given node is the last child */ return nil; return [self->childNodes objectAtIndex:(idx + 1)]; } @end /* NGDOMNodeWithChildren */ SOPE/sope-xml/DOM/README0000644000000000000000000000264015004363604013370 0ustar rootrootHow to build a DOM tree ? ========================= 1. get a factory DOMBuilderFactory *factory = [DOMBuilderFactory standardDOMBuilderFactory]; 2. get a builder for your resource type id builder = [factory createDOMBuilderForMimeType:@"text/xml"]; 3. parse what you have: id document = [builder buildFromSource:@"myfile.xml"]; KVC === You can navigate the DOM tree with standard key/value coding. The NGDOMDocument will treat all KVC keys starting with a "/" as query path expressions. Samples: document.documentElement => root DOMElement document.documentElement.childNodes => NSArray containing the root children document./uid => DOMElement or array! matching 'uid' document./uid.textValue => text-value of 'uid' element element.@value.textValue => text-value of 'value' attribute of element element./subnode.textValue => lookup subnode (strips of the /) using QP Some info on classes ... ======================== Nodes with children Document DocumentFragment EntityReference Element Attr Entity Nodes without children DocumentType ProcessingInstruction Comment Text CDATASection Notation Nodes with parent DocumentType EntityReference Element ProcessingInstruction Comment Text CDATASection Nodes without parent Document DocumentFragment Attr Entity Notation SOPE/sope-xml/DOM/DOMNotation.h0000644000000000000000000000206015004363604015010 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMNotation_H__ #define __DOMNotation_H__ #include @interface NGDOMNotation : NGDOMNode { } /* attributes */ /* node */ @end @interface NGDOMNotation(PrivateCtors) /* use DOMDocument for constructing DOMNotation's ! */ @end #endif /* __DOMNotation_H__ */ SOPE/sope-xml/DOM/DOMNodeWalker.h0000644000000000000000000000263115004363604015254 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMNodeWalker_H__ #define __DOMNodeWalker_H__ #import @interface NGDOMNodeWalker : NSObject { id target; SEL selector; id ctx; BOOL isStopped; id rootNode; id currentParentNode; id currentNode; } - (id)initWithTarget:(id)_target selector:(SEL)_selector context:(id)_ctx; /* context */ - (id)context; - (id)rootNode; - (id)currentParentNode; - (id)currentNode; /* walking */ - (void)walkNode:(id)_node; - (void)stopWalking; @end @interface NGDOMNodePreorderWalker : NGDOMNodeWalker @end @interface NGDOMNodePostorderWalker : NGDOMNodeWalker @end #endif /* __DOMNodeWalker_H__ */ SOPE/sope-xml/DOM/DOMNodeFilter.m0000644000000000000000000000166215004363604015264 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMNodeFilter.h" @implementation NGDOMNodeFilter - (DOMNodeFilterType)acceptNode:(id)_node { return DOM_FILTER_ACCEPT; } @end /* NGDOMNodeFilter */ SOPE/sope-xml/DOM/DOMComment.h0000644000000000000000000000173415004363604014626 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMComment_H__ #define __DOMComment_H__ #include @class NSString; @interface NGDOMComment : NGDOMCharacterData < DOMComment > { } @end #endif /* __DOMComment_H__ */ SOPE/sope-xml/DOM/DOMNode+Enum.m0000644000000000000000000000341715004363604015016 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMNode+Enum.h" #include "common.h" @interface _DOMNodeParentNodeEnumerator : NSEnumerator { id currentNode; } + (id)enumeratorWithDOMNode:(id)_node; @end @implementation NSObject(DOMNodeEnum) - (NSEnumerator *)domParentNodeEnumerator { return [_DOMNodeParentNodeEnumerator enumeratorWithDOMNode: [(NGDOMNode *)self parentNode]]; } @end /* NSObject(DOMNodeEnum) */ @implementation NGDOMNode(Enum) - (NSEnumerator *)parentNodeEnumerator { return [self domParentNodeEnumerator]; } @end /* NGDOMNode(Enum) */ @implementation _DOMNodeParentNodeEnumerator + (id)enumeratorWithDOMNode:(id)_node { _DOMNodeParentNodeEnumerator *e; e = [self alloc]; e->currentNode = [_node retain]; return [e autorelease]; } - (void)dealloc { [self->currentNode release]; [super dealloc]; } - (id)nextObject { id old; old = self->currentNode; self->currentNode = [[old parentNode] retain]; return [old autorelease]; } @end /* _DOMNodeParentNodeEnumerator */ SOPE/sope-xml/DOM/DOMElement.h0000644000000000000000000000404215004363604014610 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMElement_H__ #define __DOMElement_H__ #include /* Why is there no removeAttributeNodeNS method? There is, but it's called removeAttributeNode. We needed both setAttributeNode and setAttributeNodeNS, because those functions use different rules to select which (if any) existing Attr the new one will replace. setAttributeNode bases this decision on the nodeName, while setAttributeNodeNS looks at the combination of namespaceURI and localname. However, when you remove a specific Attr Node, its nodeName, localname, and namespaceURI are ignored, and there's no need for a second method to support this. */ @class NSString, NSMutableDictionary, NSMutableArray; @interface NGDOMElement : NGDOMNodeWithChildren < DOMElement > { id parent; NSString *tagName; NSMutableDictionary *keyToAttribute; NSMutableArray *attributes; NSString *namespaceURI; NSString *prefix; /* positional info */ unsigned line; /* caches */ id attrNodeMap; } @end @interface NGDOMElement(PrivateCtors) /* use DOMDocument for constructing DOMElements ! */ - (id)initWithTagName:(NSString *)_tagName; - (id)initWithTagName:(NSString *)_tagName namespaceURI:(NSString *)_uri; @end #endif /* __DOMElement_H__ */ SOPE/sope-xml/DOM/DOMNodeIterator.h0000644000000000000000000000251315004363604015617 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMNodeIterator_H__ #define __DOMNodeIterator_H__ #import @interface NGDOMNodeIterator : NSObject { id root; unsigned long whatToShow; id filter; BOOL expandEntityReferences; /* position */ id lastNode; BOOL beforeFirst; BOOL afterLast; } /* attributes */ - (id)root; - (unsigned long)whatToShow; - (id)filter; - (BOOL)expandEntityReferences; /* operators */ - (id)nextNode; - (id)previousNode; - (void)detach; @end #endif /* __DOMNodeIterator_H__ */ SOPE/sope-xml/DOM/SxXML-DOM.graffle0000644000000000000000000016053215004363604015435 0ustar rootroot CanvasColor w 1.000000e+00 ColumnAlign 0 ColumnSpacing 5.400000e+01 GraphDocumentVersion 2 GraphicsList Bounds {{14, 14}, {67, 36}} Class ShapedGraphic FitText YES ID 1404 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-BoldOblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\b\fs48 \cf0 DOM} Bounds {{18, 549}, {167, 18}} Class ShapedGraphic ID 1403 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMQueryPathExpression.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMQueryPathExpression} Class Group Graphics Bounds {{18, 342}, {126, 18}} Class ShapedGraphic ID 1386 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 DOMCharacterData} Class Group Graphics Bounds {{216, 378}, {99, 18}} Class ShapedGraphic ID 1388 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 DOMComment} Bounds {{105, 378}, {95, 18}} Class ShapedGraphic ID 1389 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMComment.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMComment} Class LineGraphic Head ID 1389 ID 1390 Points {216, 387} {200, 387} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1388 ID 1387 Class Group Graphics Bounds {{261, 342}, {126, 18}} Class ShapedGraphic ID 1392 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 DOMCDATASection} Bounds {{261, 306}, {124, 18}} Class ShapedGraphic ID 1393 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMCDATASection.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMCDATASection} ID 1391 Class Group Graphics Bounds {{171, 342}, {63, 18}} Class ShapedGraphic ID 1395 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 DOMText} Bounds {{171, 306}, {63, 18}} Class ShapedGraphic ID 1396 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMText.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMText} ID 1394 Bounds {{19, 306}, {125, 18}} Class ShapedGraphic ID 1397 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMCharacterData.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMCharacterData} Class LineGraphic Head ID 1389 ID 1398 Points {90.375, 324} {143.625, 378} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1397 Class LineGraphic Head ID 1393 ID 1399 Points {323.75, 342} {323.25, 324} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1392 Class LineGraphic Head ID 1393 ID 1400 Points {234, 315} {261, 315} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1396 Class LineGraphic Head ID 1396 ID 1401 Points {202.5, 342} {202.5, 324} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1395 Class LineGraphic Head ID 1396 ID 1402 Points {144, 315} {171, 315} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1397 ID 1385 Class Group Graphics Bounds {{22, 108}, {122, 18}} Class ShapedGraphic ID 1382 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMDocumentType.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMDocumentType} Bounds {{22, 81}, {158, 18}} Class ShapedGraphic ID 1383 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMProcessingInstruction.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMProcessingInstruction} Bounds {{22, 135}, {122, 18}} Class ShapedGraphic ID 1384 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMNotation.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMNotation} ID 1381 Class Group Graphics Bounds {{252, 36}, {72, 18}} Class ShapedGraphic ID 1379 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 DOMNode} Bounds {{162, 36}, {72, 18}} Class ShapedGraphic ID 1380 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMNode.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMNode} ID 1378 Bounds {{189, 243}, {167, 18}} Class ShapedGraphic ID 1377 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMEntity.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMEntity} Bounds {{18, 522}, {167, 18}} Class ShapedGraphic ID 1376 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMTreeWalker.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMTreeWalker} Class Group Graphics Bounds {{275, 423}, {81, 18}} Class ShapedGraphic ID 1373 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMBuilder.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 DOMBuilder} Bounds {{153, 423}, {104, 18}} Class ShapedGraphic ID 1374 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMSaxBuilder.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMSaxBuilder} Class LineGraphic Head ID 1374 ID 1375 Points {275, 432} {257, 432} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1373 ID 1372 Class Group Graphics Bounds {{18, 459}, {117, 18}} Class ShapedGraphic ID 1370 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMSaxHandler.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMSaxHandler} Bounds {{18, 423}, {117, 18}} Class ShapedGraphic ID 1371 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxDefaultHandler.h Shape Rectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 SaxDefaultHandler} ID 1369 Class Group Graphics Bounds {{364, 459}, {122, 18}} Class ShapedGraphic ID 1367 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMPYXOutputter.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMPYXOutputter} Bounds {{364, 486}, {122, 18}} Class ShapedGraphic ID 1368 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMXMLOutputter.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMXMLOutputter} ID 1366 Bounds {{365, 639}, {121, 18}} Class ShapedGraphic ID 1365 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMImplementation.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMImplementation} Bounds {{364, 585}, {122, 18}} Class ShapedGraphic ID 1364 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMNodeFilter.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMNodeFilter} Bounds {{365, 558}, {121, 18}} Class ShapedGraphic ID 1363 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMNodeIterator.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMNodeIterator} Class Group Graphics Bounds {{372, 189}, {99, 18}} Class ShapedGraphic ID 1361 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 DOMElement} Bounds {{189, 189}, {167, 18}} Class ShapedGraphic ID 1362 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMElement.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMElement} ID 1360 Bounds {{189, 216}, {167, 18}} Class ShapedGraphic ID 1359 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMEntityReference.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMEntityReference} Bounds {{364, 612}, {122, 18}} Class ShapedGraphic ID 1358 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMBuilderFactory.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMBuilderFactory} Class Group Graphics Bounds {{372, 270}, {99, 18}} Class ShapedGraphic ID 1356 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 DOMDocument} Bounds {{189, 270}, {167, 18}} Class ShapedGraphic ID 1357 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMDocument.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMDocument} ID 1355 Class Group Graphics Bounds {{372, 135}, {99, 18}} Class ShapedGraphic ID 1353 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 DOMAttr} Bounds {{189, 135}, {167, 18}} Class ShapedGraphic ID 1354 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMAttribute.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMAttribute} ID 1352 Class Group Graphics Bounds {{372, 162}, {153, 18}} Class ShapedGraphic ID 1350 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 DOMDocumentFragment} Bounds {{189, 162}, {167, 18}} Class ShapedGraphic ID 1351 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMDocumentFragment.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMDocumentFragment} ID 1349 Bounds {{288, 90}, {140, 18}} Class ShapedGraphic ID 1348 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMNode.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMNodeWithChildren} Class Group Graphics Bounds {{135, 630}, {162, 18}} Class ShapedGraphic ID 1343 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMNodeWalker.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMNodePostorderWalker} Bounds {{85, 603}, {113, 18}} Class ShapedGraphic ID 1344 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMNodeWalker.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMNodeWalker} Bounds {{27, 657}, {162, 18}} Class ShapedGraphic ID 1345 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/DOM/DOMNodeWalker.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 DOMNodePreorderWalker} Class LineGraphic Head ID 1343 ID 1346 Points {166.333, 621} {191.167, 630} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1344 Class LineGraphic Head ID 1345 ID 1347 Points {135.917, 621} {113.583, 657} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1344 ID 1342 Class LineGraphic Head ID 1348 ID 1341 Points {224.667, 54} {331.333, 90} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1380 Class LineGraphic Head ID 1397 ID 1340 Points {81.125, 342} {81.375, 324} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1386 Class LineGraphic Head ID 1397 ID 1339 Points {194.117, 54} {85.3833, 306} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1380 Class LineGraphic Head ID 1382 ID 1338 Points {183.625, 54} {97.375, 108} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1380 Class LineGraphic Head ID 1380 ID 1337 Points {252, 45} {234, 45} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1379 Class LineGraphic Head ID 1383 ID 1336 Points {178.6, 54} {120.4, 81} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1380 Class LineGraphic Head ID 1377 ID 1335 Points {352.971, 108} {277.529, 243} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1348 Class LineGraphic Head ID 1370 ID 1334 Points {76.5, 441} {76.5, 459} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1371 Class LineGraphic Head ID 1384 ID 1333 Points {187.545, 54} {93.4545, 135} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1380 Class LineGraphic Head ID 1362 ID 1332 Points {372, 198} {356, 198} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1361 Class LineGraphic Head ID 1362 ID 1331 Points {350.227, 108} {280.273, 189} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1348 Class LineGraphic Head ID 1359 ID 1330 Points {351.893, 108} {278.607, 216} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1348 Class LineGraphic Head ID 1357 ID 1329 Points {372, 279} {356, 279} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1356 Class LineGraphic Head ID 1357 ID 1328 Points {353.725, 108} {276.775, 270} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1348 Class LineGraphic Head ID 1354 ID 1327 Points {372, 144} {356, 144} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1353 Class LineGraphic Head ID 1354 ID 1326 Points {340.9, 108} {289.6, 135} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1348 Class LineGraphic Head ID 1351 ID 1325 Points {372, 171} {356, 171} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1350 Class LineGraphic Head ID 1351 ID 1324 Points {347.312, 108} {283.188, 162} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1348 GridInfo HPages 1 ImageCounter 1 IsPalette NO Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo AutoAdjust YES HierarchicalOrientation 0 MagneticFieldCenter {0, 0} MagnetsEnabled YES PageBreakColor w 3.333333e-01 PageBreaks YES PageSetup BAt0eXBlZHN0cmVhbYED6IQBQISEhAtOU1ByaW50SW5mbwGEhAhOU09iamVjdACFkoSE hBNOU011dGFibGVEaWN0aW9uYXJ5AISEDE5TRGljdGlvbmFyeQCUhAFpEpKEhIQITlNT dHJpbmcBlIQBKxBOU0pvYkRpc3Bvc2l0aW9uhpKEmZkPTlNQcmludFNwb29sSm9ihpKE mZkOTlNCb3R0b21NYXJnaW6GkoSEhAhOU051bWJlcgCEhAdOU1ZhbHVlAJSEASqEhAFm nSSGkoSZmQtOU1BhcGVyTmFtZYaShJmZBkxldHRlcoaShJmZD05TUHJpbnRBbGxQYWdl c4aShJ2chIQBc54AhpKEmZkNTlNSaWdodE1hcmdpboaShJ2cn50khpKEmZkITlNDb3Bp ZXOGkoSdnISEAVOfAYaShJmZD05TU2NhbGluZ0ZhY3RvcoaShJ2chIQBZKABhpKEmZkL TlNGaXJzdFBhZ2WGkoSdnKmfAYaShJmZFE5TVmVydGljYWxQYWdpbmF0aW9uhpKEnZyk ngCGkoSZmRVOU0hvcml6b25hbFBhZ2luYXRpb26GkoSdnKSeAIaShJmZFk5TSG9yaXpv bnRhbGx5Q2VudGVyZWSGkoSdnKSeAYaShJmZDE5TTGVmdE1hcmdpboaShJ2cn50khpKE mZkNTlNPcmllbnRhdGlvboaShJ2cpJ4AhpKEmZkZTlNQcmludFJldmVyc2VPcmllbnRh dGlvboaSo5KEmZkKTlNMYXN0UGFnZYaShJ2chJeXgn////+GkoSZmQtOU1RvcE1hcmdp boaShJ2cn50khpKEmZkUTlNWZXJ0aWNhbGx5Q2VudGVyZWSGkrSShJmZC05TUGFwZXJT aXplhpKEnpyEhAx7X05TU2l6ZT1mZn2hgQJkgQMYhoaG RowAlign 0 RowSpacing 9.000000e+00 VPages 1 WindowInfo Frame {{137, 41}, {731, 892}} VisibleRegion {{-88, -46.5}, {716, 814.75}} Zoom 1 SOPE/sope-xml/DOM/DOMQueryPathExpression.m0000644000000000000000000005333315004363604017235 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "DOMDocument.h" #include "DOMAttribute.h" #include "DOMNamedNodeMap.h" #include "common.h" @interface NSString(QP) - (NSArray *)queryPathComponents; @end #define QUERY_CURRENT 1 #define QUERY_PARENT 2 #define QUERY_ROOT 3 /* QueryPathExpression classes: NSObject _DOMQPPredicateExpression _DOMQPPredicateQPExpression DOMQueryPathExpression _DOMQueryPathSequence _DOMQueryPathPredicates _DOMQueryPathAttribute _DOMQueryPathNodeQuery _DOMQueryPathChildNodes _DOMQueryPathKeyPath */ @interface DOMQueryPathExpression(Privates) + (id)makeQueryPathExpression:(NSString *)_expr; - (id)_deepChildNodesWithName:(id)_name type:(int)_type node:(id)_domNode; - (id)_flatChildNodesWithName:(id)_name type:(int)_type node:(id)_domNode; - (id)_rootSearchNodeForNode:(id)_domNode; - (id)evaluateWithNode:(id)_node inContext:(id)_ctx; - (id)evaluateWithNodeList:(id)_nodes inContext:(id)_ctx; @end @interface _DOMQPPredicateExpression : NSObject - (BOOL)matchesNode:(id)_node inContext:(id)_ctx; @end @interface _DOMQPPredicateQPExpression : NSObject { DOMQueryPathExpression *qpexpr; } - (id)initWithQueryPathExpression:(DOMQueryPathExpression *)_expr; @end @interface _DOMQueryPathSequence : DOMQueryPathExpression { NSArray *queryPaths; } + (id)sequenceWithArray:(NSArray *)_array; @end @interface _DOMQueryPathPredicates : DOMQueryPathExpression { DOMQueryPathExpression *expr; NSArray *predicates; } - (id)initWithQueryPathExpression:(DOMQueryPathExpression *)_expr predicates:(NSArray *)_predicates; @end @interface _DOMQueryPathAttribute : DOMQueryPathExpression { NSString *attrSpec; NSString *uri; struct { int getAll:1; int hasColon:1; } aflags; } - (id)initWithString:(NSString *)_spec; @end @interface _DOMQueryPathNodeQuery : DOMQueryPathExpression { int queryOp; } - (id)initWithQueryOp:(int)_op; @end @interface _DOMQueryPathChildNodes : DOMQueryPathExpression { NSString *elementName; BOOL deep; int nodeType; } - (id)initWithName:(NSString *)_name deep:(BOOL)_flag type:(int)_type; @end @interface _DOMQueryPathKeyPath : DOMQueryPathExpression { NSString *keyPath; } - (id)initWithKeyPath:(NSString *)_path; @end @implementation DOMQueryPathExpression - (id)_deepChildNodesWithName:(id)_name type:(int)_type node:(id)_domNode { NSMutableArray *array; id children; unsigned i, count; NSString *fname, *furi; if (![_domNode hasChildNodes]) return [NSArray array]; children = [_domNode childNodes]; if ((count = [children count]) == 0) return [NSArray array]; if (_name) { NSRange r; r = [_name rangeOfString:@"}"]; if (r.length != 0) { fname = [_name substringFromIndex:(r.location + r.length)]; furi = [[_name substringToIndex:r.location] substringFromIndex:1]; } else { fname = _name; furi = nil; } } else { fname = nil; furi = nil; } array = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) { id child; if ((child = [children objectAtIndex:i]) == nil) continue; if (([child nodeType] == _type) || (_type == -1)) { if (_name == nil) { /* wildcard query */ [array addObject:child]; } else { NSString *nname; nname = [child nodeName]; if ([nname isEqualToString:_name]) { /* FQ name matches */ [array addObject:child]; } else if ([nname isEqualToString:fname]) { /* name matches */ if (furi) { /* check URI */ if ([[child namespaceURI] isEqualToString:furi]) [array addObject:child]; } else { [array addObject:child]; } } } } [array addObjectsFromArray: [self _deepChildNodesWithName:_name type:_type node:child]]; } return array; } - (id)_flatChildNodesWithName:(id)_name type:(int)_type node:(id)_domNode { NSMutableArray *array; id children; unsigned i, count; if (![_domNode hasChildNodes]) return [NSArray array]; children = [_domNode childNodes]; if ((count = [children count]) == 0) return [NSArray array]; array = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) { id child; child = [children objectAtIndex:i]; if (([child nodeType] != _type) && (_type != -1)) continue; if (_name) { if (![[child nodeName] isEqualToString:_name]) continue; } if (child) [array addObject:child]; } return [[array copy] autorelease]; } - (id)_rootSearchNodeForNode:(id)_domNode { id root; switch ([_domNode nodeType]) { case DOM_DOCUMENT_NODE: case DOM_DOCUMENT_FRAGMENT_NODE: root = [(id)_domNode documentElement]; if (root == nil) { NSLog(@"WARNING(%s): document node %@ has no root element !", __PRETTY_FUNCTION__, _domNode); } break; case DOM_COMMENT_NODE: case DOM_PROCESSING_INSTRUCTION_NODE: case DOM_ELEMENT_NODE: root = [_domNode ownerDocument]; if (root == nil) { NSLog(@"WARNING(%s): node %@ has no owner document !", __PRETTY_FUNCTION__, _domNode); } root = [self _rootSearchNodeForNode:root]; break; case DOM_ATTRIBUTE_NODE: root = [(id)_domNode ownerElement]; if (root == nil) { NSLog(@"WARNING(%s): attribute node %@ has no owner element !", __PRETTY_FUNCTION__, _domNode); } root = [self _rootSearchNodeForNode:root]; break; default: root = [self _rootSearchNodeForNode:[_domNode parentNode]]; break; } return root; } + (id)queryPathWithComponents:(NSArray *)_array { NSMutableArray *a; unsigned i, count; if ((count = [_array count]) == 0) return nil; if (count == 1) return [[self makeQueryPathExpression:[_array objectAtIndex:0]] autorelease]; a = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) { DOMQueryPathExpression *c; if ((c = [self makeQueryPathExpression:[_array objectAtIndex:i]])) { [a addObject:c]; [c release]; c = nil; } else { NSLog(@"%s: couldn't make query-path expression ..", __PRETTY_FUNCTION__); } } return [_DOMQueryPathSequence sequenceWithArray:a]; } + (NSArray *)queryPathComponentsOfString:(NSString *)_path { return [_path queryPathComponents]; } + (id)queryPathWithString:(NSString *)_string { return [self queryPathWithComponents:[_string queryPathComponents]]; } + (_DOMQPPredicateExpression *)parsePredicateExpression:(NSString *)_expr { DOMQueryPathExpression *qpexpr; _DOMQPPredicateExpression *pred; #if 0 NSLog(@"%s: can't parse predicates yet '%@'", __PRETTY_FUNCTION__, _expr); #endif _expr = [@"-" stringByAppendingString:_expr]; qpexpr = [DOMQueryPathExpression queryPathWithString:_expr]; //NSLog(@"Expr: %@", qpexpr); pred = (_DOMQPPredicateExpression*) [[_DOMQPPredicateQPExpression alloc] initWithQueryPathExpression:qpexpr]; return [pred autorelease]; } + (NSArray *)parseNodeQueryDetailExpressions:(NSString *)_path { unsigned i, len, s; NSMutableArray *predicates; if ([_path length] == 0) return nil; predicates = nil; for (i = 0, s = 0, len = [_path length]; i < len; i++) { unichar c; c = [_path characterAtIndex:i]; if ((c == ']') && (s != 0)) { /* finished a predicate */ NSString *ps; id predicate; ps = ((i - s) > 0) ? [_path substringWithRange:NSMakeRange(s, (i - s))] : (NSString *)@""; if ((predicate = [self parsePredicateExpression:ps])) { if (predicates == nil) predicates = [NSMutableArray arrayWithCapacity:4]; [predicates addObject:predicate]; } s = 0; } else if (c == '[') { /* start a predicate */ if (s != 0) { NSLog(@"%s: syntax error, predicate not properly closed ('%@') !", __PRETTY_FUNCTION__, _path); } s = (i + 1); } } return predicates; } + (id)makeQueryPathExpression:(NSString *)_path { DOMQueryPathExpression *result; BOOL isDeep = NO; NSString *predicateString; NSRange r; if (([_path rangeOfString:@")"].length) != 0) { //[self doesNotRecognizeSelector:_cmd]; NSLog(@"%s: unsupported querypath '%@'", __PRETTY_FUNCTION__, _path); } if ([_path hasPrefix:@"-"]) { isDeep = NO; _path = [_path substringFromIndex:1]; } else isDeep = YES; r = [_path rangeOfString:@"["]; if (r.length != 0) { predicateString = [_path substringFromIndex:r.location]; _path = [_path substringToIndex:r.location]; } else predicateString = nil; if ([_path length] == 0) { /* empty path, returns current node */ result = [[_DOMQueryPathNodeQuery alloc] initWithQueryOp:QUERY_CURRENT]; } else if ([_path isEqualToString:@"/"]) { /* lookup root element */ result = [[_DOMQueryPathNodeQuery alloc] initWithQueryOp:QUERY_ROOT]; } else if ([_path isEqualToString:@"."]) { /* lookup current element */ result = [[_DOMQueryPathNodeQuery alloc] initWithQueryOp:QUERY_CURRENT]; } else if ([_path isEqualToString:@".."]) { /* lookup parent element */ result = [[_DOMQueryPathNodeQuery alloc] initWithQueryOp:QUERY_PARENT]; } else if ([_path isEqualToString:@"*"]) { result = [[_DOMQueryPathChildNodes alloc] initWithName:nil deep:isDeep type:DOM_ELEMENT_NODE]; } else if ([_path isEqualToString:@"#"]) { result = [[_DOMQueryPathChildNodes alloc] initWithName:nil deep:isDeep type:-1]; } else if ([_path hasPrefix:@"!"]) { /* perform key-value call */ _path = [_path substringFromIndex:1]; result = [[_DOMQueryPathKeyPath alloc] initWithKeyPath:_path]; } else if ([_path hasPrefix:@"?"]) { /* lookup processing instruction */ _path = [_path substringFromIndex:1]; // target of PI result = [[_DOMQueryPathChildNodes alloc] initWithName:_path deep:isDeep type:DOM_PROCESSING_INSTRUCTION_NODE]; } else if ([_path hasPrefix:@"@"]) { /* lookup attribute */ _path = [_path substringFromIndex:1]; result = [[_DOMQueryPathAttribute alloc] initWithString:_path]; } else { /* deep lookup child element */ result = [[_DOMQueryPathChildNodes alloc] initWithName:_path deep:isDeep type:DOM_ELEMENT_NODE]; } /* attach predicates ... */ if (([predicateString length] > 0) && (result != nil)) { NSArray *predicates; if ((predicates = [self parseNodeQueryDetailExpressions:predicateString])){ #if 0 NSLog(@"%s: can't yet handle predicates %@", __PRETTY_FUNCTION__, predicates); #endif result = [result autorelease]; result = [[_DOMQueryPathPredicates alloc] initWithQueryPathExpression:result predicates:predicates]; } } return result; } - (id)evaluateWithNode:(id)_node inContext:(id)_ctx { /* override in subclasses ! */ [self doesNotRecognizeSelector:_cmd]; return nil; } - (id)evaluateWithNodeList:(id)_nodes inContext:(id)_ctx { unsigned i, count; NSMutableArray *ma; NSArray *results; if ((count = [_nodes count]) == 0) return _nodes; ma = [[NSMutableArray alloc] init]; for (i = 0; i < count; i++) { id node; node = [_nodes objectAtIndex:i]; node = [self evaluateWithNode:node inContext:_ctx]; if (node) [ma addObject:node]; } results = [ma copy]; [ma release]; return [results autorelease]; } - (id)evaluateWithNode:(id)_node { return [self evaluateWithNode:_node inContext:nil]; } - (id)evaluateWithNodeList:(id)_nodes { return [self evaluateWithNodeList:_nodes inContext:nil]; } @end /* DOMQueryPathExpression */ @implementation _DOMQueryPathChildNodes - (id)initWithName:(NSString *)_name deep:(BOOL)_flag type:(int)_type { self->elementName = [_name copy]; self->deep = _flag; self->nodeType = _type; return self; } - (void)dealloc { [self->elementName release]; [super dealloc]; } - (id)evaluateWithNode:(id)_node inContext:(id)_ctx { id result; BOOL _forceList = NO; result = self->deep ? [self _deepChildNodesWithName:self->elementName type:self->nodeType node:_node] : [self _flatChildNodesWithName:self->elementName type:self->nodeType node:_node]; if (!_forceList) { if ([result count] == 0) result = nil; else if ([result count] == 1) result = [result objectAtIndex:0]; } return result; } - (id)evaluateWithNodeList:(id)_nodes inContext:(id)_ctx { unsigned i, count; NSMutableArray *ma; NSArray *results; if ((count = [_nodes count]) == 0) return _nodes; ma = [[NSMutableArray alloc] init]; for (i = 0; i < count; i++) { id node; node = [_nodes objectAtIndex:i]; node = self->deep ? [self _deepChildNodesWithName:self->elementName type:self->nodeType node:node] : [self _flatChildNodesWithName:self->elementName type:self->nodeType node:node]; [ma addObjectsFromArray:node]; } results = [ma copy]; [ma release]; return [results autorelease]; } - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<%@[0x%p]:", NSStringFromClass([self class]), self]; [ms appendFormat:@" element='%@'", self->elementName]; [ms appendString:self->deep ? @" deep" : @" shallow"]; [ms appendFormat:@" nodeType=%i", self->nodeType]; [ms appendString:@">"]; return ms; } @end /* _DOMQueryPathChildNodes */ @implementation _DOMQueryPathKeyPath - (id)initWithKeyPath:(NSString *)_path { self->keyPath = [_path copy]; return self; } - (void)dealloc { [self->keyPath release]; [super dealloc]; } - (id)evaluateWithNode:(id)_node inContext:(id)_ctx { return [_node valueForKeyPath:self->keyPath]; } - (NSString *)description { return [NSString stringWithFormat:@"<0x%p[%@]: keypath='%@'>", self, NSStringFromClass([self class]), self->keyPath]; } @end /* _DOMQueryPathKeyPath */ @implementation _DOMQueryPathNodeQuery - (id)initWithQueryOp:(int)_op { self->queryOp = _op; return self; } - (id)evaluateWithNode:(id)_node inContext:(id)_ctx { switch (self->queryOp) { case QUERY_ROOT: return [self _rootSearchNodeForNode:_node]; case QUERY_PARENT: return [_node parentNode]; case QUERY_CURRENT: return _node; default: [NSException raise:@"DOMQueryPathException" format:@"unknown node operation %i on node %@", self->queryOp, _node]; return nil; } } - (NSString *)description { return [NSString stringWithFormat:@"<0x%p[%@]: op=%i>", self, NSStringFromClass([self class]), self->queryOp]; } @end /* _DOMQueryPathNodeQuery */ @implementation _DOMQueryPathPredicates - (id)initWithQueryPathExpression:(DOMQueryPathExpression *)_expr predicates:(NSArray *)_predicates { self->expr = [_expr retain]; self->predicates = [_predicates copy]; return self; } - (void)dealloc { [self->expr release]; [self->predicates release]; [super dealloc]; } - (id)evaluateWithNodeList:(id)_nodes inContext:(id)_ctx { NSArray *list; if ((list = [self->expr evaluateWithNodeList:_nodes inContext:_ctx]) && [self->predicates count] > 0) { NSMutableArray *result; unsigned i, count; result = [NSMutableArray arrayWithCapacity:16]; for (i = 0, count = [list count]; i < count; i++) { NSEnumerator *e; _DOMQPPredicateExpression *pred; id node; if ((node = [list objectAtIndex:i]) == nil) continue; e = [self->predicates objectEnumerator]; while ((pred = [e nextObject])) { if (![pred matchesNode:node inContext:nil]) { node = nil; break; } } if (node) [result addObject:node]; } list = [[result copy] autorelease]; } return list; } - (id)evaluateWithNode:(id)_node inContext:(id)_ctx { NSLog(@"WARNING(%s): called -evaluateWithNode: ...", __PRETTY_FUNCTION__); return [self evaluateWithNodeList:[NSArray arrayWithObject:_node] inContext:_ctx]; } @end /* _DOMQueryPathPredicates */ @implementation _DOMQueryPathSequence - (id)initWithArray:(NSArray *)_array { self->queryPaths = [_array retain]; return self; } + (id)sequenceWithArray:(NSArray *)_array { return [[[self alloc] initWithArray:_array] autorelease]; } - (void)dealloc { [self->queryPaths release]; [super dealloc]; } - (id)evaluateWithNode:(id)_node inContext:(id)_ctx { NSEnumerator *e; DOMQueryPathExpression *queryPathComponent; id activeNode; activeNode = _node; e = [self->queryPaths objectEnumerator]; while ((queryPathComponent = [e nextObject]) && (activeNode != nil)) { activeNode = [queryPathComponent evaluateWithNode:activeNode inContext:_ctx]; } return activeNode; } - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<%@[0x%p]: ", NSStringFromClass([self class]), self]; [ms appendString:@"sequence="]; [ms appendString:[self->queryPaths description]]; [ms appendString:@">"]; return ms; } @end /* _DOMQueryPathSequence */ @implementation _DOMQueryPathAttribute - (id)initWithString:(NSString *)_spec { if ([_spec isEqualToString:@"*"]) { /* select all attributes */ self->aflags.getAll = 1; } else if ([_spec hasPrefix:@"{"]) { /* fully qualified name */ NSRange r; r = [_spec rangeOfString:@"}"]; if (r.length == 0) { /* syntax error, missing closing '}' */ self->attrSpec = [_spec copy]; } else { self->attrSpec = [[_spec substringFromIndex:(r.location + r.length)] copy]; self->uri = [[[_spec substringToIndex:r.location] substringFromIndex:1] copy]; } } else { NSRange r; r = [_spec rangeOfString:@":"]; if (r.length != 0) { /* found colon (namespaces), eg 'html:blah' */ self->aflags.hasColon = 1; self->attrSpec = [[_spec substringFromIndex:(r.location + r.length)] copy]; self->uri = [_spec substringToIndex:r.location]; self->uri = ([self->uri length] > 1) ? [self->uri copy] : (id)@"*"; } else { /* usual 'blah' */ self->attrSpec = [_spec copy]; } } return self; } - (void)dealloc { [self->uri release]; [self->attrSpec release]; [super dealloc]; } - (id)evaluateWithNode:(id)_node inContext:(id)_ctx { /* lookup attribute element */ id attributes; id result; BOOL _forceList = NO; attributes = [(id)_node attributes]; #if DEBUG if (attributes == nil) NSLog(@"%s: node %@ has no attributes ..", __PRETTY_FUNCTION__, _node); #endif if (self->aflags.getAll) { /* all attribute elements */ result = attributes; _forceList = NO; // attributes behave already like a list .. } else if (self->uri) { result = [attributes namedItem:self->attrSpec namespaceURI:self->uri]; } else if (self->aflags.hasColon) { result = [attributes namedItem:self->attrSpec namespaceURI:self->uri]; //result = [result value]; } else { result = [attributes namedItem:self->attrSpec]; } if (_forceList) result = [NSArray arrayWithObject:result]; return result; } - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:64]; [ms appendFormat:@"<%@[0x%p]:", NSStringFromClass([self class]), self]; [ms appendFormat:@" attrSpec='%@'", self->attrSpec]; if (self->uri) [ms appendFormat:@" uri='%@'", self->uri]; if (self->aflags.getAll) [ms appendString:@" getall"]; if (self->aflags.hasColon) [ms appendString:@" colon"]; [ms appendString:@">"]; return ms; } @end /* _DOMQueryPathAttribute */ @implementation _DOMQPPredicateExpression - (BOOL)matchesNode:(id)_node inContext:(id)_ctx { /* override in subclasses ! */ [self doesNotRecognizeSelector:_cmd]; return NO; } @end /* _DOMQPPredicateExpression */ @implementation _DOMQPPredicateQPExpression - (id)initWithQueryPathExpression:(DOMQueryPathExpression *)_expr { self->qpexpr = [_expr retain]; return self; } - (id)init { return [self initWithQueryPathExpression:nil]; } - (void)dealloc { [self->qpexpr release]; [super dealloc]; } - (BOOL)matchesNode:(id)_node inContext:(id)_ctx { id nodeList; //NSLog(@"check match of node %@, qpexpr %@ ...", _node, qpexpr); nodeList = [NSArray arrayWithObject:_node]; nodeList = [self->qpexpr evaluateWithNodeList:nodeList inContext:_ctx]; return ([nodeList count] > 0) ? YES : NO; } @end /* _DOMQPPredicateQPExpression */ SOPE/sope-xml/DOM/DOMImplementation.m0000644000000000000000000000502415004363604016212 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMImplementation.h" #include "DOMDocument.h" #include "DOMDocumentFragment.h" #include "common.h" @implementation NGDOMImplementation - (id)init { self->elementClass = NSClassFromString(@"NGDOMElement"); self->textNodeClass = NSClassFromString(@"NGDOMText"); self->attrClass = NSClassFromString(@"NGDOMAttribute"); return self; } - (Class)domDocumentClass { return [NGDOMDocument class]; } - (Class)domDocumentTypeClass { return NSClassFromString(@"NGDOMDocumentType"); } - (Class)domElementClass { return self->elementClass; } - (Class)domElementNSClass { return self->elementClass; } - (Class)domDocumentFragmentClass { return NSClassFromString(@"NGDOMDocumentFragment"); } - (Class)domTextNodeClass { return self->textNodeClass; } - (Class)domCommentClass { return NSClassFromString(@"NGDOMComment"); } - (Class)domCDATAClass { return NSClassFromString(@"NGDOMCDATA"); } - (Class)domProcessingInstructionClass { return NSClassFromString(@"NGDOMProcessingInstruction"); } - (Class)domAttributeClass { return self->attrClass; } - (Class)domAttributeNSClass { return self->attrClass; } - (Class)domEntityReferenceClass { return NSClassFromString(@"NGDOMEntityReference"); } - (id)createDocumentWithName:(NSString *)_qname namespaceURI:(NSString *)_uri documentType:(id)_doctype { id doc; doc = [[[self domDocumentClass] alloc] initWithName:_qname namespaceURI:_uri documentType:_doctype dom:self]; return [doc autorelease]; } - (id)createDocumentType:(NSString *)_qname publicId:(NSString *)_pubId systemId:(NSString *)_sysId { id doc; doc = [[[self domDocumentTypeClass] alloc] initWithName:_qname publicId:_pubId systemId:_sysId dom:self]; return [doc autorelease]; } @end /* NGDOMImplementation */ SOPE/sope-xml/DOM/DOMEntityReference.h0000644000000000000000000000227615004363604016321 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMEntityReference_H__ #define __DOMEntityReference_H__ #include @class NSString; @interface NGDOMEntityReference : NGDOMNodeWithChildren { id parent; NSString *name; } /* attributes */ /* node */ @end @interface NGDOMEntityReference(PrivateCtors) /* use DOMDocument for constructing DOMEntityReference's ! */ - (id)initWithName:(NSString *)_name; @end #endif /* __DOMEntityReference_H__ */ SOPE/sope-xml/DOM/Version0000644000000000000000000000004515004363604014055 0ustar rootroot# version file SUBMINOR_VERSION:=24 SOPE/sope-xml/DOM/DOMDocument+factory.m0000644000000000000000000000356115004363604016452 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include "common.h" #include @implementation NGDOMDocument(DocumentTraversal) - (Class)domTreeWalkerClass { return NSClassFromString(@"DOMTreeWalker"); } - (id)createNodeIterator:(id)_node whatToShow:(unsigned long)_whatToShow filter:(id)_filter { [self doesNotRecognizeSelector:_cmd]; return nil; } - (id)createTreeWalker:(id)_rootNode whatToShow:(unsigned long)_whatToShow filter:(id)_filter expandEntityReferences:(BOOL)_expandEntityReferences { id walker; // should throw DOMException with NOT_SUPPORTED_ERR NSAssert(_rootNode, @"invalid root node !"); walker = [[[self domTreeWalkerClass] alloc] initWithRootNode:_rootNode whatToShow:_whatToShow filter:_filter expandEntityReferences:_expandEntityReferences]; return [walker autorelease]; } @end /* NGDOMDocument(DocumentTraversal) */ SOPE/sope-xml/DOM/DOMText.h0000644000000000000000000000344215004363604014146 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMText_H__ #define __DOMText_H__ #include /* Why do I get adjacent Text nodes? The DOM structure model that is created by whatever it is that creates it has one Text node per block of text when it starts. The only way you can have adjacent Text nodes is as a result of user operations; it is not an option for the DOM implementation when it first presents its structure model to the user. The normalize method (on the Element interface in level 1, but moved to Node for Level 2) will merge all the adjacent Text nodes into one again, so they will have the same form as if you wrote out the XML or HTML and then read it in again. Note that this will have no effect on CDATA Sections. A filtered view of a document, such as that obtained through use of TreeWalker, may have adjacent Text nodes because the intervening Nodes are not seen in that view. */ @interface NGDOMText : NGDOMCharacterData < DOMText > { } @end #endif /* __DOMTextNode_H__ */ SOPE/sope-xml/DOM/DOMNode+Enum.h0000644000000000000000000000216015004363604015003 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOM_DOMNodeEnum_H__ #define __DOM_DOMNodeEnum_H__ #include @class NSEnumerator; @interface NSObject(DOMNodeEnum) - (NSEnumerator *)domParentNodeEnumerator; @end /* NSObject(DOMNodeEnum) */ @interface NGDOMNode(Enum) - (NSEnumerator *)parentNodeEnumerator; @end /* NGDOMNode(Enum) */ #endif /* __DOM_DOMNodeEnum_H__ */ SOPE/sope-xml/DOM/DOMNode+QPEval.m0000644000000000000000000000220415004363604015233 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSObject+QPEval.h" #include "DOMNode.h" #include "DOMDocument.h" #include "common.h" @implementation NGDOMNode(QPEval) - (id)queryPathRootObjectInContext:(id)_ctx { return [self ownerDocument]; } @end /* NGDOMNode(QPEval) */ @implementation NGDOMDocument(QPEval) - (id)queryPathRootObjectInContext:(id)_ctx { return self; } @end /* NGDOMNode(QPEval) */ SOPE/sope-xml/DOM/DOMElement.m0000644000000000000000000004712415004363604014625 0ustar rootroot/* Copyright (C) 2000-2006 SKYRIX Software AG Copyright (C) 2006 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include "DOMNode+QueryPath.h" #include "common.h" @interface _DOMElementAttrNamedNodeMap : NSObject < DOMNamedNodeMap > { NGDOMElement *element; /* non-retained */ } - (id)initWithElement:(id)_element; - (id)objectEnumerator; - (void)invalidate; @end /* _DOMElementAttrNamedNodeMap */ @interface NGDOMElement(Privates) - (NSUInteger)_numberOfAttributes; - (id)_attributeNodeAtIndex:(NSUInteger)_idx; - (id)attributeNode:(NSString *)_localName; - (id)attributeNode:(NSString *)_localName namespaceURI:(NSString *)_ns; @end static NSNull *null = nil; @implementation NGDOMElement - (id)initWithTagName:(NSString *)_tagName namespaceURI:(NSString *)_uri { if (null == nil) null = [[NSNull null] retain]; if ((self = [super init])) { self->tagName = [_tagName copy]; self->namespaceURI = [_uri copy]; } return self; } - (id)initWithTagName:(NSString *)_tagName { return [self initWithTagName:_tagName namespaceURI:nil]; } - (void)dealloc { [self->attributes makeObjectsPerformSelector: @selector(_domNodeForgetParentNode:) withObject:self]; [self->attrNodeMap invalidate]; [self->attrNodeMap release]; [self->keyToAttribute release]; [self->attributes release]; [self->tagName release]; [self->namespaceURI release]; [self->prefix release]; [super dealloc]; } /* attributes */ - (NSString *)tagName { return self->tagName; } - (NSString *)localName { return self->tagName; } - (void)setPrefix:(NSString *)_prefix { id old = self->prefix; self->prefix = [_prefix copy]; [old release]; } - (NSString *)prefix { return self->prefix; } - (NSString *)namespaceURI { return self->namespaceURI; } - (void)setLine:(NSInteger)_line { self->line = _line; } - (NSUInteger)line { return self->line; } /* lookup */ - (void)_walk_getElementsByTagName:(id)_walker { id node; node = [_walker currentNode]; if ([node nodeType] != DOM_ELEMENT_NODE) return; if (![[node tagName] isEqualToString: [(NSArray *)[_walker context] objectAtIndex:0]]) /* tagname doesn't match */ return; [[(NSArray *)[_walker context] objectAtIndex:1] addObject:node]; } - (void)_walk_getElementsByTagNameAddAll:(id)_walker { id node; node = [_walker currentNode]; if ([node nodeType] != DOM_ELEMENT_NODE) return; [(NSMutableArray *)[_walker context] addObject:node]; } - (id)getElementsByTagName:(NSString *)_tagName { /* introduced in DOM2, should return a *live* list ! */ NGDOMNodePreorderWalker *walker; NSMutableArray *array; SEL sel; id ctx; if (![self hasChildNodes]) return nil; if (_tagName == nil) return nil; array = [NSMutableArray arrayWithCapacity:4]; if ([_tagName isEqualToString:@"*"]) { _tagName = nil; ctx = array; sel = @selector(_walk_getElementsByTagNameAddAll:); } else { ctx = [NSArray arrayWithObjects:_tagName, array, nil]; sel = @selector(_walk_getElementsByTagName:); } walker = [[NGDOMNodePreorderWalker alloc] initWithTarget:self selector:sel context:ctx]; [walker walkNode:self]; [walker release]; walker = nil; return [[array copy] autorelease]; } - (id)getElementsByTagName:(NSString *)_tagName namespaceURI:(NSString *)_uri { // TODO: implement [self doesNotRecognizeSelector:_cmd]; return nil; } /* element attributes */ - (void)_ensureAttrs { if (self->attributes == nil) self->attributes = [[NSMutableArray alloc] init]; if (self->keyToAttribute == nil) self->keyToAttribute = [[NSMutableDictionary alloc] init]; } - (void)_attributeSetChanged { } - (NSUInteger)_numberOfAttributes { return [self->attributes count]; } - (id)_attributeNodeAtIndex:(NSUInteger)_idx { if (_idx >= [self->attributes count]) return nil; return [self->attributes objectAtIndex:_idx]; } - (id)_keyForAttribute:(id)_attrNode { return [_attrNode name]; } - (id)_nskeyForLocalName:(NSString *)attrName namespaceURI:(NSString *)nsURI { id key; if (attrName == nil) return nil; if (nsURI) { id objs[2]; objs[0] = attrName; objs[1] = nsURI; key = [NSArray arrayWithObjects:objs count:2]; } else key = attrName; return key; } - (id)_nskeyForAttribute:(id)_attrNode { NSString *attrName; if ((attrName = [_attrNode name]) == nil) { NSLog(@"WARNING: attribute %@ has no valid attribute name !", _attrNode); return nil; } return [self _nskeyForLocalName:attrName namespaceURI:[_attrNode namespaceURI]]; } - (BOOL)hasAttribute:(NSString *)_attrName { return [self hasAttribute:_attrName namespaceURI:[self namespaceURI]]; } - (void)setAttribute:(NSString *)_attrName value:(NSString *)_value { [self setAttribute:_attrName namespaceURI:[self namespaceURI] value:_value]; #if 0 // ms: ?? id node; NSAssert1(_attrName, @"invalid attribute name '%@'", _attrName); if ((node = [self->keyToAttribute objectForKey:_attrName]) == nil) { /* create new node */ node = [[self ownerDocument] createAttribute:_attrName]; } NSAssert(node, @"couldn't find/create node for attribute"); node = [self setAttributeNode:node]; [node setValue:_value]; #endif } - (id)attributeNode:(NSString *)_attrName { return [self attributeNode:_attrName namespaceURI:[self namespaceURI]]; } - (NSString *)attribute:(NSString *)_attrName { return [[self attributeNode:_attrName] value]; } - (BOOL)hasAttribute:(NSString *)_localName namespaceURI:(NSString *)_ns { id objs[2]; id key; if ([_ns isEqualToString:@"*"]) { /* match any namespace */ NSEnumerator *e; id attr; if ((attr = [self->keyToAttribute objectForKey:_localName])) return YES; e = [self->keyToAttribute keyEnumerator]; while ((key = [e nextObject])) { if ([key isKindOfClass:[NSArray class]]) { if ([[key objectAtIndex:0] isEqualToString:_localName]) return YES; } } return NO; } objs[0] = _localName; objs[1] = _ns ? _ns : (NSString *)null; key = [NSArray arrayWithObjects:objs count:2]; return [self->keyToAttribute objectForKey:key] ? YES : NO; } - (void)setAttribute:(NSString *)_localName namespaceURI:(NSString *)_ns value:(NSString *)_value { id key; id node; key = [self _nskeyForLocalName:_localName namespaceURI:_ns]; NSAssert2(key, @"invalid (ns-)attribute name localName='%@', uri='%@'", _localName, _ns); if ((node = [self->keyToAttribute objectForKey:key]) == nil) { /* create new node */ node = [[self ownerDocument] createAttribute:_localName namespaceURI:_ns]; } NSAssert(node, @"couldn't find/create node for attribute"); node = [self setAttributeNodeNS:node]; [node setValue:_value]; } - (id)attributeNode:(NSString *)_localName namespaceURI:(NSString *)_ns { id objs[2]; id key; if ([_ns isEqualToString:@"*"]) { /* match any namespace */ NSEnumerator *e; id attr; if ((attr = [self->keyToAttribute objectForKey:_localName])) return attr; e = [self->keyToAttribute keyEnumerator]; while ((key = [e nextObject])) { if ([key isKindOfClass:[NSArray class]]) { if ([[key objectAtIndex:0] isEqualToString:_localName]) return [self->keyToAttribute objectForKey:key]; } } return nil; } objs[0] = _localName; objs[1] = _ns ? _ns : (NSString *)null; key = [NSArray arrayWithObjects:objs count:2]; return [self->keyToAttribute objectForKey:key]; } - (NSString *)attribute:(NSString *)_localName namespaceURI:(NSString *)_ns { return [[self attributeNode:_localName namespaceURI:_ns] value]; } - (id)setAttributeNodeNS:(id)_attrNode { id key, oldNode; if (_attrNode == nil) /* invalid node parameters */ return nil; if ((key = [self _nskeyForAttribute:_attrNode]) == nil) /* couldn't get key */ return nil; [self _ensureAttrs]; /* check if the key is already added */ if ((oldNode = [self->keyToAttribute objectForKey:key])) { if (oldNode == _attrNode) { /* already contained */ // NSLog(@"node is already set !"); return _attrNode; } /* replace existing node */ [self->attributes replaceObjectAtIndex: [self->attributes indexOfObject:oldNode] withObject:_attrNode]; [self->keyToAttribute setObject:_attrNode forKey:key]; [(id)_attrNode _domNodeRegisterParentNode:self]; [self _attributeSetChanged]; return _attrNode; } else { /* add node */ NSAssert(self->keyToAttribute, @"missing keyToAttribute"); NSAssert(self->attributes, @"missing attrs"); [self->keyToAttribute setObject:_attrNode forKey:key]; [self->attributes addObject:_attrNode]; [(id)_attrNode _domNodeRegisterParentNode:self]; [self _attributeSetChanged]; // NSLog(@"added attr %@, elem %@", _attrNode, self); return _attrNode; } } - (void)removeAttribute:(NSString *)_attr namespaceURI:(NSString *)_uri { id node; id key; key = [self _nskeyForLocalName:_attr namespaceURI:_uri]; NSAssert2(key, @"invalid (ns-)attribute name '%@', '%@'", _attr, _uri); node = [self->keyToAttribute objectForKey:key]; [self removeAttributeNodeNS:node]; } - (id)removeAttributeNodeNS:(id)_attrNode { id key, oldNode; if (_attrNode == nil) /* invalid node parameters */ return nil; if (self->attributes == nil) /* no attributes are set up */ return nil; if ((key = [self _nskeyForAttribute:_attrNode]) == nil) /* couldn't get key for node */ return nil; if ((oldNode = [self->keyToAttribute objectForKey:key])) { /* the node's key exists */ if (oldNode != _attrNode) { /* the node has the same key, but isn't the same */ return nil; } /* ok, found the node, let's remove ! */ [[_attrNode retain] autorelease]; [self->keyToAttribute removeObjectForKey:key]; [self->attributes removeObjectIdenticalTo:_attrNode]; [(id)_attrNode _domNodeForgetParentNode:self]; [self _attributeSetChanged]; return _attrNode; } else /* no such attribute is stored */ return nil; } - (id)setAttributeNode:(id)_attrNode { [self doesNotRecognizeSelector:_cmd]; return nil; } - (id)removeAttributeNode:(id)_attrNode { [self doesNotRecognizeSelector:_cmd]; return nil; } - (void)removeAttribute:(NSString *)_attr { id node; NSAssert1(_attr, @"invalid attribute name '%@'", _attr); node = [self->keyToAttribute objectForKey:_attr]; [self removeAttributeNode:node]; } /* node */ - (BOOL)_isValidChildNode:(id)_node { switch ([_node nodeType]) { case DOM_ELEMENT_NODE: case DOM_TEXT_NODE: case DOM_COMMENT_NODE: case DOM_PROCESSING_INSTRUCTION_NODE: case DOM_CDATA_SECTION_NODE: case DOM_ENTITY_REFERENCE_NODE: return YES; default: return NO; } } - (DOMNodeType)nodeType { return DOM_ELEMENT_NODE; } - (id)attributes { /* returns a named-node-map */ if (self->attrNodeMap == nil) { self->attrNodeMap = [[_DOMElementAttrNamedNodeMap alloc] initWithElement:self]; } return self->attrNodeMap; } /* parent node */ - (void)_domNodeRegisterParentNode:(id)_parent { self->parent = _parent; } - (void)_domNodeForgetParentNode:(id)_parent { if (_parent == self->parent) /* the node's parent was deallocated */ self->parent = nil; } - (id)parentNode { return self->parent; } /* description */ - (NSString *)description { return [NSString stringWithFormat: @"<0x%p[%@]: name=%@ parent=%@ #attrs=%"PRIuPTR" #children=%"PRIuPTR">", self, NSStringFromClass([self class]), [self nodeName], [[self parentNode] nodeName], [self _numberOfAttributes], [self hasChildNodes] ? [[self childNodes] length] : 0]; } /* QPValues */ - (NSException *)setQueryPathValue:(id)_value { return [NSException exceptionWithName:@"QueryPathEvalException" reason:@"cannot set query-path value on DOMElement !" userInfo:nil]; } - (id)queryPathValue { return [self childNodes]; } /* key/value coding */ - (id)valueForKey:(NSString *)_key { if ([_key hasPrefix:@"/"]) return [self lookupQueryPath:[_key substringFromIndex:1]]; if ([_key hasPrefix:@"@"]) { return [[self attributes] namedItem:[_key substringFromIndex:1] namespaceURI:@"*"]; } return [super valueForKey:_key]; } @end /* NGDOMElement */ @implementation _DOMElementAttrNamedNodeMap - (id)initWithElement:(id)_element { self->element = _element; return self; } - (void)invalidate { self->element = nil; } static inline void _checkValid(_DOMElementAttrNamedNodeMap *self) { if (self->element == nil) { NSCAssert(self->element, @"named node map is invalid (element was deallocated) !"); } } /* access */ static NSString *_XNSUri(NSString *_name) { NSRange r1; if (![_name hasPrefix:@"{"]) return nil; r1 = [_name rangeOfString:@"}"]; if (r1.length == 0) return nil; r1.length = (r1.location - 2); r1.location = 1; return [_name substringWithRange:r1]; } static NSString *_XNSLocalName(NSString *_name) { NSRange r; r = [_name rangeOfString:@"}"]; return r.length == 0 ? _name : [_name substringFromIndex:(r.location + r.length)]; } - (NSUInteger)length { _checkValid(self); return [self->element _numberOfAttributes]; } - (id)objectAtIndex:(NSUInteger)_idx { _checkValid(self); return [self->element _attributeNodeAtIndex:_idx]; } - (IDOMNode)namedItem:(NSString *)_name { NSString *nsuri; _checkValid(self); if ((nsuri = _XNSUri(_name))) return [self namedItem:_XNSLocalName(_name) namespaceURI:nsuri]; return [self->element attributeNode:_name]; } - (IDOMNode)setNamedItem:(IDOMNode)_node { _checkValid(self); // TODO: is the cast correct? return [self->element setAttributeNode:(id)_node]; } - (IDOMNode)removeNamedItem:(NSString *)_name { NSString *nsuri; id node; _checkValid(self); if ((nsuri = _XNSUri(_name))) return [self removeNamedItem:_XNSLocalName(_name) namespaceURI:nsuri]; if ((node = [self->element attributeNode:_name])) { node = [node retain]; [self->element removeAttribute:_name]; return [node autorelease]; } else return nil; } /* DOM2 access */ - (IDOMNode)namedItem:(NSString *)_name namespaceURI:(NSString *)_uri { return [self->element attributeNode:_name namespaceURI:_uri]; } - (IDOMNode)setNamedItemNS:(IDOMNode)_node { _checkValid(self); // TODO: is the cast correct? return [self->element setAttributeNodeNS:(id)_node]; } - (IDOMNode)removeNamedItem:(NSString *)_name namespaceURI:(NSString *)_uri { id node; _checkValid(self); if ((node = [self->element attributeNode:_name namespaceURI:_uri])) { node = [node retain]; [self->element removeAttribute:_name namespaceURI:_uri]; return [node autorelease]; } else return nil; } /* mimic NSArray */ - (NSUInteger)count { _checkValid(self); return [self->element _numberOfAttributes]; } - (id)objectEnumerator { NSMutableArray *ma; unsigned i, count; _checkValid(self); if ((count = [self->element _numberOfAttributes]) == 0) return nil; ma = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) [ma addObject:[self->element _attributeNodeAtIndex:i]]; return [ma objectEnumerator]; } /* mimic NSDictionary */ - (void)setObject:(id)_value forKey:(id)_key { _checkValid(self); [self takeValue:_value forKey:[_key stringValue]]; } - (id)objectForKey:(id)_key { _checkValid(self); return [self valueForKey:[_key stringValue]]; } /* KVC */ - (void)takeValue:(id)_value forKey:(NSString *)_key { id node; _checkValid(self); if ((node = [self->element attributeNode:_key namespaceURI:@"*"])) { [node setValue:[_value stringValue]]; } else { [self->element setAttribute:_key namespaceURI:@"xhtml" value:[_value stringValue]]; } } - (id)valueForKey:(NSString *)_key { id v; _checkValid(self); if ((v = [self namedItem:_key])) return [v value]; if ((v = [self namedItem:_key namespaceURI:@"*"])) return [v value]; return nil; } /* JSSupport */ - (id)_jsprop_length { return [NSNumber numberWithInt:[self length]]; } - (id)_jsfunc_item:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; return [self objectAtIndex:[[_args objectAtIndex:0] intValue]]; } - (id)_jsfunc_getNamedItem:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; return [self namedItem:[[_args objectAtIndex:0] stringValue]]; } - (id)_jsfunc_getNamedItemNS:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; if (count == 1) return [self namedItem:[[_args objectAtIndex:0] stringValue]]; else { return [self namedItem:[[_args objectAtIndex:1] stringValue] namespaceURI:[[_args objectAtIndex:0] stringValue]]; } } - (id)_jsfunc_setNamedItem:(NSArray *)_args { unsigned i, count; id last = nil; for (i = 0, count = [_args count]; i < count; i++) last = [self setNamedItem:[_args objectAtIndex:i]]; return last; } - (id)_jsfunc_setNamedItemNS:(NSArray *)_args { unsigned i, count; id last = nil; for (i = 0, count = [_args count]; i < count; i++) last = [self setNamedItemNS:[_args objectAtIndex:i]]; return last; } - (id)_jsfunc_removeNamedItem:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; return [self namedItem:[[_args objectAtIndex:0] stringValue]]; } - (id)_jsfunc_removeNamedItemNS:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) return nil; if (count == 1) return [self removeNamedItem:[[_args objectAtIndex:0] stringValue]]; else { return [self removeNamedItem:[[_args objectAtIndex:1] stringValue] namespaceURI:[[_args objectAtIndex:0] stringValue]]; } } /* description */ - (NSString *)description { NSMutableString *ms; NSEnumerator *e; id attr; ms = [NSMutableString stringWithCapacity:1024]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; [ms appendFormat:@" element=%@", self->element]; [ms appendString:@" attributes:\n"]; e = [self objectEnumerator]; while ((attr = [e nextObject]) != nil) { [ms appendString:[attr description]]; [ms appendString:@"\n"]; } [ms appendString:@">"]; return ms; } @end /* _DOMElementAttrNamedNodeMap */ SOPE/sope-xml/DOM/DOMNodeIterator.m0000644000000000000000000000372215004363604015627 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "common.h" @implementation NGDOMNodeIterator - (id)initWithRootNode:(id)_rootNode whatToShow:(unsigned long)_whatToShow filter:(id)_filter expandEntityReferences:(BOOL)_flag { NSAssert(_rootNode, @"missing root-node !"); if ((self = [super init])) { self->root = [_rootNode retain]; self->whatToShow = _whatToShow; self->filter = [_filter retain]; self->expandEntityReferences = _flag; self->lastNode = nil; self->beforeFirst = YES; self->afterLast = NO; } return self; } - (void)dealloc { [self->lastNode release]; [self->root release]; [self->filter release]; [super dealloc]; } /* attributes */ - (id)root { return self->root; } - (unsigned long)whatToShow { return self->whatToShow; } - (id)filter { return self->filter; } - (BOOL)expandEntityReferences { return self->expandEntityReferences; } /* operations */ - (id)nextNode { [self doesNotRecognizeSelector:_cmd]; return nil; } - (id)previousNode { [self doesNotRecognizeSelector:_cmd]; return nil; } - (void)detach { } @end /* NGDOMNodeIterator */ SOPE/sope-xml/DOM/DOMXMLOutputter.m0000644000000000000000000002710415004363604015624 0ustar rootroot/* Copyright (C) 2000-2009 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMXMLOutputter.h" #include "DOMDocument.h" #include "DOMElement.h" #include "common.h" @interface DOMXMLOutputter(Privates) - (void)outputNode:(id)_node to:(id)_target; - (void)outputNodeList:(id)_nodeList to:(id)_target; @end @interface DOMXMLOutputter(PrefixStack) - (NSString *)topPrefix; - (NSString *)topNamespace; - (void)pushPrefix:(NSString *)_prefix namespace:(NSString *)_namespace; - (void)popPrefixAndNamespace; - (BOOL)isTagValidInStack:(id)_node; - (NSArray *)newAttributePrefixesAndNamespaces:(NSArray *)_attrs; @end /* DOMXMLOutputter(PrefixStack) */ @implementation DOMXMLOutputter - (id)init { if ((self = [super init])) { self->stack = [[NSMutableArray alloc] initWithCapacity:32]; } return self; } - (void)dealloc { [self->stack release]; [super dealloc]; } - (void)indentOn:(id)_target { int i; for (i = 0; i < (self->indent * 4); i++) { if (_target) [_target appendString:@" "]; else fputc(' ', stdout); } } - (void)write:(NSString *)s to:(id)_target { if (_target) [_target appendString:s]; else #ifndef __APPLE__ printf("%s", [s cString]); #else printf("%s", [s UTF8String]); #endif } - (BOOL)currentElementPreservesWhitespace { return NO; } - (void)outputAttributeNode:(id)_attrNode ofNode:(id)_node to:(id)_target { if ([[_attrNode prefix] length] > 0) { [self write:[_attrNode prefix] to:_target]; [self write:@":" to:_target]; } [self write:[_attrNode name] to:_target]; if ([_attrNode hasChildNodes]) { id children; unsigned i, count; [self write:@"=\"" to:_target]; children = [_attrNode childNodes]; for (i = 0, count = [children count]; i < count; i++) { id child; child = [children objectAtIndex:i]; if ([child nodeType] == DOM_TEXT_NODE) [self write:[(id)child data] to:_target]; else NSLog(@"WARNING: unsupported attribute value node %@", child); } [self write:@"\"" to:_target]; } else NSLog(@"WARNING: attribute %@ has no content !", _attrNode); } - (void)outputAttributeNodes:(id)_nodes list:(NSArray *)_list to:(id)_target { unsigned i, count, count2; if ((count = [_nodes length]) == 0) return; // append required prefix and namespaces for (i = 0, count2 = [_list count]; i < count2; i = i + 2) { [self write:@" xmlns:" to:_target]; [self write:[_list objectAtIndex:i] to:_target]; [self write:@"=\"" to:_target]; [self write:[_list objectAtIndex:i+1] to:_target]; [self write:@"\"" to:_target]; } for (i = 0; i < count; i++) { id attrNode; attrNode = [_nodes objectAtIndex:i]; [self write:@" " to:_target]; [self outputAttributeNode:attrNode ofNode:nil to:_target]; } } - (void)outputTextNode:(id)_node to:(id)_target { NSString *s; unsigned len; s = [_node data]; if ((len = [s length]) == 0) return; if (![self currentElementPreservesWhitespace]) { unsigned i; for (i = 0; i < len; i++) { if (!isspace([s characterAtIndex:i])) break; } if (i == len) /* only whitespace */ return; [self indentOn:_target]; } [self write:[_node data] to:_target]; if (![self currentElementPreservesWhitespace]) [self write:@"\n" to:_target]; } - (void)outputCommentNode:(id)_node to:(id)_target { [self write:@"" to:_target]; if (![self currentElementPreservesWhitespace]) [self write:@"\n" to:_target]; } - (void)outputElementNode:(id)_node to:(id)_target { NSArray *list; // new attribute prefixes and namespaces NSString *tagName; NSString *ns = nil; NSString *tagURI; NSString *tagPrefix; BOOL isNodeValid; unsigned i, count; // getting new attributes prefixes and namespaces list = (NSArray *)[_node attributes]; list = [self newAttributePrefixesAndNamespaces:list]; // push new attribute prefixes and namespaces to stack for (i = 0, count = [list count]; i < count; i = i + 2) { [self pushPrefix:[list objectAtIndex:i] namespace:[list objectAtIndex:i+1]]; } tagURI = [_node namespaceURI]; tagPrefix = [_node prefix]; isNodeValid = [self isTagValidInStack:_node]; if (!isNodeValid) [self pushPrefix:tagPrefix namespace:tagURI]; /* needs to declare namespaces !!! */ tagName = [_node tagName]; if ([[_node prefix] length] > 0) { NSString *p; if (!isNodeValid) { ns = [NSString stringWithFormat:@" xmlns:%@=\"%@\"", tagPrefix, tagURI]; } p = [_node prefix]; p = [p stringByAppendingString:@":"]; tagName = [p stringByAppendingString:tagName]; } else if ([tagURI length] > 0) { id parent; BOOL addNS; addNS = YES; if ((parent = [_node parentNode])) { if ([parent nodeType] == DOM_ELEMENT_NODE) { if ([[parent namespaceURI] isEqualToString:tagURI]) { if ([[parent prefix] length] == 0) addNS = NO; } } } else addNS = YES; if (addNS) ns = [NSString stringWithFormat:@" xmlns=\"%@\"", [_node namespaceURI]]; else ns = nil; } else ns = nil; if ([_node hasChildNodes]) { [self indentOn:_target]; [self write:@"<" to:_target]; [self write:tagName to:_target]; if (ns) [self write:ns to:_target]; [self outputAttributeNodes:[_node attributes] list:list to:_target]; [self write:@">\n" to:_target]; self->indent++; [self outputNodeList:[_node childNodes] to:_target]; self->indent--; [self indentOn:_target]; [self write:@"\n" to:_target]; } else { [self indentOn:_target]; [self write:@"<" to:_target]; [self write:tagName to:_target]; [self outputAttributeNodes:[_node attributes] list:list to:_target]; [self write:@"/>\n" to:_target]; } // pop attributes prefixes and namespaces from stack for (i = 0; i < count; i = i + 2) { [self popPrefixAndNamespace]; } if (!isNodeValid) [self popPrefixAndNamespace]; } - (void)outputCDATA:(id)_node to:(id)_target { [self write:@"" to:_target]; } - (void)outputPI:(id)_node to:(id)_target { [self indentOn:_target]; [self write:@"\n" to:_target]; } - (void)outputNode:(id)_node to:(id)_target { switch ([_node nodeType]) { case DOM_ELEMENT_NODE: [self outputElementNode:(id)_node to:_target]; break; case DOM_CDATA_SECTION_NODE: [self outputCDATA:(id)_node to:_target]; break; case DOM_PROCESSING_INSTRUCTION_NODE: [self outputPI:(id)_node to:_target]; break; case DOM_TEXT_NODE: [self outputTextNode:(id)_node to:_target]; break; case DOM_COMMENT_NODE: [self outputCommentNode:(id)_node to:_target]; break; default: NSLog(@"cannot output node '%@'", _node); break; } } - (void)outputNodeList:(id)_nodeList to:(id)_target { id children; unsigned i, count; children = _nodeList; for (i = 0, count = [children count]; i < count; i++) [self outputNode:[children objectAtIndex:i] to:_target]; } - (void)outputDocument:(id)_document to:(id)_target { if (![_document hasChildNodes]) { NSLog(@"ERROR: document has no childnodes !"); return; } [self write:@"\n" to:_target]; [self->stack removeAllObjects]; [self outputNodeList:[_document childNodes] to:_target]; #if 0 NS_DURING { } NS_HANDLER abort(); NS_ENDHANDLER; #endif } @end /* DOMXMLOutputter */ @implementation DOMXMLOutputter(PrefixStack) - (void)_checkPrefixStack { NSAssert2(([self->stack count] % 2 == 0), @"%s: prefixStack is not valid (%@)!!!", __PRETTY_FUNCTION__, self->stack); } - (NSString *)topPrefix { [self _checkPrefixStack]; if ([self->stack count] == 0) return nil; return [self->stack objectAtIndex:[self->stack count] -2]; } - (NSString *)topNamespace { [self _checkPrefixStack]; if ([self->stack count] == 0) return nil; return [self->stack lastObject]; } - (void)pushPrefix:(NSString *)_prefix namespace:(NSString *)_namespace { [self _checkPrefixStack]; [self->stack addObject:(_prefix) ? _prefix : (NSString *)@""]; [self->stack addObject:(_namespace) ? _namespace : (NSString *)@""]; } - (void)popPrefixAndNamespace { [self _checkPrefixStack]; NSAssert1(([self->stack count] > 0), @"%s: prefixStack.count == 0", __PRETTY_FUNCTION__); [self->stack removeLastObject]; // namespace [self->stack removeLastObject]; // prefix } - (BOOL)isTagValidInStack:(id)_node { NSString *nodeNamespace; NSString *nodePrefix; int i; nodePrefix = [_node prefix]; nodeNamespace = [_node namespaceURI]; for (i = [self->stack count]; i >= 2; i = i - 2) { NSString *namespace; NSString *prefix; prefix = [self->stack objectAtIndex:i-2]; namespace = [self->stack objectAtIndex:i-1]; if ([nodePrefix isEqualToString:prefix] && [nodeNamespace isEqualToString:namespace]) return YES; } return NO; } - (NSArray *)newAttributePrefixesAndNamespaces:(NSArray *)_attrs { NSMutableArray *result; int i, j, count; count = [_attrs count]; if (count == 0) return [NSArray array]; result = [[NSMutableArray alloc] initWithCapacity:count]; for (j = 0; j < count; j++) { id attr; NSString *attrNamespace; NSString *attrPrefix; BOOL didMatch = NO; attr = [_attrs objectAtIndex:j]; attrNamespace = [attr namespaceURI]; attrPrefix = [attr prefix]; attrNamespace = (attrNamespace) ? attrNamespace : (NSString *)@""; attrPrefix = (attrPrefix) ? attrPrefix : (NSString *)@""; if (([attrNamespace length] == 0 && [attrPrefix length] == 0)) continue; for (i = [self->stack count]; i >= 2; i = i - 2) { NSString *namespace; NSString *prefix; prefix = [self->stack objectAtIndex:i-2]; namespace = [self->stack objectAtIndex:i-1]; if ([attrPrefix isEqualToString:prefix] && [attrNamespace isEqualToString:namespace]) { didMatch = YES; break; } } if (didMatch == NO) { [result addObject:attrPrefix]; [result addObject:attrNamespace]; } } return [result autorelease]; } @end /* DOMXMLOutputter(PrefixStack) */ SOPE/sope-xml/DOM/DOMDocumentFragment.h0000644000000000000000000000242515004363604016464 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMDocumentFragment_H__ #define __DOMDocumentFragment_H__ #include @class NSString; @class NGDOMImplementation; @interface NGDOMDocumentFragment : NGDOMNodeWithChildren < DOMDocumentFragment > { } @end @interface NGDOMDocumentFragment(PrivateCtors) /* use DOMImplementation for constructing DOMDocumentFragment's ! */ - (id)initWithName:(NSString *)_name publicId:(NSString *)_p systemId:(NSString *)_s dom:(NGDOMImplementation *)_dom; @end #endif /* __DOMDocumentFragment_H__ */ SOPE/sope-xml/DOM/DOMPYXOutputter.h0000644000000000000000000000177115004363604015641 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMPYXOutputter_H__ #define __DOMPYXOutputter_H__ #import @interface NGDOMPYXOutputter : NSObject { } - (void)outputDocument:(id)_document to:(id)_target; @end #endif /* __DOMPYXOutputter_H__ */ SOPE/sope-xml/DOM/DOMAttribute.h0000644000000000000000000000474215004363604015171 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMAttribute_H__ #define __DOMAttribute_H__ #include /* Why is Attr a Node? Can it have children? Can it be a child? Attr is a Node because its value is actually carried by its children, which may be a mixture of Text and EntityReference nodes, and because making it a Node allows us to store it in a NamedNodeMap for easy retrieval. The getAttribute method hides this detail by returning a string representing the concatenation of all these children, and similarly setAttribute replaces the Attr's contents with a single Text node holding the new string. To create or manipulate other children of an Attr, you have to access the Attr node directly via the getAttributeNode and setAttributeNode methods, or by retrieving it from the element's "attributes" NamedNodeMap. Section 1.1.1 of the Level 1 DOM Recommendation gives a list of which nodes can be parents and children of which other nodes. Attr is not a legal child of any node, so attempts to insert it as one will throw a DOMException (HIERARCHY_REQUEST_ERR). Note that: parentNode, nextSibling, previousSibling always return nil !!! */ @interface NGDOMAttribute : NGDOMNodeWithChildren < DOMAttr > { id element; NSString *name; NSString *namespaceURI; NSString *prefix; BOOL isSpecified; NSString *value; } @end @interface NGDOMAttribute(PrivateCtors) /* use DOMDocument for constructing DOMAttributes ! */ - (id)initWithName:(NSString *)_name; - (id)initWithName:(NSString *)_name namespaceURI:(NSString *)_uri; @end @interface NGDOMAttribute(ObjCValues) - (NSString *)stringValue; - (int)intValue; - (double)doubleValue; @end /* DOMAttribute(Values) */ #endif /* __DOMAttribute_H__ */ SOPE/sope-xml/DOM/DOMDocumentFragment.m0000644000000000000000000000302115004363604016462 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMDocumentFragment.h" #include "common.h" @implementation NGDOMDocumentFragment /* node */ - (BOOL)_isValidChildNode:(id)_node { switch ([_node nodeType]) { case DOM_ELEMENT_NODE: case DOM_PROCESSING_INSTRUCTION_NODE: case DOM_COMMENT_NODE: case DOM_TEXT_NODE: case DOM_CDATA_SECTION_NODE: case DOM_ENTITY_REFERENCE_NODE: return YES; default: return NO; } } - (DOMNodeType)nodeType { return DOM_DOCUMENT_FRAGMENT_NODE; } - (id)attributes { return nil; } /* parent node */ - (id)parentNode { return nil; } - (id)nextSibling { return nil; } - (id)previousSibling { return nil; } @end /* NGDOMDocumentFragment */ SOPE/sope-xml/DOM/DOMNotation.m0000644000000000000000000000257115004363604015024 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMNotation.h" @implementation NGDOMNotation - (DOMNodeType)nodeType { return DOM_NOTATION_NODE; } - (BOOL)_isValidChildNode:(id)_node { return NO; } - (BOOL)hasChildNodes { return NO; } - (id)childNodes { return nil; } - (id)appendChild:(id)_node { return nil; } - (id)attributes { return nil; } /* parent node */ - (id)parentNode { return nil; } - (id)nextSibling { return nil; } - (id)previousSibling { return nil; } @end /* NGDOMNotation */ SOPE/sope-xml/DOM/DOMDocument.h0000644000000000000000000000365715004363604015010 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMDocument_H__ #define __DOMDocument_H__ #include @class NSString, NSArray; @class NGDOMImplementation; @interface NGDOMDocument : NGDOMNodeWithChildren < DOMDocument > { NSString *qname; NSString *uri; id doctype; NGDOMImplementation *dom; NSArray *errors; NSArray *warnings; } + (id)documentFromData:(NSData *)_data; + (id)documentFromString:(NSString *)_string; + (id)documentFromURI:(NSString *)_uri; /* errors/warnings */ - (void)addErrors:(NSArray *)_errors; - (void)addWarnings:(NSArray *)_errors; @end @interface NGDOMDocument(DocumentTraversal) - (id)createNodeIterator:(id)_node whatToShow:(unsigned long)_whatToShow filter:(id)_filter; - (id)createTreeWalker:(id)_node whatToShow:(unsigned long)_whatToShow filter:(id)_filter expandEntityReferences:(BOOL)_expandEntityReferences; @end @interface NGDOMDocument(PrivateCtors) /* use DOMImplementation for constructing DOMDocument ! */ - (id)initWithName:(NSString *)_qname namespaceURI:(NSString *)_uri documentType:(id)_doctype dom:(NGDOMImplementation *)_dom; @end #endif /* __DOMDocument_H__ */ SOPE/sope-xml/DOM/DOMNodeWalker.m0000644000000000000000000000605515004363604015265 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMNodeWalker.h" #include "DOMNode.h" #include "common.h" @interface NGDOMNodeWalker(Privates) - (void)_processCurrentNode; @end @implementation NGDOMNodeWalker - (id)initWithTarget:(id)_target selector:(SEL)_selector context:(id)_ctx { self->target = [_target retain]; self->selector = _selector; self->ctx = [_ctx retain]; if (self->target == nil) { [self release]; return nil; } if (self->selector == NULL) { [self release]; return nil; } return self; } - (void)dealloc { [self->ctx release]; [self->rootNode release]; [self->target release]; [super dealloc]; } /* accessors */ - (id)context { return self->ctx; } - (id)rootNode { return self->rootNode; } - (id)currentParentNode { return self->currentParentNode; } - (id)currentNode { return self->currentNode; } /* private */ - (void)_processCurrentNode { [self->target performSelector:self->selector withObject:self]; } - (void)_beforeChildren { } - (void)_afterChildren { } - (void)_walkNodeUsingChildNodes:(id)_node { if (self->isStopped) return; self->currentNode = _node; [self _beforeChildren]; if (self->isStopped) return; if ([_node hasChildNodes]) { id children; unsigned i, count; id oldParent; oldParent = self->currentParentNode; self->currentParentNode = self->currentNode; children = [_node childNodes]; for (i = 0, count = [children count]; i < count; i++) { [self _walkNodeUsingChildNodes:[children objectAtIndex:i]]; if (self->isStopped) return; } self->currentParentNode = oldParent; } [self _afterChildren]; if (self->isStopped) return; } /* public */ - (void)walkNode:(id)_node { self->rootNode = [_node retain]; self->isStopped = NO; self->currentParentNode = nil; [self _walkNodeUsingChildNodes:_node]; [self->rootNode release]; self->rootNode = nil; } - (void)stopWalking { self->isStopped = YES; } @end /* NGDOMNodeWalker */ @implementation NGDOMNodePreorderWalker - (void)_beforeChildren { [self _processCurrentNode]; } - (void)_afterChildren { } @end /* NGDOMNodePreorderWalker */ @implementation NGDOMNodePostorderWalker - (void)_beforeChildren { } - (void)_afterChildren { [self _processCurrentNode]; } @end /* NGDOMNodePreorderWalker */ SOPE/sope-xml/DOM/DOM-Info.plist0000644000000000000000000000132715004363604015076 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable DOM CFBundleGetInfoString CFBundleIdentifier org.OpenGroupware.SOPE.xml.DOM CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType FMWK CFBundleShortVersionString CFBundleSignature ???? CFBundleVersion 4.5 SOPE/sope-xml/DOM/DOMText.m0000644000000000000000000000322615004363604014153 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMText.h" @interface NSObject(UsedFdExt) - (id)doesNotRecognizeSelector:(SEL)_sel; @end @implementation NGDOMText /* node */ - (DOMNodeType)nodeType { return DOM_TEXT_NODE; } - (BOOL)_isValidChildNode:(id)_node { return NO; } - (BOOL)hasChildNodes { return NO; } - (id)childNodes { return nil; } - (id)appendChild:(id)_node { return nil; } - (id)attributes { return nil; } - (id)splitText:(NSUInteger)_offset { [self doesNotRecognizeSelector:_cmd]; return nil; } /* Level 3 Methods */ - (BOOL)isWhitespaceInElementContent { return NO; } - (NSString *)wholeText { [self doesNotRecognizeSelector:_cmd]; return nil; } - (id)replaceWholeText:(NSString *)_content { [self doesNotRecognizeSelector:_cmd]; return nil; } @end /* NGDOMText */ SOPE/sope-xml/DOM/DOMProcessingInstruction.h0000644000000000000000000000253015004363604017575 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMProcessingInstruction_H__ #define __DOMProcessingInstruction_H__ #include @class NSString; @interface NGDOMProcessingInstruction : NGDOMNode { id parent; NSString *target; NSString *data; } /* attributes */ - (NSString *)target; - (void)setData:(NSString *)_data; - (NSString *)data; /* node */ @end @interface NGDOMProcessingInstruction(PrivateCtors) /* use DOMDocument for constructing DOMProcessingInstructions ! */ - (id)initWithTarget:(NSString *)_target data:(NSString *)_data; @end #endif /* __DOMProcessingInstruction_H__ */ SOPE/sope-xml/DOM/NSObject+QPEval.m0000644000000000000000000001352015004363604015460 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSObject+QPEval.h" #include "common.h" @interface NSObject(QPEvalPrivates) - (NSArray *)evaluateQueryPathComponent:(NSString *)_pc inContext:(id)_ctx; - (NSArray *)evaluateQueryPathComponents:(NSArray *)_pcs; - (void)takeValue:(id)_value forQueryPath:(NSString *)_qp; - (id)valueForQueryPath:(NSString *)_qp; - (NSException *)setQueryPathValue:(id)_value; - (id)queryPathValue; @end /* NSObject(QPEval) */ @implementation NSString(QP) - (NSArray *)queryPathComponents { NSMutableArray *pc; unsigned i, len, s; if ([self rangeOfString:@"/"].length == 0) return [NSArray arrayWithObject:self]; if ([self isEqualToString:@"/"]) return [NSArray arrayWithObject:self]; pc = [NSMutableArray arrayWithCapacity:8]; len = [self length]; i = 0; /* add root, if absolute path */ if ([self characterAtIndex:0] == '/') { i++; [pc addObject:@"/"]; } for (s = i; i < len; i++) { if ([self characterAtIndex:i] == '/') { unsigned plen; NSString *p; plen = (i - s); p = [self substringWithRange:NSMakeRange(s, plen)]; [pc addObject:p]; s = (i + 1); /* next component begins at idx right after '/' .. */ } else if ([self characterAtIndex:i] == '{') { unsigned j; for (j = (i + 1); j < len; j++) { if ([self characterAtIndex:j] == '}') { /* continue after closing brace .. */ i = j; break; } } } } if (s < i) { NSString *p; p = [self substringWithRange:NSMakeRange(s, (i - s))]; [pc addObject:p]; } return pc; } @end /* NSString(QP) */ @implementation NSObject(QPEval) /* special expressions */ - (id)queryPathRootObjectInContext:(id)_ctx { return self; } /* query path evaluation */ - (NSArray *)evaluateQueryPathComponent:(NSString *)_pc inContext:(id)_ctx { unsigned len; NSArray *result; result = nil; if ((len = [_pc length]) == 0) return nil; else if (len == 1) { unichar c; c = [_pc characterAtIndex:0]; if (c == '/') { id root = [self queryPathRootObjectInContext:_ctx]; result = root ? [NSArray arrayWithObject:root] : nil; } else if (c == '.') result = [NSArray arrayWithObject:self]; } else { } NSLog(@"0x%p<%@> eval QP '%@': %@", self, NSStringFromClass([self class]), _pc, result); return result; } - (NSArray *)queryPathCursorArray { return [NSArray arrayWithObject:self]; } - (NSArray *)evaluateQueryPathComponents:(NSArray *)_pcs { NSEnumerator *pcs; NSString *pc; NSAutoreleasePool *pool; NSArray *array; NSMutableDictionary *ctx; pool = [[NSAutoreleasePool alloc] init]; ctx = [NSMutableDictionary dictionaryWithCapacity:16]; NSLog(@"eval PCs: %@", _pcs); array = [self queryPathCursorArray]; pcs = [_pcs objectEnumerator]; while ((array != nil) && (pc = [pcs nextObject])) { if ((array = [array evaluateQueryPathComponent:pc inContext:ctx]) == nil) break; } array = [array retain]; [pool release]; return [array autorelease]; } - (NSArray *)evaluateQueryPath:(NSString *)_path { if ([_path rangeOfString:@"/"].length == 0) return [self evaluateQueryPathComponents:[NSArray arrayWithObject:_path]]; if ([_path isEqualToString:@"/"]) { static NSArray *rootElem = nil; if (rootElem == nil) rootElem = [NSArray arrayWithObject:@"/"]; return [self evaluateQueryPathComponents:rootElem]; } return [self evaluateQueryPathComponents:[_path queryPathComponents]]; } /* query KVC */ - (NSException *)setQueryPathValue:(id)_value { if (_value == self) return nil; return [NSException exceptionWithName:@"QueryPathEvalException" reason:@"cannot set query-path value on object" userInfo:nil]; } - (id)queryPathValue { return self; } - (void)takeValue:(id)_value forQueryPath:(NSString *)_qp { [[[self evaluateQueryPath:_qp] setQueryPathValue:_value] raise]; } - (id)valueForQueryPath:(NSString *)_qp { return [[self evaluateQueryPath:_qp] queryPathValue]; } @end /* NSObject(QPEval) */ @implementation NSArray(QPEval) - (NSArray *)queryPathCursorArray { return self; } - (NSArray *)evaluateQueryPathComponent:(NSString *)_pc inContext:(id)_ctx { unsigned i, j, count; NSArray *array; id *objs; if ((count = [self count]) == 0) return [NSArray array]; objs = calloc(count + 1, sizeof(id)); for (i = 0, j = 0; i < count; i++) { id obj; obj = [self objectAtIndex:i]; obj = [obj evaluateQueryPathComponent:_pc inContext:_ctx]; if (obj) { objs[j] = obj; j++; } } array = [NSArray arrayWithObjects:objs count:j]; if (objs) free(objs); return array; } @end /* NSArray(QPEval) */ @implementation NSSet(QPEval) - (NSArray *)evaluateQueryPathComponent:(NSString *)_pc inContext:(id)_ctx { return [[self allObjects] evaluateQueryPathComponent:_pc inContext:(id)_ctx]; } - (NSArray *)evaluateQueryPathComponents:(NSArray *)_pcs { return [[self allObjects] evaluateQueryPathComponents:_pcs]; } @end /* NSSet(QPEval) */ SOPE/sope-xml/DOM/DOMSaxHandler.m0000644000000000000000000002530515004363604015262 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMSaxHandler.h" #include "DOMImplementation.h" #include "DOMDocument.h" #include "DOMElement.h" #include "common.h" #include @interface NSObject(LineInfoProtocol) - (void)setLine:(int)_line; @end @implementation DOMSaxHandler static BOOL printErrors = NO; - (id)initWithDOMImplementation:(id)_domImpl { if ((self = [super init])) { self->dom = [_domImpl retain]; self->maxErrorCount = 100; // this also includes NPSOBJ in HTML ! } return self; } - (id)init { static id idom = nil; if (idom == nil) idom = [[NGDOMImplementation alloc] init]; return [self initWithDOMImplementation:idom]; } - (void)dealloc { [self->document release]; [self->dom release]; [self->locator release]; [self->fatals release]; [self->errors release]; [self->warnings release]; [super dealloc]; } - (void)setDocumentLocator:(id)_loc { ASSIGN(self->locator, _loc); } - (id)document { return self->document; } - (void)clear { ASSIGN(self->document, (id)nil); [self->fatals removeAllObjects]; [self->errors removeAllObjects]; [self->warnings removeAllObjects]; self->errorCount = 0; } - (int)errorCount { return self->errorCount; } - (int)fatalErrorCount { return [self->fatals count]; } - (int)warningCount { return [self->warnings count]; } - (int)maxErrorCount { return self->maxErrorCount; } - (NSArray *)warnings { return [[self->warnings copy] autorelease]; } - (NSArray *)errors { return [[self->errors copy] autorelease]; } - (NSArray *)fatalErrors { return [[self->fatals copy] autorelease]; } /* attributes */ - (id)_nodeForSaxAttrWithName:(NSString *)_name namespace:(NSString *)_uri rawName:(NSString *)_rawName type:(NSString *)_saxType value:(NSString *)_saxValue { id attr; NSString *nsPrefix; attr = [self->document createAttribute:_name namespaceURI:_uri]; if (attr == nil) return nil; nsPrefix = nil; if (_uri) { NSRange r; r = [_rawName rangeOfString:@":"]; if (r.length > 0) nsPrefix = [_rawName substringToIndex:r.location]; } if (nsPrefix) [attr setPrefix:nsPrefix]; /* add content to attribute */ if ([_saxType isEqualToString:@"CDATA"] || (_saxType == nil)) { id content; NSAssert(self->document, @"missing document object"); if ((content = [self->document createTextNode:_saxValue])) [attr appendChild:content]; else NSLog(@"couldn't create text node !"); } else NSLog(@"unsupported sax attr type '%@' !", _saxType); return attr; } /* document */ - (void)startDocument { id docType; [self->document release]; self->document = nil; self->errorCount = 0; self->tagDepth = 0; docType = [self->dom createDocumentType:nil publicId:[self->locator publicId] systemId:[self->locator systemId]]; self->document = [self->dom createDocumentWithName:nil namespaceURI:nil documentType:docType]; self->document = [self->document retain]; //NSLog(@"started doc: %@", self->document); self->currentElement = self->document; } - (void)endDocument { self->currentElement = nil; } - (void)startPrefixMapping:(NSString *)_prefix uri:(NSString *)_uri { //printf("ns-map: %s=%s\n", [_prefix cString], [_uri cString]); } - (void)endPrefixMapping:(NSString *)_prefix { //printf("ns-unmap: %s\n", [_prefix cString]); } - (void)startElement:(NSString *)_localName namespace:(NSString *)_ns rawName:(NSString *)_rawName attributes:(id)_attrs { id elem; NSString *nsPrefix; self->tagDepth++; elem = [self->document createElement:_localName namespaceURI:_ns]; if (elem == nil) { NSLog(@"%s: couldn't create element for tag '%@'", __PRETTY_FUNCTION__, _rawName); return; } if ([elem respondsToSelector:@selector(setLine:)]) [elem setLine:[self->locator lineNumber]]; if (_ns) { NSRange r; r = [_rawName rangeOfString:@":"]; nsPrefix = (r.length > 0) ? [_rawName substringToIndex:r.location] : (NSString *)nil; } else nsPrefix = nil; if (nsPrefix) [elem setPrefix:nsPrefix]; NSAssert(self->currentElement, @"no current element !"); [self->currentElement appendChild:elem]; self->currentElement = elem; /* process attributes */ { unsigned i, count; for (i = 0, count = [_attrs count]; i < count; i++) { id attr; // NSLog(@"attr %@", [_attrs nameAtIndex:i]); attr = [self _nodeForSaxAttrWithName:[_attrs nameAtIndex:i] namespace:[_attrs uriAtIndex:i] rawName:[_attrs rawNameAtIndex:i] type:[_attrs typeAtIndex:i] value:[_attrs valueAtIndex:i]]; if (attr == nil) { NSLog(@"couldn't create attribute for SAX attr %@, element %@", attr, elem); continue; } /* add node to element */ if ([elem setAttributeNodeNS:attr] == nil) NSLog(@"couldn't add attribute %@ to element %@", attr, elem); } } } - (void)endElement:(NSString *)_localName namespace:(NSString *)_ns rawName:(NSString *)_rawName { id parent; parent = [self->currentElement parentNode]; #if DEBUG NSAssert1(parent, @"no parent for current element %@ !", self->currentElement); #endif self->currentElement = parent; self->tagDepth--; } - (void)characters:(unichar *)_chars length:(NSUInteger)_len { id charNode; NSString *data; data = [[NSString alloc] initWithCharacters:_chars length:_len]; charNode = [self->document createTextNode:data]; [data release]; data = nil; [self->currentElement appendChild:charNode]; } - (void)ignorableWhitespace:(unichar *)_chars length:(NSUInteger)_len { } - (void)processingInstruction:(NSString *)_pi data:(NSString *)_data { id piNode; piNode = [self->document createProcessingInstruction:_pi data:_data]; [self->currentElement appendChild:piNode]; } #if 0 - (xmlEntityPtr)getEntity:(NSString *)_name { NSLog(@"get entity %@", _name); return NULL; } - (xmlEntityPtr)getParameterEntity:(NSString *)_name { NSLog(@"get para entity %@", _name); return NULL; } #endif /* lexical handler */ - (void)comment:(unichar *)_chars length:(int)_len { id commentNode; NSString *data; if (_len == 0) return; data = [[NSString alloc] initWithCharacters:_chars length:_len]; commentNode = [self->document createComment:data]; [data release]; data = nil; [self->currentElement appendChild:commentNode]; } - (void)startDTD:(NSString *)_name publicId:(NSString *)_pub systemId:(NSString *)_sys { self->inDTD = YES; } - (void)endDTD { self->inDTD = NO; } - (void)startCDATA { self->inCDATA = YES; } - (void)endCDATA { self->inCDATA = NO; } /* entities */ - (id)resolveEntityWithPublicId:(NSString *)_pubId systemId:(NSString *)_sysId { NSLog(@"shall resolve entity with '%@' '%@'", _pubId, _sysId); return nil; } /* errors */ - (void)warning:(SaxParseException *)_exception { NSString *sysId; int line; sysId = [[_exception userInfo] objectForKey:@"systemId"]; line = [[[_exception userInfo] objectForKey:@"line"] intValue]; NSLog(@"DOM XML WARNING(%@:%i): %@", sysId, line, [_exception reason]); if (self->warnings == nil) self->warnings = [[NSMutableArray alloc] initWithCapacity:32]; if (_exception) [self->warnings addObject:_exception]; } - (void)error:(SaxParseException *)_exception { self->errorCount++; if (printErrors) { NSString *sysId; int line; sysId = [[_exception userInfo] objectForKey:@"systemId"]; line = [[[_exception userInfo] objectForKey:@"line"] intValue]; NSLog(@"DOM XML ERROR(%@:%i[%@]): %@ (errcount=%i,max=%i)", sysId, line, [[_exception userInfo] objectForKey:@"parser"], [_exception reason], self->errorCount, self->maxErrorCount); } if (self->errors == nil) self->errors = [[NSMutableArray alloc] initWithCapacity:32]; if (_exception) [self->errors addObject:_exception]; } - (void)fatalError:(SaxParseException *)_exception { NSString *sysId; int line; sysId = [[_exception userInfo] objectForKey:@"systemId"]; line = [[[_exception userInfo] objectForKey:@"line"] intValue]; NSLog(@"DOM XML FATAL(%@:%i[%@]): %@", sysId, line, [[_exception userInfo] objectForKey:@"parser"], [_exception reason]); if (self->fatals == nil) self->fatals = [[NSMutableArray alloc] initWithCapacity:32]; if (_exception) [self->fatals addObject:_exception]; [_exception raise]; } /* DTD */ - (void)notationDeclaration:(NSString *)_name publicId:(NSString *)_pubId systemId:(NSString *)_sysId { NSLog(@"decl: notation %@ pub=%@ sys=%@", _name, _pubId, _sysId); } - (void)unparsedEntityDeclaration:(NSString *)_name publicId:(NSString *)_pubId systemId:(NSString *)_sysId notationName:(NSString *)_notName { NSLog(@"decl: unparsed entity %@ pub=%@ sys=%@ not=%@", _name, _pubId, _sysId, _notName); } /* decl */ - (void)attributeDeclaration:(NSString *)_attributeName elementName:(NSString *)_elementName type:(NSString *)_type defaultType:(NSString *)_defType defaultValue:(NSString *)_defValue { NSLog(@"decl: attr %@[%@] type '%@' default '%@'[%@]", _attributeName, _elementName, _type, _defValue, _defType); } - (void)elementDeclaration:(NSString *)_name contentModel:(NSString *)_model { NSLog(@"decl: element %@ model %@", _name, _model); } - (void)externalEntityDeclaration:(NSString *)_name publicId:(NSString *)_pub systemId:(NSString *)_sys { NSLog(@"decl: e-entity %@ pub %@ sys %@", _name, _pub, _sys); } - (void)internalEntityDeclaration:(NSString *)_name value:(NSString *)_value { NSLog(@"decl: i-entity %@ value %@", _name, _value); } @end /* DOMSaxHandler */ @implementation DOMSaxHandler(SubHandler) - (NSUInteger)tagDepth { return self->tagDepth; } - (id)object { return [self document]; } - (void)setNamespaces:(NSString *)_namespaces { // not yet implemented } @end /* DOMSaxHandler(SubHandler) */ SOPE/sope-xml/DOM/DOMNodeFilter.h0000644000000000000000000000341215004363604015252 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMNodeFilter_H__ #define __DOMNodeFilter_H__ #import typedef enum { DOM_FILTER_ACCEPT = 1, DOM_FILTER_REJECT = 2, DOM_FILTER_SKIP = 3 } DOMNodeFilterType; /* constants for whatToShow */ #define DOM_SHOW_ALL 0xFFFFFFFF #define DOM_SHOW_ELEMENT 0x00000001 #define DOM_SHOW_ATTRIBUTE 0x00000002 #define DOM_SHOW_TEXT 0x00000004 #define DOM_SHOW_CDATA_SECTION 0x00000008 #define DOM_SHOW_ENTITY_REFERENCE 0x00000010 #define DOM_SHOW_ENTITY 0x00000020 #define DOM_SHOW_PROCESSING_INSTRUCTION 0x00000040 #define DOM_SHOW_COMMENT 0x00000080 #define DOM_SHOW_DOCUMENT 0x00000100 #define DOM_SHOW_DOCUMENT_TYPE 0x00000200 #define DOM_SHOW_DOCUMENT_FRAGMENT 0x00000400 #define DOM_SHOW_NOTATION 0x00000800 @interface NGDOMNodeFilter : NSObject - (DOMNodeFilterType)acceptNode:(id)_node; @end #endif /* __DOMNodeFilter_H__ */ SOPE/sope-xml/DOM/COPYRIGHT0000644000000000000000000000010615004363604013776 0ustar rootrootCopyright (C) 2000-2005 SKYRIX Software AG Contact: info@skyrix.com SOPE/sope-xml/DOM/DOMProtocols.h0000644000000000000000000001622215004363604015206 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOM_DOMProtocols_H__ #define __DOM_DOMProtocols_H__ /* Protocols for DOM objects ... IDL taken from http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010913/DOM3-Core.html */ typedef enum { DOM_UNKNOWN_NODE = 0, DOM_ATTRIBUTE_NODE = 1, DOM_CDATA_SECTION_NODE = 2, DOM_COMMENT_NODE = 3, DOM_DOCUMENT_FRAGMENT_NODE = 4, DOM_DOCUMENT_NODE = 5, DOM_DOCUMENT_TYPE_NODE = 6, DOM_ELEMENT_NODE = 7, DOM_ENTITY_NODE = 8, DOM_ENTITY_REFERENCE_NODE = 9, DOM_NOTATION_NODE = 10, DOM_PROCESSING_INSTRUCTION_NODE = 11, DOM_TEXT_NODE = 12 } DOMNodeType; // TODO: find out which GCC version started to have forward protocols decls ... //#define HAVE_FORWARD_PROTOCOLS 1 #if HAVE_FORWARD_PROTOCOLS @protocol DOMNode; @protocol DOMAttr, DOMCDATASection, DOMComment, DOMDocumentFragment; @protocol DOMDocument, DOMDocumentType, DOMElement, DOMEntity; @protocol DOMEntityReference, DOMNotation, DOMProcessingInstruction; @protocol DOMText; // NOTE: _ONLY_ use those defines for forward declarations! #define IDOMNode id #define IDOMDocument id #define IDOMElement id #else #define IDOMNode id #define IDOMDocument id #define IDOMElement id #endif @protocol DOMNodeList - (NSUInteger)length; - (id)objectAtIndex:(NSUInteger)_idx; // returns the proper attribute node @end /* DOMNodeList */ @protocol DOMNamedNodeMap - (NSUInteger)length; - (id)objectAtIndex:(NSUInteger)_idx; // returns the proper attribute node - (IDOMNode)namedItem:(NSString *)_name; - (IDOMNode)setNamedItem:(IDOMNode)_node; - (IDOMNode)removeNamedItem:(NSString *)_name; /* DOM2 access */ - (IDOMNode)namedItem:(NSString *)_name namespaceURI:(NSString *)_uri; - (IDOMNode)setNamedItemNS:(IDOMNode)_node; - (IDOMNode)removeNamedItem:(NSString *)_name namespaceURI:(NSString *)_uri; @end /* DOMNamedNodeMap */ @protocol DOMNode - (DOMNodeType)nodeType; - (NSString *)nodeName; - (NSString *)nodeValue; - (NSString *)localName; - (NSString *)namespaceURI; - (void)setPrefix:(NSString *)_prefix; - (NSString *)prefix; /* element attributes */ - (id)attributes; /* navigation */ - (id)parentNode; - (id)previousSibling; - (id)nextSibling; - (id)childNodes; - (BOOL)hasChildNodes; - (id)firstChild; - (id)lastChild; /* modification */ - (id)appendChild:(id)_node; - (id)removeChild:(id)_node; /* owner */ - (IDOMDocument)ownerDocument; @end /* DOMNode */ @protocol DOMDocumentFragment < DOMNode > @end @protocol DOMAttr < DOMNode > - (NSString *)name; - (BOOL)specified; - (void)setValue:(NSString *)_value; - (NSString *)value; /* owner */ - (IDOMElement)ownerElement; @end /* DOMAttr */ @protocol DOMCharacterData < DOMNode > - (void)setData:(NSString *)_data; - (NSString *)data; - (NSUInteger)length; - (NSString *)substringData:(NSUInteger)_offset count:(NSUInteger)_count; - (void)appendData:(NSString *)_data; - (void)insertData:(NSString *)_data offset:(NSUInteger)_offset; - (void)deleteData:(NSUInteger)_offset count:(NSUInteger)_count; - (void)replaceData:(NSUInteger)_offs count:(NSUInteger)_count with:(NSString *)_s; @end /* DOMCharacterData */ @protocol DOMComment < DOMCharacterData > @end /* DOMComment */ @protocol DOMText < DOMCharacterData > - (id)splitText:(NSUInteger)_offset; /* DOM Level 3 */ - (BOOL)isWhitespaceInElementContent; - (NSString *)wholeText; - (id)replaceWholeText:(NSString *)_content; @end @protocol DOMCDATASection < DOMText > @end @protocol DOMElement < DOMNode > /* attributes */ - (NSString *)tagName; /* lookup */ - (id)getElementsByTagName:(NSString *)_tagName; - (id)getElementsByTagName:(NSString *)_tagName namespaceURI:(NSString *)_uri; /* element attributes */ - (BOOL)hasAttribute:(NSString *)_attrName; - (BOOL)hasAttribute:(NSString *)_localName namespaceURI:(NSString *)_ns; - (void)setAttribute:(NSString *)_attrName value:(NSString *)_value; - (void)setAttribute:(NSString *)_localName namespaceURI:(NSString *)_ns value:(NSString *)_value; - (NSString *)attribute:(NSString *)_attrName; - (NSString *)attribute:(NSString *)_localName namespaceURI:(NSString *)_ns; - (void)removeAttribute:(NSString *)_attrName; - (void)removeAttribute:(NSString *)_attrName namespaceURI:(NSString *)_ns; - (id)setAttributeNode:(id)_attrNode; - (id)removeAttributeNode:(id)_attrNode; - (id)setAttributeNodeNS:(id)_attrNode; - (id)removeAttributeNodeNS:(id)_attrNode; @end /* DOMElement */ @protocol DOMDocumentType < DOMNode > @end /* DOMDocumentType */ @protocol DOMProcessingInstruction < DOMNode > - (NSString *)target; - (NSString *)data; @end /* DOMProcessingInstruction */ @protocol DOMEntityReference < DOMNode > @end @class NGDOMImplementation; @protocol DOMDocument < DOMNode > - (id)doctype; - (NGDOMImplementation *)implementation; - (id)documentElement; - (id)getElementsByTagName:(NSString *)_tagName; - (id)getElementsByTagName:(NSString *)_tagName namespaceURI:(NSString *)_uri; - (id)getElementById:(NSString *)_eid; /* creation */ - (id)createElement:(NSString *)_tagName; - (id)createElement:(NSString *)_tagName namespaceURI:(NSString *)_uri; - (id)createDocumentFragment; - (id)createTextNode:(NSString *)_data; - (id)createComment:(NSString *)_data; - (id)createCDATASection:(NSString *)_data; - (id) createProcessingInstruction:(NSString *)_target data:(NSString *)_data; - (id)createAttribute:(NSString *)_name; - (id)createAttribute:(NSString *)_name namespaceURI:(NSString *)_uri; - (id)createEntityReference:(NSString *)_name; @end /* DOMDocument */ #endif /* __DOM_DOMProtocols_H__ */ SOPE/sope-xml/DOM/DOMCDATASection.h0000644000000000000000000000207615004363604015365 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMCDATASection_H__ #define __DOMCDATASection_H__ #include @interface NGDOMCDATASection : NGDOMText < DOMCDATASection > { } @end @interface NGDOMCDATASection(PrivateCtors) /* use DOMDocument for constructing DOMCDATASection's ! */ @end #endif /* __DOMCDATASection_H__ */ SOPE/sope-xml/DOM/DOMAttribute.m0000644000000000000000000001021515004363604015166 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMAttribute.h" #include "DOMDocument.h" #include "common.h" @implementation NGDOMAttribute - (id)initWithName:(NSString *)_name namespaceURI:(NSString *)_uri { if ((self = [super init])) { self->name = [_name copy]; self->namespaceURI = [_uri copy]; } return self; } - (id)initWithName:(NSString *)_name { return [self initWithName:_name namespaceURI:nil]; } - (void)dealloc { [self->prefix release]; [self->name release]; [self->namespaceURI release]; [super dealloc]; } /* element tracking */ - (void)_domNodeRegisterParentNode:(id)_element { self->element = _element; } - (void)_domNodeForgetParentNode:(id)_element { if (_element == self->element) self->element = nil; } /* attributes */ - (IDOMElement)ownerElement { return self->element; } - (IDOMDocument)ownerDocument { return [[self ownerElement] ownerDocument]; } - (BOOL)specified { return self->isSpecified; } - (NSString *)name { return self->name; } - (NSString *)namespaceURI { return self->namespaceURI; } - (void)setPrefix:(NSString *)_prefix { id old = self->prefix; self->prefix = [_prefix copy]; [old release]; } - (NSString *)prefix { return self->prefix; } - (void)setValue:(NSString *)_value { id child; self->isSpecified = YES; /* remove all existing children */ while ((child = [self lastChild])) [self removeChild:child]; child = [[self ownerDocument] createTextNode:_value]; NSAssert1(child, @"couldn't create text-node child for value '%@' !", _value); [self appendChild:child]; } - (NSString *)_stringValueOfChildNode:(id)_node { return [_node nodeValue]; } - (NSString *)value { id children; unsigned count; if (![self hasChildNodes]) return nil; children = [self childNodes]; if ((count = [children count]) == 0) return nil; if (count == 1) { return [self _stringValueOfChildNode:[children objectAtIndex:0]]; } else { unsigned i; NSMutableString *s; s = [NSMutableString stringWithCapacity:256]; for (i = 0; i < count; i++) { [s appendString: [self _stringValueOfChildNode:[children objectAtIndex:i]]]; } return [[s copy] autorelease]; } } /* node */ - (BOOL)_isValidChildNode:(id)_node { switch ([_node nodeType]) { case DOM_TEXT_NODE: case DOM_ENTITY_REFERENCE_NODE: return YES; default: return NO; } } - (DOMNodeType)nodeType { return DOM_ATTRIBUTE_NODE; } - (id)attributes { return nil; } - (id)parentNode { return nil; } - (id)nextSibling { return nil; } - (id)previousSibling { return nil; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"<0x%p[%@]: {%@}%@%s '%@'>", self, NSStringFromClass([self class]), self->namespaceURI, [self name], [self specified] ? " specified" : "", [self stringValue]]; } /* ObjCValues */ - (NSString *)stringValue { return [self value]; } - (int)intValue { return [[self stringValue] intValue]; } - (double)doubleValue { return [[self stringValue] doubleValue]; } /* QPValues */ - (NSException *)setQueryPathValue:(id)_value { [self setValue:[_value stringValue]]; return nil; } - (id)queryPathValue { return [self value]; } @end /* NGDOMAttribute */ SOPE/sope-xml/DOM/DOMDocumentType.h0000644000000000000000000000247415004363604015646 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMDocumentType_H__ #define __DOMDocumentType_H__ #include @interface NGDOMDocumentType : NGDOMNode { id parent; } /* attributes */ - (NSString *)name; - (id)entities; - (id)notations; - (NSString *)publicId; - (NSString *)systemId; - (NSString *)internalSubset; /* node */ @end @interface NGDOMDocumentType(PrivateCtors) /* use DOMDocument for constructing DOMDocumentType's ! */ - (id)initWithName:(NSString *)_name publicId:(NSString *)_pubId systemId:(NSString *)_sysId; @end #endif /* __DOMDocumentType_H__ */ SOPE/sope-xml/DOM/DOMCharacterData.h0000644000000000000000000000201515004363604015703 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMCharacterData_H__ #define __DOMCharacterData_H__ #include @class NSString; @interface NGDOMCharacterData : NGDOMNode < DOMCharacterData > { id parent; NSString *data; } @end #endif /* __DOMCharacterData_H__ */ SOPE/sope-xml/DOM/TODO0000644000000000000000000000011415004363604013172 0ustar rootrootTODOs for DOM ============= - add a DOM builder which uses NSXMLParser API SOPE/sope-xml/DOM/DOMXMLOutputter.h0000644000000000000000000000235215004363604015615 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOMXMLOutputter_H__ #define __DOMXMLOutputter_H__ #import #include /* DOMXMLOutputter Class to generate a text representation of an DOM node to stdout. */ @class NSMutableArray; @interface DOMXMLOutputter : NSObject { NSMutableArray *stack; unsigned indent; } - (void)outputNode:(id)_node to:(id)_target; - (void)outputDocument:(id)_document to:(id)_target; @end #endif /* __DOMXMLOutputter_H__ */ SOPE/sope-xml/DOM/NSObject+QPEval.h0000644000000000000000000000212715004363604015454 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NSObject_QPEval_H__ #define __NSObject_QPEval_H__ #import #import @class NSArray; @interface NSObject(QPEval) - (NSArray *)evaluateQueryPath:(NSString *)_pc; @end @interface NSString(QP) - (NSArray *)queryPathComponents; @end #endif /* __NSObject_QPEval_H__ */ SOPE/sope-xml/DOM/DOMNode+QueryPath.h0000644000000000000000000000243415004363604016025 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOM_DOMNodeQueryPath_H__ #define __DOM_DOMNodeQueryPath_H__ #include #include /* Perform query path lookups on a DOM node. Look into DOMQueryPathExpression for the actual path syntax. */ @class NSString, NSArray; @interface NGDOMNode(QueryPath) /* Evaluate a stack of path specifiers. */ - (id)lookupPathComponents:(NSArray *)_path; /* Same like above using a string */ - (id)lookupQueryPath:(NSString *)_path; @end #endif /* __DOM_DOMNodeQueryPath_H__ */ SOPE/sope-xml/DOM/GNUmakefile.preamble0000644000000000000000000000271415004363604016352 0ustar rootroot# compilation settings include ./Version libDOM_HEADER_FILES_DIR = . libDOM_HEADER_FILES_INSTALL_DIR = /DOM libDOM_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION) libDOM_INSTALL_DIR=$(SOPE_SYSLIBDIR) libDOM_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION) DOM_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION) DOM_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION) # framework support DOM_HEADER_FILES = $(libDOM_HEADER_FILES) DOM_OBJC_FILES = $(libDOM_OBJC_FILES) ADDITIONAL_CPPFLAGS += \ -O2 \ -Wall -DCOMPILE_FOR_GSTEP_MAKE=1 \ -DSOPE_MAJOR_VERSION=$(MAJOR_VERSION) \ -DSOPE_MINOR_VERSION=$(MINOR_VERSION) \ -DSOPE_SUBMINOR_VERSION=$(SUBMINOR_VERSION) ADDITIONAL_INCLUDE_DIRS += -I.. -I../.. libDOM_LIBRARIES_DEPEND_UPON += -lSaxObjC $(BASE_LIBS) ifneq ($(GNUSTEP_BUILD_DIR),) libDOM_LIB_DIRS += -L$(GNUSTEP_BUILD_DIR)/../SaxObjC/$(GNUSTEP_OBJ_DIR_NAME) DOM_LIB_DIRS += -F$(GNUSTEP_BUILD_DIR)/../SaxObjC/ else libDOM_LIB_DIRS += -L../SaxObjC/$(GNUSTEP_OBJ_DIR) DOM_LIB_DIRS += -F../SaxObjC/ endif # Apple ifeq ($(FOUNDATION_LIB),apple) libDOM_PREBIND_ADDR="0xC0200000" libDOM_LDFLAGS += -seg1addr $(libDOM_PREBIND_ADDR) #ADDITIONAL_INCLUDE_DIRS += -framework SaxObjC DOM_FRAMEWORK_LIBS += -framework SaxObjC DOM_LIBRARIES_DEPEND_UPON += -framework SaxObjC endif ifeq ($(FOUNDATION_LIB),nx) domxml_LDFLAGS += -framework Foundation testqp_LDFLAGS += -framework Foundation endif SOPE/sope-xml/DOM/DOM.h0000644000000000000000000000264015004363604013300 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOM_H__ #define __DOM_H__ /* Standard DOM stuff */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif /* __DOM_H__ */ SOPE/sope-xml/DOM/DOMCDATASection.m0000644000000000000000000000233515004363604015370 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMCDATASection.h" @implementation NGDOMCDATASection /* node */ - (DOMNodeType)nodeType { return DOM_CDATA_SECTION_NODE; } - (BOOL)_isValidChildNode:(id)_node { return NO; } - (BOOL)hasChildNodes { return NO; } - (id)childNodes { return nil; } - (id)appendChild:(id)_node { return nil; } - (id)attributes { return nil; } @end /* NGDOMCDATASection */ SOPE/sope-xml/DOM/DOMComment.m0000644000000000000000000000231015004363604014622 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMComment.h" @implementation NGDOMComment /* node */ - (DOMNodeType)nodeType { return DOM_COMMENT_NODE; } - (BOOL)_isValidChildNode:(id)_node { return NO; } - (BOOL)hasChildNodes { return NO; } - (id)childNodes { return nil; } - (id)appendChild:(id)_node { return nil; } - (id)attributes { return nil; } @end /* NGDOMComment */ SOPE/sope-xml/DOM/DOMDocumentType.m0000644000000000000000000000354315004363604015651 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMDocumentType.h" #include "common.h" @implementation NGDOMDocumentType - (id)initWithName:(NSString *)_name publicId:(NSString *)_pubId systemId:(NSString *)_sysId dom:(id)_dom { [self release]; return nil; } /* attributes */ - (NSString *)name { return nil; } - (id)entities { return nil; } - (id)notations { return nil; } - (NSString *)publicId { return nil; } - (NSString *)systemId { return nil; } - (NSString *)internalSubset { return nil; } /* node */ - (DOMNodeType)nodeType { return DOM_DOCUMENT_TYPE_NODE; } - (BOOL)_isValidChildNode:(id)_node { return NO; } - (BOOL)hasChildNodes { return NO; } - (id)childNodes { return nil; } - (id)attributes { return nil; } /* parent node */ - (void)_domNodeRegisterParentNode:(id)_parent { self->parent = _parent; } - (void)_domNodeForgetParentNode:(id)_parent { if (_parent == self->parent) /* the node's parent was deallocated */ self->parent = nil; } - (id)parentNode { return self->parent; } @end /* NGDOMDocumentType */ SOPE/sope-xml/SaxObjC/0000755000000000000000000000000015004363604013360 5ustar rootrootSOPE/sope-xml/SaxObjC/SaxMethodCallHandler.h0000644000000000000000000000561715004363604017530 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxMethodCallHandler_H__ #define __SaxMethodCallHandler_H__ #include #import @class NSString, NSMutableArray, NSMutableDictionary; /* [also take a look at SaxObjectDecoder] This handler calls a method on a delegate for each tag. The selector is constructed this way: [start|end] + nskey + tagname + ':' If no method could be found for the tag, it is first checked whether the delegate responds to [start|end] + nskey + 'unknownTag:attributes:' and it this couldn't be found, it is checked for [start|end] + 'tag:_tagName namespace:_ns attributes:' If no key could be found for a namespace, it is first checked whether the delegate responds to [start|end] + 'any_' + tagname + ':' if this fails it is checked for this selector [start|end] + 'tag:_tagName namespace:_ns attributes:' if neither exists, the tag is ignored. Eg: nskey='xhtml' startKey='start_' endKey='end_' - (void)start_xhtml_br:(id)_attrs; - (void)end_xhtml_br; */ @interface SaxMethodCallHandler : SaxDefaultHandler { id delegate; // non-retained: default=self (for subclasses) NSMutableDictionary *namespaceToKey; NSMutableArray *tagStack; NSString *startKey; // default: 'start_' NSString *endKey; // default: 'end_' NSString *unknownNamespaceKey; // default: 'any_' int ignoreLevel; /* processing */ NSMapTable *fqNameToStartSel; NSMutableString *selName; /* reused for each construction */ } /* namespaces */ - (void)registerNamespace:(NSString *)_namespace withKey:(NSString *)_key; /* keys */ - (void)setStartKey:(NSString *)_s; - (NSString *)startKey; - (void)setEndKey:(NSString *)_s; - (NSString *)endKey; - (void)setUnknownNamespaceKey:(NSString *)_s; - (NSString *)unknownNamespaceKey; /* tag stack */ - (NSArray *)tagStack; - (unsigned)depth; - (void)ignoreChildren; - (BOOL)doesIgnoreChildren; /* delegate */ - (void)setDelegate:(id)_delegate; - (id)delegate; @end #endif /* __SaxMethodCallHandler_H__ */ SOPE/sope-xml/SaxObjC/SaxXMLReaderFactory.h0000644000000000000000000000315115004363604017320 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxXMLReaderFactory_H__ #define __SaxXMLReaderFactory_H__ #import #include /* To get a reader for HTML files: reader = [factory createXMLReaderForMimeType:@"text/html"]; for XML files: reader = [factory createXMLReaderForMimeType:@"text/xml"]; a specific reader: reader = [factory createXMLReaderWithName:@"libxmlSAXDriver"]; */ @class NSDictionary; @interface SaxXMLReaderFactory : NSObject { NSDictionary *nameToBundle; NSDictionary *mimeTypeToName; } + (id)standardXMLReaderFactory; - (id)createXMLReader; - (id)createXMLReaderWithName:(NSString *)_name; - (id)createXMLReaderForMimeType:(NSString *)_mtype; - (NSArray *)availableXMLReaders; @end #endif /* __SaxXMLReaderFactory_H__ */ SOPE/sope-xml/SaxObjC/SaxDTDHandler.h0000644000000000000000000000226015004363604016116 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxDTDHandler_H__ #define __SaxDTDHandler_H__ @class NSString; @protocol SaxDTDHandler - (void)notationDeclaration:(NSString *)_name publicId:(NSString *)_pubId systemId:(NSString *)_sysId; - (void)unparsedEntityDeclaration:(NSString *)_name publicId:(NSString *)_pubId systemId:(NSString *)_sysId notationName:(NSString *)_notName; @end /* SaxDTDHandler */ #endif /* __SaxDTDHandler_H__ */ SOPE/sope-xml/SaxObjC/GNUmakefile0000644000000000000000000000255115004363604015435 0ustar rootroot# GNUstep makefile include ../../config.make include ../common.make ifneq ($(frameworks),yes) LIBRARY_NAME = libSaxObjC else FRAMEWORK_NAME = SaxObjC SaxObjC_RESOURCE_FILES += Version endif libSaxObjC_PCH_FILE = common.h SaxObjC_PCH_FILE = common.h libSaxObjC_OBJC_FILES = \ SaxAttributeList.m \ SaxAttributes.m \ SaxDefaultHandler.m \ SaxException.m \ SaxHandlerBase.m \ SaxLocator.m \ SaxMethodCallHandler.m \ SaxNamespaceSupport.m \ SaxObjectDecoder.m \ SaxObjectModel.m \ SaxXMLFilter.m \ SaxXMLReaderFactory.m \ libSaxObjC_HEADER_FILES = \ SaxObjC.h \ SaxAttributeList.h \ SaxAttributes.h \ SaxContentHandler.h \ SaxDTDHandler.h \ SaxDeclHandler.h \ SaxDefaultHandler.h \ SaxDocumentHandler.h \ SaxEntityResolver.h \ SaxErrorHandler.h \ SaxException.h \ SaxHandlerBase.h \ SaxLexicalHandler.h \ SaxLocator.h \ SaxNamespaceSupport.h \ SaxObjectDecoder.h \ SaxObjectModel.h \ SaxXMLFilter.h \ SaxXMLReader.h \ SaxXMLReaderFactory.h \ SaxMethodCallHandler.h \ XMLNamespaces.h \ libSaxObjC_PCH_FILE = common.h # building -include GNUmakefile.preamble ifneq ($(FHS_INSTALL_ROOT),) GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include endif ifneq ($(frameworks),yes) include $(GNUSTEP_MAKEFILES)/library.make else include $(GNUSTEP_MAKEFILES)/framework.make endif -include GNUmakefile.postamble SOPE/sope-xml/SaxObjC/SaxObjC-Info.plist0000644000000000000000000000133715004363604016623 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable SaxObjC CFBundleGetInfoString CFBundleIdentifier org.OpenGroupware.sope-xml.SaxObjC CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType FMWK CFBundleShortVersionString CFBundleSignature ???? CFBundleVersion 4.7 SOPE/sope-xml/SaxObjC/SaxLexicalHandler.h0000644000000000000000000000643715004363604017076 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxLexicalHandler_H__ #define __SaxLexicalHandler_H__ #import /* new in SAX 2.0beta SAX2 extension handler for lexical events. This is an optional extension handler for SAX2 to provide lexical information about an XML document, such as comments and CDATA section boundaries; XML readers are not required to support this handler. The events in the lexical handler apply to the entire document, not just to the document element, and all lexical handler events must appear between the content handler's startDocument and endDocument events. To set the LexicalHandler for an XML reader, use the setProperty method with the propertyId "http://xml.org/sax/handlers/LexicalHandler". If the reader does not support lexical events, it will throw a SAXNotRecognizedException or a SAXNotSupportedException when you attempt to register the handler. */ @protocol SaxLexicalHandler /* Report an XML comment anywhere in the document. This callback will be used for comments inside or outside the document element, including comments in the external DTD subset (if read). */ - (void)comment:(unichar *)_chars length:(int)_len; /* Report the start of DTD declarations, if any. Any declarations are assumed to be in the internal subset unless otherwise indicated by a startEntity event. Note that the start/endDTD events will appear within the start/endDocument events from ContentHandler and before the first startElement event. */ - (void)startDTD:(NSString *)_name publicId:(NSString *)_pub systemId:(NSString *)_sys; /* Report the end of DTD declarations. */ - (void)endDTD; /* Report the beginning of an entity in content. NOTE: entity references in attribute values -- and the start and end of the document entity -- are never reported. The start and end of the external DTD subset are reported using the pseudo-name "[dtd]". All other events must be properly nested within start/end entity events. Note that skipped entities will be reported through the skippedEntity event, which is part of the ContentHandler interface. If it is a parameter entity, the name will begin with '%'. */ - (void)startEntity:(NSString *)_name; /* report the end of an entity */ - (void)endEntity:(NSString *)_name; /* Report the start of a CDATA section. The contents of the CDATA section will be reported through the regular characters event. */ - (void)startCDATA; /* Report the end of a CDATA section */ - (void)endCDATA; @end #endif /* __SaxLexicalHandler_H__ */ SOPE/sope-xml/SaxObjC/ChangeLog0000644000000000000000000003112215004363604015131 0ustar rootroot2007-03-28 Helge Hess * XMLNamespaces.h: added XMLNS_MXML_2006 namespace (4.7.66) 2007-02-08 Helge Hess * XMLNamespaces.h: added XMLNS_CARDDAV namespace (v4.5.65) * XMLNamespaces.h: added XMLNS_AppleCalApp namespace (v4.5.64) * XMLNamespaces.h: added XMLNS_GROUPDAV namespace (v4.5.63) * XMLNamespaces.h: added XMLNS_AppleCalServer namespace (v4.5.62) 2006-09-20 Helge Hess * GNUmakefile.preamble: filter out -O% flags for files using exception handlers, enable -O2 per default (v4.5.61) 2006-07-05 Helge Hess * SaxObjectModel.m: added FHS_INSTALL_ROOT to lookup path (v4.5.60) * SaxXMLReaderFactory.m: changed to find SAX drivers on 64bit systems in lib64, added FHS_INSTALL_ROOT to lookup path (v4.5.59) 2006-07-03 Helge Hess * v4.5.58 * SaxAttributes.m: fixed gcc 4.1 warnings * use %p for pointer formats 2006-07-02 Helge Hess * XMLNamespaces.h: added ATOM namespace, gCal namespace, OpenSearch namespace (v4.5.57) 2006-06-04 Helge Hess * XMLNamespaces.h (XMLNS_CALDAV): added CalDAV namespace (v4.5.56) 2006-04-23 Helge Hess * XMLNamespaces.h: added Google namespace (v4.5.55) 2005-12-27 Marcus Mueller * SaxObjectDecoder.m: trigger debug logging via new SaxObjectDecoderDebugEnabled default (v4.5.54) 2005-11-25 Helge Hess * SaxMethodCallHandler.m: rewrote tag=>selector mapping function to be Unicode safe (v4.5.53) 2005-08-16 Helge Hess * v4.5.52 * SaxXMLReaderFactory.m: improved bundle-info.plist lookup (first look in bundle directory, then try to lookup as a NSBundle resource), log searched pathes if no XML reader could be found * GNUmakefile.preamble: set framework/cocoa defines when compiling with frameworks support 2005-05-08 Helge Hess * XMLNamespaces.h: added namespace declaration for XML vCards (v4.5.51) 2005-04-23 Helge Hess * SaxMethodCallHandler.m: fixed a gcc 4.0 warning (v4.5.50) 2005-03-23 Marcus Mueller * SaxObjectDecoder.m: fixed remaining leaks (v4.5.49) 2005-01-29 Marcus Mueller * SaxObjectDecoder.m: fixed hard to spot autorelease bug (v4.5.48) 2004-11-12 Max Berger * SaxXMLReaderFactory.m: fixed SaxDriver lookup for gstep-base on MingW32 (OGo bug #979) (v4.5.47) 2004-11-12 Helge Hess * SaxXMLReaderFactory.m: cleanup of driver path processing (v4.5.46) 2004-11-07 Marcus Mueller * SaxObjC.xcode: added SOPE_MAJOR/MINOR definitions for the build 2004-11-07 Helge Hess * SaxXMLReaderFactory.m: fixed a bug in FHS bundle lookup (v4.5.45) 2004-11-06 Helge Hess * SaxObjectModel.m, SaxXMLReaderFactory.m: use SOPE version defines for object model lookup (v4.5.44) 2004-10-30 Marcus Mueller * SaxObjectDecoder.m: fixed typo that prevented compile on non Apple Foundation (v4.3.43) * SaxObjectDecoder.m: provide fix for discovering mutable array on Apple/CoreFoundation - this is rather disturbing, but Apple really broke the concept of mutability for NSArray/NSDictionary. (v4.3.42) 2004-09-22 Marcus Mueller * SaxObjC.xcode: minor fixes 2004-09-21 Marcus Mueller * SaxObjC.xcode: Fixed dependencies to resemble the make process more closely. Our aim should be to stick to the make process as closely as possible, so we shouldn't introduce dependencies in non-toplevel projects. Also fixed cyclic dependency between the framework and the libxmlSAXDriver, which gets copied into the framework wrapper after compilation. This now gets achieved by two shellscript phases, one in the framework and one as a separate shellscript target. 2004-08-29 Helge Hess * v4.3.41 * SaxXMLReaderFactory.m: look in /usr/local/lib/sope-4.3/saxdrivers/ and /usr/lib/sope-4.3/saxdrivers/ for SAX drivers * SaxObjectModel.m: also look in /usr/local/share/sope-4.3/saxmappings/ and /usr/share/sope-4.3/saxmappings/ for models * added hack to install the project in FHS locations - the library, its headers, the tools and the resources will be installed in FHS_INSTALL_ROOT if specified (eg make FHS_INSTALL_ROOT=/usr/local) 2004-08-26 Marcus Mueller * SaxObjC.xcode: new Xcode project 2004-08-24 Helge Hess * changed lookup path to SaxDrivers-4.3 to be consistent with OGo (v4.3.40) * SaxXMLReaderFactory.m: lookup SAX drivers in Library/SaxDrivers/4.3 (v4.3.39) 2004-08-20 Helge Hess * moved to SOPE 4.3 (v4.3.38) 2004-08-03 Marcus Mueller * SaxXMLReaderFactory.m: fixed multiple registration of sax drivers in the search path. Also, when built as a framework, the frameworks's SaxDriver directory is added to the search path (with least significance, so it doesn't interfere with development and custom deployments). (v4.2.37) 2004-07-17 Helge Hess * XMLNamespaces.h: added OOo WebDAV namespace (v4.2.36) 2004-07-16 Helge Hess * XMLNamespaces.h: added namespace declaration for Kupu and XInclude (v4.2.35) 2004-07-15 Helge Hess * XMLNamespaces.h: added relaxng structure namespace as used by Kupu (v4.2.34) 2004-07-07 Helge Hess * XMLNamespaces.h: added namespace declarations for SOAP, XMLSchema and some Novell namespaces (v4.2.33) 2004-06-27 Helge Hess * XMLNamespaces.h: added namespace declaration for OOo meta (v4.2.32) 2004-06-10 Helge Hess * SaxObjectModel.m: fixed a warning with gcc 3.4 (v4.2.31) 2004-06-09 Helge Hess * v4.2.30 * GNUmakefile: also build SaxObjC.framework on non-libFoundation systems * GNUmakefile.preamble: added prebinding segaddr 2004-03-16 Helge Hess * SaxXMLReaderFactory.m: added SaxDebugReaderFactory default to enable debug logs, added more debug logging (v4.2.29) * XMLNamespaces.h: added namespace declaration for Zope METAL (v4.2.28) 2004-03-15 Helge Hess * XMLNamespaces.h: added namespace declaration for Zope TAL (v4.2.27) 2004-02-27 Helge Hess * SaxXMLReaderFactory.m: subminbor improvement to warn-log in case multiple XML parsers are found for a single type (v4.2.26) 2004-02-16 Helge Hess * SaxXMLReaderFactory.m: subminor code cleanup and fixes to log messages (v4.2.25) 2003-12-26 Helge Hess * SaxXMLReaderFactory.m: cleaned up logging for missing parsers (v4.2.24) 2003-11-20 Helge Hess * XMLNamespaces.h: added namespace declaration for some proprietary groupware server (v4.2.23) 2003-11-19 Helge Hess * GNUmakefile: removed autodoc target 2003-11-09 Helge Hess * v4.2.22 * SaxAttributes.m: added -initWithDictionary method necessary for the NSXMLParser support (Note: Panther NSXMLParser currently doesn't seem to be able to do proper namespace processing for attributes?) * added the SaxDefaultHandler+NSXML category which allows any SAX handler inheriting from SaxDefaultHandler to be used as a delegate for the new NSXMLParser in Panther 2003-10-30 Helge Hess * SaxAttributes.m: fixed an Xcode warning (v4.2.21) 2003-10-15 Helge Hess * XMLNamespaces.h: added MS WordML namespace, added Dublin Core namespace (v4.2.20) 2003-10-12 Helge Hess * SaxObjectModel.m, SaxXMLReaderFactory.m: added support for GNUSTEP_PATHLIST (apparently replaces GNUSTEP_PATHPREFIX_LIST in newer gstep-make versions (v4.2.19) 2003-08-19 Helge Hess * SaxObjectDecoder.m: fixed OGo bug 133, decoder did not properly check value classes on Cocoa (v4.2.18) 2003-07-18 Helge Hess * SaxXMLReaderFactory.m: added a missing @end for gstep-base, patch provided by Filip Van Raemdonck (v4.2.17) 2003-07-03 Helge Hess * XMLNamespaces.h: added defines for the various XML namespaces used in OpenOffice.org emitted XML files (v4.2.16) 2003-06-18 Helge Hess * v4.2.15 * SaxXMLReaderFactory.m: added SaxCoreOnMissingParser default to trigger a coredump for debugging purposes * fixed some signed/unsigned warnings 2003-02-11 Helge Hess * moved saxxml and xmln tools to ../samples/ 2003-01-23 Helge Hess * SaxMethodCallHandler.m, SaxObjectDecoder.m: reduced logging if debugOn is off (v4.2.14) Thu Jan 2 10:40:19 2003 Helge Hess * v4.2.13 * saxxml.m: replaced RELEASE macros with method calls * common.h: define ASSIGN macro if missing, do not include headers from FoundationExt * SaxNamespaceSupport.m: replaced -notImplemented: with -doesNotRecognizeSelector: since -notImplemented: is not available on MacOSX 2002-11-27 Helge Hess * SaxObjectModel.m: fixed a bug with parsing toMany keys (addToRel: was not properly called) (v4.2.12) 2002-11-05 Helge Hess * XMLNamespaces.h: added Nautilus namespace (v4.2.11) 2002-11-04 Helge Hess * XMLNamespaces.h: added the cadaver namespaces (v4.2.10) 2002-10-24 Helge Hess * XMLNamespaces.h: added various namespace declarations (v4.2.9) 2002-10-23 Helge Hess * SaxObjectModel.m, SaxObjectDecoder.m: added a namespaceKey to the model (allows you to track the namespace in your parsed objects) * XMLNamespaces.h: added the hotmail and httpmail namespaces (v4.2.8) Thu Oct 17 20:24:53 2002 Helge Hess * SaxObjectDecoder.m ([_SaxObjTagInfo -unableToSetValue:forKey:withTag:toParent:exception:]): now logs, why it was unable to set the key (exception) (v4.2.7) 2002-10-17 Helge Hess * SaxObjectModel.m: when searching for a model the mainbundle resources are checked before traversing the Library/SaxMappings pathes (v4.2.6) 2002-10-14 Helge Hess * SaxObjectDecoder.m: added support for contentKey (v4.2.5) 2002-10-13 Helge Hess * added SaxObjectDecoder, a SAX handler which constructs object trees by consulting a XML<->object mapping model (v4.2.4) 2002-10-10 Helge Hess * XMLNamespaces.h: added namespace declaration for xcal 01 (v4.2.3) 2002-08-29 Helge Hess * SaxXMLReaderFactory.m: small fix for OSX, renamed COCOA_FRAMEWORK define to COCOA_Foundation_LIBRARY 2002-05-31 Helge Hess * SaxXMLReaderFactory.m: added NSBundle -copyWithZone: when compiling for gstep-base compatibility Sun May 5 18:01:32 2002 Helge Hess * removed SAX1<->SAX2 adaptor classes, SAX1 stuff in general Tue Feb 12 20:24:59 2002 Helge Hess * SaxXMLReaderFactory.m: modified to be usable without NGBundleManager (but uses same bundle-info.plist ...) Sat Feb 9 11:35:27 2002 Helge Hess * moved XML test files to Examples/xmlsamples Wed Jan 9 13:24:40 2002 Helge Hess * SaxXMLReaderFactory.m: ensure that a text/xml reader is created ... Mon Dec 17 17:02:15 2001 Helge Hess * added namespaces-declaration header Wed Oct 24 18:45:05 2001 Helge Hess * ExpatSaxDriver/ExpatSaxDriver.m: fixed UTF8->UTF16 conversion bug (incorrect string length was passed to Sax callbacks) Mon Oct 1 15:47:31 2001 Helge Hess * SaxXMLReaderFactory.m: added capability to create SAX parsers based on MIME-type Thu Aug 16 13:48:01 2001 Helge Hess * SaxAttributes.m: added NSCopying SOPE/sope-xml/SaxObjC/common.h0000644000000000000000000000225215004363604015022 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxObjC_common_H__ #define __SaxObjC_common_H__ #import #ifndef ASSIGN # define ASSIGN(object, value) \ ({id __object = (id)object; \ id __value = (id)value; \ if (__value != __object) { if (__value) [__value retain]; \ if (__object) [__object release]; \ object = __value;}}) #endif #endif /* __SaxObjC_common_H__ */ SOPE/sope-xml/SaxObjC/SaxAttributeList.m0000644000000000000000000001124615004363604017015 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SaxAttributeList.h" #include "SaxAttributes.h" #include "common.h" @implementation SaxAttributeList - (id)init { self->names = [[NSMutableArray alloc] init]; self->types = [[NSMutableArray alloc] init]; self->values = [[NSMutableArray alloc] init]; return self; } - (id)initWithAttributeList:(id)_attrList { if ((self = [self init])) { NSUInteger i; for (i = 0; i < [_attrList count]; i++) { [self->names addObject:[_attrList nameAtIndex:i]]; [self->types addObject:[_attrList typeAtIndex:i]]; [self->values addObject:[_attrList valueAtIndex:i]]; } } return self; } - (id)initWithAttributes:(id)_attrList { if ((self = [self init])) { NSUInteger i, c; for (i = 0, c = [_attrList count]; i < c; i++) { [self->names addObject:[_attrList rawNameAtIndex:i]]; [self->types addObject:[_attrList typeAtIndex:i]]; [self->values addObject:[_attrList valueAtIndex:i]]; } } return self; } - (void)dealloc { [self->names release]; [self->types release]; [self->values release]; [super dealloc]; } /* modify operations */ - (void)setAttributeList:(id)_attrList { NSUInteger i; [self clear]; for (i = 0; i < [_attrList count]; i++) { [self->names addObject:[_attrList nameAtIndex:i]]; [self->types addObject:[_attrList typeAtIndex:i]]; [self->values addObject:[_attrList valueAtIndex:i]]; } } - (void)clear { [self->names removeAllObjects]; [self->types removeAllObjects]; [self->values removeAllObjects]; } - (void)addAttribute:(NSString *)_name type:(NSString *)_type value:(NSString *)_value { if (_type == nil) _type = @"CDATA"; if (_value == nil) _value = @""; [self->names addObject:_name]; [self->types addObject:_type]; [self->values addObject:_value]; } - (void)removeAttribute:(NSString *)_name { NSUInteger idx; if ((idx = [self->names indexOfObject:_name]) == NSNotFound) return; [self->names removeObjectAtIndex:idx]; [self->types removeObjectAtIndex:idx]; [self->values removeObjectAtIndex:idx]; } /* protocol implementation */ - (NSString *)nameAtIndex:(NSUInteger)_idx { return [self->names objectAtIndex:_idx]; } - (NSString *)typeAtIndex:(NSUInteger)_idx { return [self->types objectAtIndex:_idx]; } - (NSString *)valueAtIndex:(NSUInteger)_idx { return [self->values objectAtIndex:_idx]; } - (NSString *)typeForName:(NSString *)_name { NSUInteger i; if ((i = [self->names indexOfObject:_name]) == NSNotFound) return nil; return [self typeAtIndex:i]; } - (NSString *)valueForName:(NSString *)_name { NSUInteger i; if ((i = [self->names indexOfObject:_name]) == NSNotFound) return nil; return [self valueAtIndex:i]; } - (NSUInteger)count { return [self->names count]; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { return [[[self class] allocWithZone:_zone] initWithAttributeList:self]; } /* description */ - (id)propertyList { id objs[3], keys[3]; objs[0] = self->names; keys[0] = @"names"; objs[1] = self->types; keys[1] = @"types"; objs[2] = self->values; keys[2] = @"values"; return [NSDictionary dictionaryWithObjects:objs forKeys:keys count:3]; } - (NSString *)description { NSMutableString *s; NSString *is; NSUInteger i, c; s = [[NSMutableString alloc] init]; [s appendFormat:@"<%p[%@]:", self, NSStringFromClass([self class])]; for (i = 0, c = [self count]; i < c; i++) { NSString *type; [s appendString:@" "]; [s appendString:[self nameAtIndex:i]]; [s appendString:@"='"]; [s appendString:[self valueAtIndex:i]]; [s appendString:@"'"]; type = [self typeAtIndex:i]; if (![type isEqualToString:@"CDATA"]) { [s appendString:@"["]; [s appendString:type]; [s appendString:@"]"]; } } [s appendString:@">"]; is = [s copy]; [s release]; return [is autorelease]; } @end /* SaxAttributeList */ SOPE/sope-xml/SaxObjC/SaxAttributes.h0000644000000000000000000000462215004363604016337 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxAttributes_H__ #define __SaxAttributes_H__ #import @class NSString, NSArray, NSMutableArray, NSDictionary; /* new in SAX 2.0beta, replaces the SaxAttributeList */ @protocol SaxAttributes /* lookup indices */ - (NSUInteger)indexOfRawName:(NSString *)_rawName; - (NSUInteger)indexOfName:(NSString *)_localPart uri:(NSString *)_uri; /* lookup data by index */ - (NSString *)nameAtIndex:(NSUInteger)_idx; - (NSString *)rawNameAtIndex:(NSUInteger)_idx; - (NSString *)typeAtIndex:(NSUInteger)_idx; - (NSString *)uriAtIndex:(NSUInteger)_idx; - (NSString *)valueAtIndex:(NSUInteger)_idx; /* lookup data by name */ - (NSString *)typeForRawName:(NSString *)_rawName; - (NSString *)typeForName:(NSString *)_localName uri:(NSString *)_uri; - (NSString *)valueForRawName:(NSString *)_rawName; - (NSString *)valueForName:(NSString *)_localName uri:(NSString *)_uri; /* list size */ - (NSUInteger)count; @end /* simple attributes implementation, should be improved */ @interface SaxAttributes : NSObject < SaxAttributes, NSCopying > { @private NSMutableArray *names; NSMutableArray *uris; NSMutableArray *rawNames; NSMutableArray *types; NSMutableArray *values; } - (id)initWithAttributes:(id)_attrs; - (id)initWithDictionary:(NSDictionary *)_dict; - (void)addAttribute:(NSString *)_localName uri:(NSString *)_uri rawName:(NSString *)_rawName type:(NSString *)_type value:(NSString *)_value; - (void)clear; @end #include @interface SaxAttributes(Compatibility) - (id)initWithAttributeList:(id)_attrList; @end #endif /* __SaxAttributes_H__ */ SOPE/sope-xml/SaxObjC/SaxException.m0000644000000000000000000000172315004363604016153 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SaxException.h" @implementation SaxException @end @implementation SaxParseException @end @implementation SaxNotSupportedException @end @implementation SaxNotRecognizedException @end SOPE/sope-xml/SaxObjC/SaxDefaultHandler.m0000644000000000000000000000437515004363604017105 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SaxDefaultHandler.h" #include "SaxException.h" @implementation SaxDefaultHandler /* SaxContentHandler */ - (void)startDocument { } - (void)endDocument { } - (void)startPrefixMapping:(NSString *)_prefix uri:(NSString *)_uri { } - (void)endPrefixMapping:(NSString *)_prefix { } - (void)startElement:(NSString *)_localName namespace:(NSString *)_ns rawName:(NSString *)_rawName attributes:(id)_attributes { } - (void)endElement:(NSString *)_localName namespace:(NSString *)_ns rawName:(NSString *)_rawName { } - (void)characters:(unichar *)_chars length:(NSUInteger)_len { } - (void)ignorableWhitespace:(unichar *)_chars length:(NSUInteger)_len { } - (void)processingInstruction:(NSString *)_pi data:(NSString *)_data { } - (void)setDocumentLocator:(id)_locator { } - (void)skippedEntity:(NSString *)_entityName { } /* SaxDTDHandler */ - (void)notationDeclaration:(NSString *)_name publicId:(NSString *)_pubId systemId:(NSString *)_sysId { } - (void)unparsedEntityDeclaration:(NSString *)_name publicId:(NSString *)_pubId systemId:(NSString *)_sysId notationName:(NSString *)_notName { } /* SaxEntityResolver */ - (id)resolveEntityWithPublicId:(NSString *)_pubId systemId:(NSString *)_sysId { return nil; } /* SaxErrorHandler */ - (void)warning:(SaxParseException *)_exception { } - (void)error:(SaxParseException *)_exception { } - (void)fatalError:(SaxParseException *)_exception { [_exception raise]; } @end /* SaxDefaultHandler */ SOPE/sope-xml/SaxObjC/XMLNamespaces.h0000644000000000000000000002016215004363604016172 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxObjC_XML_Namespaces_H__ #define __SaxObjC_XML_Namespaces_H__ #ifndef XMLNS_OD_BIND # define XMLNS_OD_BIND @"http://www.skyrix.com/od/binding" #endif #ifndef XMLNS_OD_CONST # define XMLNS_OD_CONST @"http://www.skyrix.com/od/constant" #endif #ifndef XMLNS_OD_ACTION # define XMLNS_OD_ACTION @"http://www.skyrix.com/od/action" #endif #ifndef XMLNS_OD_EVALJS # define XMLNS_OD_EVALJS @"http://www.skyrix.com/od/javascript" #endif #ifndef XMLNS_XHTML # define XMLNS_XHTML @"http://www.w3.org/1999/xhtml" #endif #ifndef XMLNS_HTML40 # define XMLNS_HTML40 @"http://www.w3.org/TR/REC-html40" #endif #ifndef XMLNS_XLINK # define XMLNS_XLINK @"http://www.w3.org/1999/xlink" #endif #ifndef XMLNS_XSLT # define XMLNS_XSLT @"http://www.w3.org/1999/XSL/Transform" #endif #ifndef XMLNS_XSL_FO # define XMLNS_XSL_FO @"http://www.w3.org/1999/XSL/Format" #endif #ifndef XMLNS_RDF # define XMLNS_RDF \ @"http://www.w3.org/1999/02/22-rdf-syntax-ns#" #endif #ifndef XMLNS_XUL # define XMLNS_XUL \ @"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" #endif #ifndef XMLNS_XFORMS # define XMLNS_XFORMS @"http://www.w3.org/2001/06/xforms" #endif #ifndef XMLNS_SVG # define XMLNS_SVG @"http://www.w3.org/2000/svg" #endif #ifndef XMLNS_MATHML # define XMLNS_MATHML @"http://www.w3.org/1998/Math/MathML" #endif #ifndef XMLNS_WML12 # define XMLNS_WML12 @"http://www.wapforum.org/DTD/wml_1.2.xml" #endif #ifndef XMLNS_XUPDATE # define XMLNS_XUPDATE @"http://www.xmldb.org/xupdate" #endif #ifndef XMLNS_WEBDAV # define XMLNS_WEBDAV @"DAV:" #endif #ifndef XMLNS_XCAL_01 # define XMLNS_XCAL_01 \ @"http://www.ietf.org/internet-drafts/draft-ietf-calsch-many-xcal-01.txt" #endif #ifndef XMLNS_RELAXNG_STRUCTURE # define XMLNS_RELAXNG_STRUCTURE @"http://relaxng.org/ns/structure/1.0" #endif #ifndef XMLNS_XINCLUDE # define XMLNS_XINCLUDE @"http://www.w3.org/2001/XInclude" #endif #ifndef XMLNS_KUPU # define XMLNS_KUPU @"http://kupu.oscom.org/namespaces/dist" #endif /* Microsoft related namespaces */ #ifndef XMLNS_MS_OFFICE_WORDML # define XMLNS_MS_OFFICE_WORDML \ @"http://schemas.microsoft.com/office/word/2003/wordml" #endif #ifndef XMLNS_MS_OFFICE_OFFICE # define XMLNS_MS_OFFICE_OFFICE @"urn:schemas-microsoft-com:office:office" #endif #ifndef XMLNS_MS_OFFICE_WORD # define XMLNS_MS_OFFICE_WORD @"urn:schemas-microsoft-com:office:word" #endif #ifndef XMLNS_MS_HOTMAIL # define XMLNS_MS_HOTMAIL @"http://schemas.microsoft.com/hotmail/" #endif #ifndef XMLNS_MS_HTTPMAIL # define XMLNS_MS_HTTPMAIL @"urn:schemas:httpmail:" #endif #ifndef XMLNS_MS_EXCHANGE # define XMLNS_MS_EXCHANGE @"http://schemas.microsoft.com/exchange/" #endif #ifndef XMLNS_MS_EX_CALENDAR # define XMLNS_MS_EX_CALENDAR @"urn:schemas:calendar:" #endif #ifndef XMLNS_MS_EX_CONTACTS # define XMLNS_MS_EX_CONTACTS @"urn:schemas:contacts:" #endif /* WebDAV related namespaces */ #ifndef XMLNS_WEBDAV_APACHE # define XMLNS_WEBDAV_APACHE @"http://apache.org/dav/props/" #endif #ifndef XMLNS_CADAVER_PROPS # define XMLNS_CADAVER_PROPS @"http://webdav.org/cadaver/custom-properties/" #endif #ifndef XMLNS_NAUTILUS_PROPS # define XMLNS_NAUTILUS_PROPS @"http://services.eazel.com/namespaces" #endif /* OpenOffice.org namespaces */ #ifndef XMLNS_OOo_UCB_WEBDAV # define XMLNS_OOo_UCB_WEBDAV @"http://ucb.openoffice.org/dav/props/" #endif #ifndef XMLNS_OOo_MANIFEST # define XMLNS_OOo_MANIFEST @"http://openoffice.org/2001/manifest" #endif #ifndef XMLNS_OOo_OFFICE # define XMLNS_OOo_OFFICE @"http://openoffice.org/2000/office" #endif #ifndef XMLNS_OOo_TEXT # define XMLNS_OOo_TEXT @"http://openoffice.org/2000/text" #endif #ifndef XMLNS_OOo_META # define XMLNS_OOo_META @"http://openoffice.org/2000/meta" #endif #ifndef XMLNS_OOo_STYLE # define XMLNS_OOo_STYLE @"http://openoffice.org/2000/style" #endif #ifndef XMLNS_OOo_TABLE # define XMLNS_OOo_TABLE @"http://openoffice.org/2000/table" #endif #ifndef XMLNS_OOo_DRAWING # define XMLNS_OOo_DRAWING @"http://openoffice.org/2000/drawing" #endif #ifndef XMLNS_OOo_DATASTYLE # define XMLNS_OOo_DATASTYLE @"http://openoffice.org/2000/datastyle" #endif #ifndef XMLNS_OOo_PRESENTATION # define XMLNS_OOo_PRESENTATION @"http://openoffice.org/2000/presentation" #endif #ifndef XMLNS_OOo_CHART # define XMLNS_OOo_CHART @"http://openoffice.org/2000/chart" #endif #ifndef XMLNS_OOo_DRAW3D # define XMLNS_OOo_DRAW3D @"http://openoffice.org/2000/dr3d" #endif #ifndef XMLNS_OOo_FORM # define XMLNS_OOo_FORM @"http://openoffice.org/2000/form" #endif #ifndef XMLNS_OOo_SCRIPT # define XMLNS_OOo_SCRIPT @"http://openoffice.org/2000/script" #endif #ifndef XMLNS_DublinCore # define XMLNS_DublinCore @"http://purl.org/dc/elements/1.1/" #endif #ifndef XMLNS_PROPRIETARY_SLOX # define XMLNS_PROPRIETARY_SLOX @"SLOX:" #endif /* Zope */ #ifndef XMLNS_Zope_TAL # define XMLNS_Zope_TAL @"http://xml.zope.org/namespaces/tal" #endif #ifndef XMLNS_Zope_METAL # define XMLNS_Zope_METAL @"http://xml.zope.org/namespaces/metal" #endif /* SOAP */ #ifndef XMLNS_SOAP_ENVELOPE # define XMLNS_SOAP_ENVELOPE @"http://schemas.xmlsoap.org/soap/envelope/" #endif #ifndef XMLNS_SOAP_ENCODING # define XMLNS_SOAP_ENCODING @"http://schemas.xmlsoap.org/soap/encoding/" #endif #ifndef XMLNS_XMLSchema # define XMLNS_XMLSchema @"http://www.w3.org/1999/XMLSchema" #endif #ifndef XMLNS_XMLSchemaInstance1999 # define XMLNS_XMLSchemaInstance1999 \ @"http://www.w3.org/1999/XMLSchema-instance" #endif #ifndef XMLNS_XMLSchemaInstance2001 # define XMLNS_XMLSchemaInstance2001 \ @"http://www.w3.org/2001/XMLSchema-instance" #endif /* Novell */ #ifndef XMLNS_Novell_NCSP_Types # define XMLNS_Novell_NCSP_Types \ @"http://schemas.novell.com/2003/10/NCSP/types.xsd" #endif #ifndef XMLNS_Novell_NCSP_Methods # define XMLNS_Novell_NCSP_Methods \ @"http://schemas.novell.com/2003/10/NCSP/methods.xsd" #endif /* XML vCards */ #ifndef XMLNS_VCARD_XML_03 # define XMLNS_VCARD_XML_03 \ @"http://www.ietf.org/internet-drafts/draft-dawson-vcard-xml-dtd-03.txt" #endif /* ATOM */ #ifndef XMLNS_ATOM_2005 # define XMLNS_ATOM_2005 @"http://www.w3.org/2005/Atom" #endif /* Google */ #ifndef XMLNS_GOOGLE_2005 # define XMLNS_GOOGLE_2005 @"http://schemas.google.com/g/2005" #endif #ifndef XMLNS_GOOGLE_CAL_2005 # define XMLNS_GOOGLE_CAL_2005 @"http://schemas.google.com/gCal/2005" #endif #ifndef XMLNS_OPENSEARCH_RSS # define XMLNS_OPENSEARCH_RSS @"http://a9.com/-/spec/opensearchrss/1.0/" #endif /* GroupDAV */ #ifndef XMLNS_GROUPDAV # define XMLNS_GROUPDAV @"http://groupdav.org/" #endif /* CalDAV / CardDAV */ #ifndef XMLNS_CALDAV # define XMLNS_CALDAV @"urn:ietf:params:xml:ns:caldav" #endif #ifndef XMLNS_CARDDAV # define XMLNS_CARDDAV @"urn:ietf:params:xml:ns:carddav" #endif /* Apple CalServer */ #ifndef XMLNS_AppleCalServer # define XMLNS_AppleCalServer @"http://apple.com/ns/calendarserver/" #endif #ifndef XMLNS_CalendarServerOrg # define XMLNS_CalendarServerOrg @"http://calendarserver.org/ns/" #endif #ifndef XMLNS_AppleCalApp # define XMLNS_AppleCalApp @"com.apple.ical:" #endif /* Adobe */ #ifndef XMLNS_MXML_2006 # define XMLNS_MXML_2006 @"http://www.adobe.com/2006/mxml" #endif #endif /* __SaxObjC_XML_Namespaces_H__ */ SOPE/sope-xml/SaxObjC/SaxAttributeList.h0000644000000000000000000000347315004363604017013 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxAttributeList_H__ #define __SaxAttributeList_H__ #import @class NSString, NSMutableArray; /* deprecated in SAX 2.0beta */ @protocol SaxAttributeList - (NSString *)nameAtIndex:(NSUInteger)_idx; - (NSString *)typeAtIndex:(NSUInteger)_idx; - (NSString *)valueAtIndex:(NSUInteger)_idx; - (NSString *)typeForName:(NSString *)_name; - (NSString *)valueForName:(NSString *)_name; - (NSUInteger)count; @end @interface SaxAttributeList : NSObject < SaxAttributeList, NSCopying > { @private NSMutableArray *names; NSMutableArray *types; NSMutableArray *values; } - (id)init; - (id)initWithAttributeList:(id)_attrList; - (void)setAttributeList:(id)_attrList; - (void)clear; - (void)addAttribute:(NSString *)_name type:(NSString *)_type value:(NSString *)_value; - (void)removeAttribute:(NSString *)_attr; @end #include @interface SaxAttributeList(Compatibility) - (id)initWithAttributes:(id)_attrs; @end #endif /* __SaxAttributeList_H__ */ SOPE/sope-xml/SaxObjC/COPYING0000644000000000000000000006130315004363604014416 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-xml/SaxObjC/fhs.make0000644000000000000000000000173615004363604015006 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) FHS_INCLUDE_DIR=$(FHS_INSTALL_ROOT)/include/ FHS_BIN_DIR=$(FHS_INSTALL_ROOT)/bin/ ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib64/ else FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib/ endif fhs-header-dirs :: $(MKDIRS) $(FHS_INCLUDE_DIR)$(libSaxObjC_HEADER_FILES_INSTALL_DIR) move-headers-to-fhs :: fhs-header-dirs @echo "moving headers to $(FHS_INCLUDE_DIR) .." mv $(GNUSTEP_HEADERS)$(libSaxObjC_HEADER_FILES_INSTALL_DIR)/*.h \ $(FHS_INCLUDE_DIR)$(libSaxObjC_HEADER_FILES_INSTALL_DIR)/ NONFHS_LIBDIR="$(GNUSTEP_LIBRARIES)/$(GNUSTEP_TARGET_LDIR)/" NONFHS_LIBNAME="$(LIBRARY_NAME)$(LIBRARY_NAME_SUFFIX)$(SHARED_LIBEXT)" move-libs-to-fhs :: @echo "moving libs to $(FHS_LIB_DIR) .." mv $(NONFHS_LIBDIR)/$(NONFHS_LIBNAME)* $(FHS_LIB_DIR)/ move-to-fhs :: move-headers-to-fhs move-libs-to-fhs after-install :: move-to-fhs endif SOPE/sope-xml/SaxObjC/README0000644000000000000000000000102515004363604014236 0ustar rootrootThis directory contains a SAX (Simple API for XML) for Objective-C. SaxObjDecoder ============= Take a look at SaxObjDecoder for simple mapping from XML to ObjC objects. SaxMethodCallHandler ==================== Take a look at SaxMethodCallHandler for mapping SAX events to ObjC method calls. Write a method per tag and SaxMethodCallHandler will call that for you ;-) Defaults ======== SaxCoreOnMissingParser - YES|NO - abort if a SAX driver could not be found SaxDebugReaderFactory - YES|NO - debug SAX reader lookup/loading SOPE/sope-xml/SaxObjC/SaxContentHandler.h0000644000000000000000000000355215004363604017122 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxContentHandler_H__ #define __SaxContentHandler_H__ #import #include #include @class NSString; /* new in SAX 2.0beta, replaces SaxDocumentHandler */ @protocol SaxContentHandler - (void)startDocument; - (void)endDocument; - (void)startPrefixMapping:(NSString *)_prefix uri:(NSString *)_uri; - (void)endPrefixMapping:(NSString *)_prefix; - (void)startElement:(NSString *)_localName namespace:(NSString *)_ns rawName:(NSString *)_rawName attributes:(id)_attributes; - (void)endElement:(NSString *)_localName namespace:(NSString *)_ns rawName:(NSString *)_rawName; /* CDATA */ - (void)characters:(unichar *)_chars length:(NSUInteger)_len; - (void)ignorableWhitespace:(unichar *)_chars length:(NSUInteger)_len; /* PIs */ - (void)processingInstruction:(NSString *)_pi data:(NSString *)_data; /* positioning info */ - (void)setDocumentLocator:(id)_locator; /* entities */ - (void)skippedEntity:(NSString *)_entityName; @end #endif /* __SaxContentHandler_H__ */ SOPE/sope-xml/SaxObjC/SxXML-SaxObjC.graffle0000644000000000000000000014253515004363604017164 0ustar rootroot CanvasColor w 1.000000e+00 ColumnAlign 0 ColumnSpacing 5.400000e+01 GraphDocumentVersion 2 GraphicsList Bounds {{12, 477}, {98, 18}} Class ShapedGraphic FitText YES ID 1101 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 libxmlSAXDriver} Bounds {{9, 10}, {112, 36}} Class ShapedGraphic FitText YES ID 1100 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-BoldOblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\b\fs48 \cf0 SaxObjC} Bounds {{9, 459}, {702, 1}} Class ShapedGraphic ID 1099 Shape Rectangle Class Group Graphics Bounds {{27, 81}, {131, 18}} Class ShapedGraphic ID 1073 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxDocumentHandler.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 SaxDocumentHandler} Bounds {{202, 81}, {104, 18}} Class ShapedGraphic ID 1074 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxHandlerBase.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 SaxHandlerBase} Class Group Graphics Bounds {{189, 306}, {135, 18}} Class ShapedGraphic ID 1076 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxMethodCallHandler.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 SaxMethodCallHandler} Bounds {{202, 270}, {113, 18}} Class ShapedGraphic ID 1077 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxDefaultHandler.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 SaxDefaultHandler} ID 1075 Class Group Graphics Bounds {{315, 180}, {90, 18}} Class ShapedGraphic ID 1079 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxXMLFilter.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 SaxXMLFilter} Bounds {{207, 180}, {90, 18}} Class ShapedGraphic ID 1080 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxXMLFilter.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 SaxXMLFilter} ID 1078 Bounds {{27, 180}, {131, 18}} Class ShapedGraphic ID 1081 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxEntityResolver.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 SaxEntityResolver} Bounds {{27, 135}, {131, 18}} Class ShapedGraphic ID 1082 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxDTDHandler.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 SaxDTDHandler} Bounds {{27, 270}, {131, 18}} Class ShapedGraphic ID 1083 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxContentHandler.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 SaxContentHandler} Bounds {{27, 225}, {131, 18}} Class ShapedGraphic ID 1084 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxErrorHandler.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 SaxErrorHandler} Class LineGraphic Head ID 1074 ID 1085 Points {107.182, 180} {239.318, 99} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1081 Class LineGraphic Head ID 1074 ID 1086 Points {119.417, 135} {227.083, 99} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1082 Class LineGraphic Head ID 1074 ID 1087 Points {158, 90} {202, 90} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1073 Class LineGraphic Head ID 1074 ID 1088 Points {102.594, 225} {243.906, 99} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1084 Class LineGraphic Head ID 1076 ID 1089 Points {258, 288} {257, 306} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1077 Class LineGraphic Head ID 1077 ID 1090 Points {109.1, 198} {241.9, 270} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1081 Class LineGraphic Head ID 1077 ID 1091 Points {103.567, 153} {247.433, 270} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1082 Class LineGraphic Head ID 1077 ID 1092 Points {158, 279} {202, 279} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1083 Class LineGraphic Head ID 1077 ID 1093 Points {125.7, 243} {225.3, 270} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1084 Class LineGraphic Head ID 1080 ID 1094 Points {315, 189} {297, 189} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1079 Class LineGraphic Head ID 1080 ID 1095 Points {158, 189} {207, 189} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1081 Class LineGraphic Head ID 1080 ID 1096 Points {124.4, 153} {220.1, 180} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1082 Class LineGraphic Head ID 1080 ID 1097 Points {108.45, 270} {236.05, 198} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1083 Class LineGraphic Head ID 1080 ID 1098 Points {124.4, 225} {220.1, 198} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1084 ID 1072 Bounds {{333, 504}, {130, 18}} Class ShapedGraphic ID 1071 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/libxmlSAXDriver/libxmlSAXDriver.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 libxmlSAXDriver} Class Group Graphics Bounds {{603, 81}, {90, 18}} Class ShapedGraphic ID 1068 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxAttributes.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 SaxAttributes} Bounds {{495, 81}, {90, 18}} Class ShapedGraphic ID 1069 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxAttributes.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 SaxAttributes} Class LineGraphic Head ID 1069 ID 1070 Points {603, 90} {585, 90} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1068 ID 1067 Bounds {{495, 504}, {108, 18}} Class ShapedGraphic ID 1066 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/libxmlSAXDriver/libxmlSAXLocator.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 libxmlSAXLocator} Bounds {{193, 504}, {131, 18}} Class ShapedGraphic ID 1065 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/libxmlSAXDriver/libxmlDocSAXDriver.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 libxmlDocSAXDriver} Class Group Graphics Bounds {{490, 207}, {86, 18}} Class ShapedGraphic ID 1058 Shape Rectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NSException} Bounds {{508, 333}, {167, 18}} Class ShapedGraphic ID 1059 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxException.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 SaxNotSupportedException} Bounds {{508, 279}, {167, 18}} Class ShapedGraphic ID 1060 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxException.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 SaxParseException} Bounds {{486, 243}, {91, 18}} Class ShapedGraphic ID 1061 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxException.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 SaxException} Bounds {{418, 306}, {167, 18}} Class ShapedGraphic ID 1062 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxException.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 SaxNotRecognizedException} Class LineGraphic Head ID 1059 ID 1063 Points {537.5, 261} {585.5, 333} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1061 Class LineGraphic Head ID 1060 ID 1064 Points {546.5, 261} {576.5, 279} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1061 ID 1057 Bounds {{207, 423}, {99, 18}} Class ShapedGraphic ID 1056 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxXMLReader.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 SaxXMLReader} Bounds {{54, 504}, {130, 18}} Class ShapedGraphic ID 1055 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/libxmlSAXDriver/libxmlHTMLSAXDriver.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 libxmlHTMLSAXDriver} Bounds {{527, 153}, {167, 18}} Class ShapedGraphic ID 1054 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxXMLReaderFactory.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 SaxXMLReaderFactory} Class Group Graphics Bounds {{265, 360}, {95, 18}} Class ShapedGraphic ID 1051 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxAttributeList.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 SaxAttributeList} Bounds {{144, 360}, {103, 18}} Class ShapedGraphic ID 1052 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxAttributeList.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 SaxAttributeList} Class LineGraphic Head ID 1052 ID 1053 Points {265, 369} {247, 369} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1051 ID 1050 Bounds {{527, 126}, {167, 18}} Class ShapedGraphic ID 1049 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxNamespaceSupport.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 SaxNamespaceSupport} Bounds {{495, 423}, {108, 18}} Class ShapedGraphic ID 1048 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxLocator.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 SaxLocator} Bounds {{396, 423}, {81, 18}} Class ShapedGraphic ID 1047 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxLocator.h Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 SaxLocator} Class LineGraphic Head ID 1071 ID 1046 Points {272.222, 441} {382.278, 504} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1056 Class LineGraphic Head ID 1066 ID 1045 Points {549, 441} {549, 504} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1048 Class LineGraphic Head ID 1065 ID 1044 Points {256.722, 441} {258.278, 504} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1056 Class LineGraphic Head ID 1061 ID 1043 Points {532.625, 225} {531.875, 243} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1058 Class LineGraphic Head ID 1055 ID 1042 Points {241.222, 441} {134.278, 504} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1056 Class LineGraphic Head ID 1062 ID 1041 Points {527.214, 261} {505.786, 306} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1061 Class LineGraphic Head ID 1047 ID 1040 Points {495, 432} {477, 432} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1048 GridInfo HPages 1 ImageCounter 1 IsPalette NO Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo AutoAdjust YES HierarchicalOrientation 0 MagneticFieldCenter {0, 0} MagnetsEnabled YES PageBreakColor w 3.333333e-01 PageBreaks YES PageSetup BAt0eXBlZHN0cmVhbYED6IQBQISEhAtOU1ByaW50SW5mbwGEhAhOU09iamVjdACFkoSE hBNOU011dGFibGVEaWN0aW9uYXJ5AISEDE5TRGljdGlvbmFyeQCUhAFpEpKEhIQITlNT dHJpbmcBlIQBKxBOU0pvYkRpc3Bvc2l0aW9uhpKEmZkPTlNQcmludFNwb29sSm9ihpKE mZkOTlNCb3R0b21NYXJnaW6GkoSEhAhOU051bWJlcgCEhAdOU1ZhbHVlAJSEASqEhAFm nSSGkoSZmQtOU1BhcGVyTmFtZYaShJmZBkxldHRlcoaShJmZD05TUHJpbnRBbGxQYWdl c4aShJ2chIQBc54AhpKEmZkNTlNSaWdodE1hcmdpboaShJ2cn50khpKEmZkITlNDb3Bp ZXOGkoSdnISEAVOfAYaShJmZD05TU2NhbGluZ0ZhY3RvcoaShJ2chIQBZKABhpKEmZkL TlNGaXJzdFBhZ2WGkoSdnKmfAYaShJmZFE5TVmVydGljYWxQYWdpbmF0aW9uhpKEnZyk ngCGkoSZmRVOU0hvcml6b25hbFBhZ2luYXRpb26GkoSdnKSeAIaShJmZFk5TSG9yaXpv bnRhbGx5Q2VudGVyZWSGkoSdnKSeAYaShJmZDE5TTGVmdE1hcmdpboaShJ2cn50khpKE mZkNTlNPcmllbnRhdGlvboaShJ2cpJ4BhpKEmZkZTlNQcmludFJldmVyc2VPcmllbnRh dGlvboaSo5KEmZkKTlNMYXN0UGFnZYaShJ2chJeXgn////+GkoSZmQtOU1RvcE1hcmdp boaShJ2cn50khpKEmZkUTlNWZXJ0aWNhbGx5Q2VudGVyZWSGkrSShJmZC05TUGFwZXJT aXplhpKEnpyEhAx7X05TU2l6ZT1mZn2hgQMYgQJkhoaG RowAlign 0 RowSpacing 9.000000e+00 VPages 1 WindowInfo Frame {{109, 134}, {783, 743}} VisibleRegion {{-24, -63}, {768, 666}} Zoom 1 SOPE/sope-xml/SaxObjC/SaxErrorHandler.h0000644000000000000000000000210015004363604016565 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxErrorHandler_H__ #define __SaxErrorHandler_H__ @class SaxParseException; @protocol SaxErrorHandler - (void)warning:(SaxParseException *)_exception; - (void)error:(SaxParseException *)_exception; - (void)fatalError:(SaxParseException *)_exception; @end #endif /* __SaxErrorHandler_H__ */ SOPE/sope-xml/SaxObjC/SaxAttributes.m0000644000000000000000000001361615004363604016347 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SaxAttributes.h" #include "common.h" @implementation SaxAttributes - (id)init { Class c = [NSMutableArray class]; self->names = [[c alloc] init]; self->uris = [[c alloc] init]; self->rawNames = [[c alloc] init]; self->types = [[c alloc] init]; self->values = [[c alloc] init]; return self; } - (id)initWithAttributes:(id)_attrs { if ((self = [self init])) { NSUInteger i, c; for (i = 0, c = [_attrs count]; i < c; i++) { [self addAttribute:[_attrs nameAtIndex:i] uri:[_attrs uriAtIndex:i] rawName:[_attrs rawNameAtIndex:i] type:[_attrs typeAtIndex:i] value:[_attrs valueAtIndex:i]]; } } return self; } - (id)initWithAttributeList:(id)_attrList { if ((self = [self init])) { NSUInteger i; for (i = 0; i < [_attrList count]; i++) { [self addAttribute:[_attrList nameAtIndex:i] uri:@"" rawName:[_attrList nameAtIndex:i] type:[_attrList typeAtIndex:i] value:[_attrList valueAtIndex:i]]; } } return self; } - (id)initWithDictionary:(NSDictionary *)_dict { if ((self = [self init])) { NSEnumerator *keys; NSString *key; keys = [_dict keyEnumerator]; while ((key = [keys nextObject])) { [self addAttribute:key uri:nil rawName:key type:nil value:[_dict objectForKey:key]]; } } return self; } - (void)dealloc { [self->names release]; [self->uris release]; [self->rawNames release]; [self->types release]; [self->values release]; [super dealloc]; } /* modifications */ - (void)addAttribute:(NSString *)_localName uri:(NSString *)_uri rawName:(NSString *)_rawName type:(NSString *)_type value:(NSString *)_value { [self->names addObject:_localName ? _localName : _rawName]; [self->uris addObject:_uri ? _uri : (NSString *)@""]; [self->rawNames addObject:_rawName ? _rawName : (NSString *)@""]; [self->types addObject:_type ? _type : (NSString *)@"CDATA"]; [self->values addObject:_value]; } - (void)clear { [self->names removeAllObjects]; [self->uris removeAllObjects]; [self->rawNames removeAllObjects]; [self->types removeAllObjects]; [self->values removeAllObjects]; } /* lookup indices */ - (NSUInteger)indexOfRawName:(NSString *)_rawName { return [self->rawNames indexOfObject:_rawName]; } - (NSUInteger)indexOfName:(NSString *)_localPart uri:(NSString *)_uri { NSUInteger i, c; for (i = 0, c = [self count]; i < c; i++) { NSString *name; name = [self nameAtIndex:i]; if ([name isEqualToString:_localPart]) { NSString *auri; auri = [self uriAtIndex:i]; //NSLog(@"found name %@", name); if (([auri length] == 0) && ([_uri length] == 0)) return i; if ([_uri isEqualToString:auri]) return i; } } return NSNotFound; } /* lookup data by index */ - (NSString *)nameAtIndex:(NSUInteger)_idx { return [self->names objectAtIndex:_idx]; } - (NSString *)rawNameAtIndex:(NSUInteger)_idx { return [self->rawNames objectAtIndex:_idx]; } - (NSString *)typeAtIndex:(NSUInteger)_idx { return [self->types objectAtIndex:_idx]; } - (NSString *)uriAtIndex:(NSUInteger)_idx { return [self->uris objectAtIndex:_idx]; } - (NSString *)valueAtIndex:(NSUInteger)_idx { return [self->values objectAtIndex:_idx]; } /* lookup data by name */ - (NSString *)typeForRawName:(NSString *)_rawName { NSUInteger i; if ((i = [self indexOfRawName:_rawName]) == NSNotFound) return nil; return [self typeAtIndex:i]; } - (NSString *)typeForName:(NSString *)_localName uri:(NSString *)_uri { NSUInteger i; if ((i = [self indexOfName:_localName uri:_uri]) == NSNotFound) return nil; return [self typeAtIndex:i]; } - (NSString *)valueForRawName:(NSString *)_rawName { NSUInteger i; if ((i = [self indexOfRawName:_rawName]) == NSNotFound) return nil; return [self valueAtIndex:i]; } - (NSString *)valueForName:(NSString *)_localName uri:(NSString *)_uri { NSUInteger i; if ((i = [self indexOfName:_localName uri:_uri]) == NSNotFound) return nil; return [self valueAtIndex:i]; } /* list size */ - (NSUInteger)count { return [self->names count]; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { return [(SaxAttributes *)[[self class] alloc] initWithAttributes:self]; } /* description */ - (NSString *)description { NSMutableString *s; NSString *is; NSUInteger i, c; s = [[NSMutableString alloc] init]; [s appendFormat:@"<%p[%@]:", self, NSStringFromClass([self class])]; for (i = 0, c = [self count]; i < c; i++) { NSString *type; [s appendString:@" "]; [s appendString:[self nameAtIndex:i]]; [s appendString:@"='"]; [s appendString:[self valueAtIndex:i]]; [s appendString:@"'"]; type = [self typeAtIndex:i]; if (![type isEqualToString:@"CDATA"]) { [s appendString:@"["]; [s appendString:type]; [s appendString:@"]"]; } } [s appendString:@">"]; is = [s copy]; [s release]; return [is autorelease]; } @end /* SaxAttributes */ SOPE/sope-xml/SaxObjC/SaxXMLFilter.h0000644000000000000000000000317215004363604016016 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxXMLFilter_H__ #define __SaxXMLFilter_H__ #import #include /* new in SAX 2.0beta */ @protocol SaxXMLFilter < SaxXMLReader > - (void)setParent:(id)_parent; - (id)parent; @end #include "SaxEntityResolver.h" #include "SaxDTDHandler.h" #include "SaxContentHandler.h" #include "SaxErrorHandler.h" @interface SaxXMLFilter : NSObject < SaxXMLFilter, SaxEntityResolver, SaxDTDHandler, SaxContentHandler, SaxErrorHandler > { @private id parent; id contentHandler; id dtdHandler; id errorHandler; id entityResolver; } - (id)initWithParent:(id)_parent; @end #endif /* __SaxXMLFilter_H__ */ SOPE/sope-xml/SaxObjC/SaxObjectModel.h0000644000000000000000000000473615004363604016406 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxObjC_SaxObjectModel_H__ #define __SaxObjC_SaxObjectModel_H__ #import @class NSDictionary, NSString, NSArray; @class SaxTagModel; @interface SaxObjectModel : NSObject { NSDictionary *nsToModel; } + (id)modelWithName:(NSString *)_name; + (id)modelWithContentsOfFile:(NSString *)_path; + (NSString *)libraryDriversSubDir; - (id)initWithDictionary:(NSDictionary *)_dict; /* queries */ - (SaxTagModel *)modelForTag:(NSString *)_localName namespace:(NSString *)_ns; @end @interface SaxNamespaceModel : NSObject { NSDictionary *tagToModel; } /* queries */ - (SaxTagModel *)modelForTag:(NSString *)_localName; @end @interface SaxTagModel : NSObject { NSString *className; NSString *key; NSString *tagKey; /* the key to store the tag name under */ NSString *namespaceKey; /* the key to store the namespace uri under */ NSString *parentKey; /* the key to store the parent object under */ NSString *contentKey; /* the key to store the cdata content under */ NSArray *toManyRelationshipKeys; NSDictionary *defaultValues; NSDictionary *tagToKey; NSDictionary *attrToKey; } /* accessors */ - (NSString *)className; - (NSString *)key; - (NSString *)tagKey; - (NSString *)namespaceKey; - (NSString *)parentKey; - (NSString *)contentKey; - (NSDictionary *)defaultValues; - (NSString *)propertyKeyForChildTag:(NSString *)_tag; - (BOOL)isToManyKey:(NSString *)_key; - (NSArray *)toManyRelationshipKeys; - (NSArray *)attributeKeys; - (NSString *)propertyKeyForAttribute:(NSString *)_attr; /* object operations */ - (void)addValue:(id)_val toPropertyWithKey:(NSString *)_key ofObject:(id)_obj; @end #endif /* __SaxObjC_SaxObjectModel_H__ */ SOPE/sope-xml/SaxObjC/SaxObjectDecoder.h0000644000000000000000000000331415004363604016702 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxObjC_SaxObjectDecoder_H__ #define __SaxObjC_SaxObjectDecoder_H__ #include /* This SAX handler takes a model dictionary and maps the SAX events to object construction commands. [to be done: further description of format and function] */ @class SaxObjectModel; @interface SaxObjectDecoder : SaxDefaultHandler { id locator; id rootObject; id mapping; NSMutableArray *infoStack; NSMutableArray *mappingStack; NSMutableArray *objectStack; } - (id)initWithMappingModel:(SaxObjectModel *)_model; - (id)initWithMappingAtPath:(NSString *)_path; - (id)initWithMappingNamed:(NSString *)_name; /* parse results */ - (id)rootObject; /* cleanup */ - (void)reset; @end @interface NSObject(SaxObjectCoding) - (id)initWithSaxDecoder:(SaxObjectDecoder *)_decoder; - (id)awakeAfterUsingSaxDecoder:(SaxObjectDecoder *)_decoder; @end #endif /* __SaxObjC_SaxObjectDecoder_H__ */ SOPE/sope-xml/SaxObjC/Version0000644000000000000000000000004515004363604014727 0ustar rootroot# version file SUBMINOR_VERSION:=66 SOPE/sope-xml/SaxObjC/SaxObjectDecoder.m0000644000000000000000000002774315004363604016723 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SaxObjectDecoder.h" #include "SaxObjectModel.h" #include "common.h" static BOOL debugOn = NO; @interface _SaxObjTagInfo : NSObject { @public SaxObjectDecoder *decoder; /* non-retained */ _SaxObjTagInfo *parentInfo; /* non-retained */ SaxTagModel *mapping; NSString *tagName; NSString *namespace; NSException *error; id object; struct { int isRoot:1; int isMutableDict:1; int isString:1; int isMutableString:1; int hasContentKey:1; } flags; NSMutableString *collectedCharData; } /* accessors */ - (SaxTagModel *)mapping; - (id)object; /* tag handling */ - (void)start; - (void)stop; - (void)characters:(unichar *)_chars length:(NSUInteger)_len; @end @implementation SaxObjectDecoder static NSNull *null = nil; + (void)initialize { static BOOL didInit = NO; NSUserDefaults *ud; if (didInit) return; didInit = YES; null = [[NSNull null] retain]; ud = [NSUserDefaults standardUserDefaults]; debugOn = [ud boolForKey:@"SaxObjectDecoderDebugEnabled"]; } - (id)initWithMappingModel:(SaxObjectModel *)_model { if ((self = [super init])) { self->mapping = [_model retain]; } return self; } - (id)initWithMappingAtPath:(NSString *)_path { SaxObjectModel *model; model = [SaxObjectModel modelWithContentsOfFile:_path]; return [self initWithMappingModel:model]; } - (id)initWithMappingNamed:(NSString *)_name { SaxObjectModel *model; model = [SaxObjectModel modelWithName:_name]; return [self initWithMappingModel:model]; } - (id)init { return [self initWithMappingModel:nil]; } - (void)dealloc { [self->locator release]; [self->rootObject release]; [self->mapping release]; [self->infoStack release]; [self->mappingStack release]; [self->objectStack release]; [super dealloc]; } /* parse results */ - (id)rootObject { return self->rootObject; } /* cleanup */ - (void)parseReset { NSAutoreleasePool *pool; pool = [[NSAutoreleasePool alloc] init]; [self->infoStack removeAllObjects]; [self->mappingStack removeAllObjects]; [self->objectStack removeAllObjects]; [pool release]; } - (void)reset { [self parseReset]; [self->rootObject release]; self->rootObject = nil; } /* parsing */ - (void)startDocument { [self reset]; if (self->infoStack == nil) self->infoStack = [[NSMutableArray alloc] initWithCapacity:16]; } - (void)endDocument { [self parseReset]; } /* positioning info */ - (void)setDocumentLocator:(id)_locator { ASSIGN(self->locator, _locator); } /* stacks */ - (void)pushInfo:(_SaxObjTagInfo *)_info { [self->infoStack addObject:_info]; } - (void)popInfo { [self->infoStack removeObjectAtIndex:([self->infoStack count] - 1)]; } - (id)currentInfo { return [self->infoStack lastObject]; } /* elements */ - (NSException *)missingNamespaceMapping:(NSString *)_ns { return [NSException exceptionWithName:@"MissingNamespaceMapping" reason:_ns userInfo:nil]; } - (NSException *)missingElementMapping:(NSString *)_ns :(NSString *)_tag { return [NSException exceptionWithName:@"MissingElementMapping" reason:_tag userInfo:nil]; } - (NSException *)missingMappedClass:(NSString *)_className { return [NSException exceptionWithName:@"MissingMappedClass" reason:_className userInfo:nil]; } - (SaxTagModel *)mappingForTag:(NSString *)_tag namespace:(NSString *)_ns { return [self->mapping modelForTag:_tag namespace:_ns]; } - (void)couldNotApplyAttribute:(NSString *)_attr asKey:(NSString *)_key onObject:(id)_object { NSLog(@"SaxObjectDecoder: could not apply attribute '%@' (key=%@) " @"on object %@", _attr, _key, _object); } - (void)startElement:(NSString *)_localName namespace:(NSString *)_ns rawName:(NSString *)_rawName attributes:(id)_attributes { _SaxObjTagInfo *info; info = [_SaxObjTagInfo alloc]; info->decoder = self; info->flags.isRoot = [self->infoStack count] == 0 ? 1 : 0; info->parentInfo = info->flags.isRoot ? nil : [self->infoStack lastObject]; info->tagName = [_localName copy]; info->namespace = [_ns copy]; [self->infoStack addObject:info]; [info release]; /* determine mapping dictionary */ if ((info->mapping = [self mappingForTag:_localName namespace:_ns]) == nil) { if (debugOn) { NSLog(@"found no mapping for element '%@' (namespace %@)", _localName, _ns); } info->error = [[self missingElementMapping:_ns:_localName] retain]; return; } /* start object */ [info start]; /* add attribute values */ { NSEnumerator *e; NSString *a; e = [[info->mapping attributeKeys] objectEnumerator]; while ((a = [e nextObject])) { NSString *v, *key; if ((v = [_attributes valueForName:a uri:_ns])) { key = [info->mapping propertyKeyForAttribute:a]; NS_DURING [info->object takeValue:v forKey:key]; NS_HANDLER [self couldNotApplyAttribute:a asKey:key onObject:info->object]; NS_ENDHANDLER; } } } } - (void)endElement:(NSString *)_localName namespace:(NSString *)_ns rawName:(NSString *)_rawName { _SaxObjTagInfo *info; unsigned idx; idx = [self->infoStack count] - 1; info = [self->infoStack objectAtIndex:idx]; [info stop]; if (idx == 0) ASSIGN(self->rootObject, [info object]); [self->infoStack removeObjectAtIndex:idx]; } /* CDATA */ - (void)characters:(unichar *)_chars length:(NSUInteger)_len { _SaxObjTagInfo *info; if (_len == 0) return; info = [self->infoStack objectAtIndex:([self->infoStack count] - 1)]; [info characters:_chars length:_len]; } - (BOOL)processIgnorableWhitespace { return NO; } - (void)ignorableWhitespace:(unichar *)_chars length:(NSUInteger)_len { if ([self processIgnorableWhitespace]) [self characters:_chars length:_len]; } @end /* SaxObjectDecoder */ @implementation NSObject(SaxObjectCoding) - (id)initWithSaxDecoder:(SaxObjectDecoder *)_decoder { return [self init]; } - (id)awakeAfterUsingSaxDecoder:(SaxObjectDecoder *)_decoder { return self; } @end /* SaxCoding */ @implementation _SaxObjTagInfo static Class MutableDictClass = Nil; static Class MutableStringClass = Nil; static Class StringClass = Nil; + (void)initialize { MutableDictClass = [NSMutableDictionary class]; MutableStringClass = [NSMutableString class]; StringClass = [NSString class]; } - (void)dealloc { [self->tagName release]; [self->namespace release]; [self->error release]; [self->object release]; [self->collectedCharData release]; [super dealloc]; } /* errors */ - (NSException *)missingMappedClass:(NSString *)_className { return [NSException exceptionWithName:@"MissingMappedClass" reason:_className userInfo:nil]; } /* accessors */ - (SaxTagModel *)mapping { return self->mapping; } - (id)object { return (self->object == null) ? nil : self->object; } - (SaxTagModel *)parentMapping { return [self->parentInfo mapping]; } - (id)parentObject { return [self->parentInfo object]; } /* run */ - (Class)defaultElementClass { return [NSMutableDictionary class]; } - (void)unableToSetValue:(id)_object forKey:(NSString *)_key withTag:(NSString *)_tag toParent:(id)_parent exception:(NSException *)_exc { NSLog(@"couldn't apply value %@ for key %@ with parent %@<%@>: %@", _object, _key, _parent, NSStringFromClass([_parent class]), _exc); } - (void)addObject:(id)_object fromTag:(NSString *)_tag withMapping:(SaxTagModel *)_elementMap toParent:(id)_parent withMapping:(SaxTagModel *)_parentMap { NSString *key; if (_object == nil || _object == null) return; if (_parent == nil || _parent == null) return; if (_elementMap == nil || _elementMap == (id)null) return; if (_parentMap == nil || _parentMap == (id)null) return; if ((key = [_parentMap propertyKeyForChildTag:_tag]) == nil) { if ((key = [_elementMap key]) == nil) key = _tag; } NS_DURING { if ([_parentMap isToManyKey:key]) { [_parentMap addValue:_object toPropertyWithKey:key ofObject:_parent]; } else { [_parent takeValue:_object forKey:key]; } } NS_HANDLER { [self unableToSetValue:_object forKey:key withTag:_tag toParent:_parent exception:localException]; } NS_ENDHANDLER; } - (void)start { NSString *s; Class mappedClazz; /* determine class */ if ((s = [self->mapping className])) { mappedClazz = NSClassFromString(s); if (mappedClazz == Nil) { self->error = [[self missingMappedClass:s] retain]; return; } } else mappedClazz = [self defaultElementClass]; /* do we need to check for subclasses? I guess not. */ self->flags.isMutableDict = (mappedClazz == MutableDictClass) ? 1 : 0; self->flags.isMutableString = (mappedClazz == MutableStringClass) ? 1 : 0; self->flags.isString = (mappedClazz == StringClass) ? 1 : 0; self->flags.hasContentKey = [[self->mapping contentKey] length] > 0 ?1:0; /* create an object for the element .. */ if ((self->object = [[mappedClazz alloc] initWithSaxDecoder:self->decoder])) { NSDictionary *defaultValues; id tmp; if ((defaultValues = [self->mapping defaultValues])) [self->object takeValuesFromDictionary:defaultValues]; if ((tmp = [self->mapping tagKey])) [self->object takeValue:self->tagName forKey:tmp]; if ((tmp = [self->mapping namespaceKey])) [self->object takeValue:self->namespace forKey:tmp]; } } - (void)stop { id tmp; /* awake from decoding (the decoded object can replace itself :-) */ if (self->flags.isString) { } else { if (self->flags.hasContentKey) { NSString *s; s = [self->collectedCharData copy]; ASSIGN(self->collectedCharData, (id)nil); [self->object takeValue:s forKey:[self->mapping contentKey]]; [s release]; } tmp = self->object; self->object = [[self->object awakeAfterUsingSaxDecoder:self->decoder] retain]; [tmp release]; } if (!self->flags.isRoot) { NSString *t; id parent; parent = [self parentObject]; /* add to parent */ if ((t = [self->mapping parentKey])) [self->object takeValue:parent forKey:t]; [self addObject:self->object fromTag:self->tagName withMapping:self->mapping toParent:parent withMapping:[self parentMapping]]; } } - (void)characters:(unichar *)_chars length:(NSUInteger)_len { if (self->flags.isMutableString) { NSString *tmp; tmp = [[NSString alloc] initWithCharacters:_chars length:_len]; [self->object appendString:tmp]; [tmp release]; } else if (self->flags.isString) { NSString *tmp, *old; old = self->object; tmp = [[NSString alloc] initWithCharacters:_chars length:_len]; self->object = [[self->object stringByAppendingString:tmp] retain]; [tmp release]; [old release]; } else if (self->flags.hasContentKey) { if (self->collectedCharData == nil) { self->collectedCharData = [[NSMutableString alloc] initWithCharacters:_chars length:_len]; } else { NSString *tmp; tmp = [[NSString alloc] initWithCharacters:_chars length:_len]; [self->collectedCharData appendString:tmp]; [tmp release]; } } } @end /* _SaxObjTagInfo */ SOPE/sope-xml/SaxObjC/SaxObjC.h0000644000000000000000000000276315004363604015032 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxObjC_H__ #define __SaxObjC_H__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif /* __SaxObjC_H__ */ SOPE/sope-xml/SaxObjC/SaxLocator.h0000644000000000000000000000300615004363604015607 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxLocator_H__ #define __SaxLocator_H__ #import @class NSString; @protocol SaxLocator - (NSInteger)columnNumber; - (NSInteger)lineNumber; - (NSString *)publicId; - (NSString *)systemId; @end /* sample locator */ @interface SaxLocator : NSObject < SaxLocator, NSCopying > { @private int column; int line; NSString *pubId; NSString *sysId; } - (id)init; - (id)initWithLocator:(id)_locator; - (void)setColumnNumber:(NSInteger)_col; - (NSInteger)columnNumber; - (void)setLineNumber:(NSInteger)_line; - (NSInteger)lineNumber; - (void)setPublicId:(NSString *)_pubId; - (NSString *)publicId; - (void)setSystemId:(NSString *)_sysId; - (NSString *)systemId; @end #endif /* __SaxLocator_H__ */ SOPE/sope-xml/SaxObjC/SaxEntityResolver.h0000644000000000000000000000202515004363604017202 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxEntityResolver_H__ #define __SaxEntityResolver_H__ @class NSString; @protocol SaxEntityResolver - (id)resolveEntityWithPublicId:(NSString *)_pubId systemId:(NSString *)_sysId; @end /* SaxEntityResolver */ #endif /* __SaxEntityResolver_H__ */ SOPE/sope-xml/SaxObjC/SaxHandlerBase.m0000644000000000000000000000371615004363604016371 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SaxHandlerBase.h" #include "SaxException.h" @implementation SaxHandlerBase /* SaxDocumentHandler */ - (void)startDocument { } - (void)endDocument { } - (void)startElement:(NSString *)_tagName attributes:(id)_attrs { } - (void)endElement:(NSString *)_tagName { } - (void)characters:(unichar *)_chars length:(NSUInteger)_len { } - (void)ignorableWhitespace:(unichar *)_chars length:(NSUInteger)_len { } - (void)processingInstruction:(NSString *)_pi data:(NSString *)_data { } - (void)setDocumentLocator:(id)_locator { } /* SaxDTDHandler */ - (void)notationDeclaration:(NSString *)_name publicId:(NSString *)_pubId systemId:(NSString *)_sysId { } - (void)unparsedEntityDeclaration:(NSString *)_name publicId:(NSString *)_pubId systemId:(NSString *)_sysId notationName:(NSString *)_notName { } /* SaxEntityResolver */ - (id)resolveEntityWithPublicId:(NSString *)_pubId systemId:(NSString *)_sysId { return nil; } /* SaxErrorHandler */ - (void)warning:(SaxParseException *)_exception { } - (void)error:(SaxParseException *)_exception { } - (void)fatalError:(SaxParseException *)_exception { [_exception raise]; } @end /* SaxHandlerBase */ SOPE/sope-xml/SaxObjC/SaxObjectModel.m0000644000000000000000000002666215004363604016415 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SaxObjectModel.h" #include "common.h" #if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY || \ APPLE_FOUNDATION_LIBRARY bool _CFArrayIsMutable(CFArrayRef dict); #endif static NSDictionary *mapDictsToObjects(NSDictionary *_dict, Class clazz) { NSMutableDictionary *md; NSEnumerator *e; NSString *key; md = [NSMutableDictionary dictionaryWithCapacity:16]; e = [_dict keyEnumerator]; while ((key = [e nextObject])) { id obj; obj = [[clazz alloc] initWithDictionary:[_dict objectForKey:key]]; [md setObject:obj forKey:key]; [obj release]; } return md; } @implementation SaxObjectModel static BOOL doDebug = NO; static NSArray *searchPathes = nil; #if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY || \ APPLE_FOUNDATION_LIBRARY static Class NSCFArrayClass = Nil; + (void)initialize { static BOOL isInitialized = NO; if (isInitialized) return; isInitialized = YES; NSCFArrayClass = NSClassFromString(@"NSCFArray"); } #endif + (NSArray *)saxMappingSearchPathes { if (searchPathes == nil) { NSMutableArray *ma; ma = [NSMutableArray arrayWithCapacity:6]; #if COCOA_Foundation_LIBRARY id tmp; tmp = NSSearchPathForDirectoriesInDomains(NSAllLibrariesDirectory, NSAllDomainsMask, YES); if ([tmp count] > 0) { NSEnumerator *e; e = [tmp objectEnumerator]; while ((tmp = [e nextObject])) { tmp = [tmp stringByAppendingPathComponent:@"SaxMappings"]; if (![ma containsObject:tmp]) [ma addObject:tmp]; } } #elif GNUSTEP_BASE_LIBRARY NSEnumerator *libraryPaths; NSString *directory, *suffix; suffix = [self libraryDriversSubDir]; libraryPaths = [NSStandardLibraryPaths() objectEnumerator]; while ((directory = [libraryPaths nextObject])) [ma addObject: [directory stringByAppendingPathComponent: suffix]]; #else NSDictionary *env; id tmp; env = [[NSProcessInfo processInfo] environment]; if ((tmp = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"]) == nil) tmp = [env objectForKey:@"GNUSTEP_PATHLIST"]; tmp = [tmp componentsSeparatedByString:@":"]; if ([tmp count] > 0) { NSEnumerator *e; e = [tmp objectEnumerator]; while ((tmp = [e nextObject])) { tmp = [tmp stringByAppendingPathComponent:@"Library/SaxMappings"]; if (![ma containsObject:tmp]) [ma addObject:tmp]; } } #endif /* FHS fallback */ { NSString *p; p = [NSString stringWithFormat:@"share/sope-%i.%i/saxmappings/", SOPE_MAJOR_VERSION, SOPE_MINOR_VERSION]; #ifdef FHS_INSTALL_ROOT [ma addObject:[FHS_INSTALL_ROOT stringByAppendingPathComponent:p]]; #endif [ma addObject:[@"/usr/local/" stringByAppendingString:p]]; [ma addObject:[@"/usr/" stringByAppendingString:p]]; } searchPathes = [ma copy]; if ([searchPathes count] == 0) NSLog(@"%s: no search pathes were found!", __PRETTY_FUNCTION__); } return searchPathes; } + (NSString *)libraryDriversSubDir { return [NSString stringWithFormat:@"SaxMappings"]; } + (id)modelWithName:(NSString *)_name { NSFileManager *fileManager; NSEnumerator *pathes; NSString *path; /* first look in main bundle */ if ((path = [[NSBundle mainBundle] pathForResource:_name ofType:@"xmap"])) return [self modelWithContentsOfFile:path]; /* then in Library */ fileManager = [NSFileManager defaultManager]; pathes = [[[self class] saxMappingSearchPathes] objectEnumerator]; _name = [_name stringByAppendingPathExtension:@"xmap"]; while ((path = [pathes nextObject])) { BOOL isDir; path = [path stringByAppendingPathComponent:_name]; if (![fileManager fileExistsAtPath:path isDirectory:&isDir]) continue; if (isDir) continue; break; } return [self modelWithContentsOfFile:path]; } + (id)modelWithContentsOfFile:(NSString *)_path { NSDictionary *dict; if ((dict = [NSDictionary dictionaryWithContentsOfFile:_path]) == nil) return nil; return [[[self alloc] initWithDictionary:dict] autorelease]; } - (id)initWithDictionary:(NSDictionary *)_dict { self->nsToModel = [mapDictsToObjects(_dict, [SaxNamespaceModel class]) retain]; return self; } - (void)dealloc { [self->nsToModel release]; [super dealloc]; } /* queries */ - (SaxTagModel *)modelForTag:(NSString *)_localName namespace:(NSString *)_ns { SaxNamespaceModel *nsmap; if ((nsmap = [self->nsToModel objectForKey:_ns]) == nil) { if ((nsmap = [self->nsToModel objectForKey:@"*"]) == nil) return nil; } return [nsmap modelForTag:_localName]; } /* faking dictionary */ - (id)objectForKey:(id)_key { return [self->nsToModel objectForKey:_key]; } @end /* SaxMappingModel */ @implementation SaxNamespaceModel - (id)initWithDictionary:(NSDictionary *)_dict { self->tagToModel = [mapDictsToObjects(_dict, [SaxTagModel class]) retain]; return self; } - (void)dealloc { [self->tagToModel release]; [super dealloc]; } /* queries */ - (SaxTagModel *)modelForTag:(NSString *)_localName { SaxTagModel *map; if ((map = [self->tagToModel objectForKey:_localName])) return map; if ((map = [self->tagToModel objectForKey:@"*"])) return map; return nil; } /* faking dictionary */ - (id)objectForKey:(id)_key { return [self->tagToModel objectForKey:_key]; } @end /* SaxNamespaceModel */ @implementation SaxTagModel - (NSDictionary *)_extractAttributeMapping:(NSDictionary *)as { NSMutableDictionary *md; NSEnumerator *keys; NSString *k; NSDictionary *result; md = [[NSMutableDictionary alloc] initWithCapacity:16]; keys = [as keyEnumerator]; while ((k = [keys nextObject])) { id val; val = [as objectForKey:k]; if ([val isKindOfClass:[NSString class]]) [md setObject:val forKey:k]; else if ([val count] == 0) [md setObject:k forKey:k]; else [md setObject:[(NSDictionary *)val objectForKey:@"key"] forKey:k]; } result = [md copy]; [md release]; return result; } - (id)initWithDictionary:(NSDictionary *)_dict { if ((self = [super init])) { NSDictionary *rels; NSDictionary *as; self->className = [[_dict objectForKey:@"class"] copy]; self->key = [[_dict objectForKey:@"key"] copy]; self->tagKey = [[_dict objectForKey:@"tagKey"] copy]; self->namespaceKey = [[_dict objectForKey:@"namespaceKey"] copy]; self->parentKey = [[_dict objectForKey:@"parentKey"] copy]; self->contentKey = [[_dict objectForKey:@"contentKey"] copy]; self->defaultValues = [[_dict objectForKey:@"defaultValues"] copy]; if ((as = [_dict objectForKey:@"attributes"])) self->attrToKey = [self _extractAttributeMapping:as]; if ((rels = [_dict objectForKey:@"ToManyRelationships"])) { NSMutableDictionary *md; NSEnumerator *keys; NSString *k; self->toManyRelationshipKeys = [[rels allKeys] copy]; md = [[NSMutableDictionary alloc] initWithCapacity:16]; keys = [self->toManyRelationshipKeys objectEnumerator]; while ((k = [keys nextObject])) { id tags; NSString *tag; tags = [rels objectForKey:k]; if ([tags isKindOfClass:[NSString class]]) tags = [NSArray arrayWithObject:tags]; tags = [tags objectEnumerator]; while ((tag = [tags nextObject])) { NSString *t; if ((t = [md objectForKey:tag])) { NSLog(@"SaxObjectModel: cannot map tag '%@' to key '%@', " @"it is already mapped to key '%@'.", tag, k, t); } else { [md setObject:k forKey:tag]; } } } self->tagToKey = [md copy]; [md release]; } } return self; } - (void)dealloc { [self->defaultValues release]; [self->toManyRelationshipKeys release]; [self->tagToKey release]; [self->className release]; [self->tagKey release]; [self->namespaceKey release]; [self->parentKey release]; [self->contentKey release]; [self->key release]; [self->attrToKey release]; [super dealloc]; } /* accessors */ - (NSString *)className { return self->className; } - (NSString *)key { return self->key; } - (NSString *)tagKey { return self->tagKey; } - (NSString *)namespaceKey { return self->namespaceKey; } - (NSString *)parentKey { return self->parentKey; } - (NSString *)contentKey { return self->contentKey; } - (NSDictionary *)defaultValues { return self->defaultValues; } - (BOOL)isToManyKey:(NSString *)_key { return [self->toManyRelationshipKeys containsObject:_key]; } - (NSArray *)toManyRelationshipKeys { return self->toManyRelationshipKeys; } - (BOOL)isToManyTag:(NSString *)_tag { return ([self->tagToKey objectForKey:_tag] != nil) ? YES : NO; } - (NSString *)propertyKeyForChildTag:(NSString *)_tag { return [self->tagToKey objectForKey:_tag]; } - (NSArray *)attributeKeys { return [self->attrToKey allKeys]; } - (NSString *)propertyKeyForAttribute:(NSString *)_attr { return [self->attrToKey objectForKey:_attr]; } /* object operations */ - (void)addValue:(id)_value toPropertyWithKey:(NSString *)_key ofObject:(id)_object { NSString *selname; SEL sel; selname = [[NSString alloc] initWithFormat:@"addTo%@:", [_key capitalizedString]]; if ((sel = NSSelectorFromString(selname)) == NULL) { if (doDebug) { NSLog(@"got no selector for key '%@', selname '%@' !", _key, selname); } } [selname release]; selname = nil; if (doDebug) { NSLog(@"%s: adding value %@ to %@ of %@", __PRETTY_FUNCTION__, _value, _key, _object); NSLog(@" selector: %@", NSStringFromSelector(sel)); } if ((sel != NULL) && [_object respondsToSelector:sel]) { [_object performSelector:sel withObject:_value]; } else { id v; v = [_object valueForKey:_key]; if ([self isToManyKey:_key]) { /* to-many relationship */ if (v == nil) { [_object takeValue:[NSArray arrayWithObject:_value] forKey:_key]; } else { #if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY || \ APPLE_FOUNDATION_LIBRARY if ([v isKindOfClass:NSCFArrayClass] && _CFArrayIsMutable((CFArrayRef)v)) #else if ([v respondsToSelector:@selector(addObject:)]) #endif /* the value is mutable */ [v addObject:_value]; else { /* the value is immutable */ v = [v arrayByAddingObject:_value]; [_object takeValue:v forKey:_key]; } } } else { NSLog(@" APPLIED ON TO-ONE (%@) !", _key); /* to-one relationship */ if (v != _value) [_object takeValue:v forKey:_key]; } } } @end /* SaxTagModel */ SOPE/sope-xml/SaxObjC/SaxMethodCallHandler.m0000644000000000000000000002107315004363604017527 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SaxMethodCallHandler.h" #include "common.h" @interface NSObject(ToBeFixed) - (id)performSelector:(SEL)_sel withObject:(id)_arg1 withObject:(id)_arg2 withObject:(id)_arg3; @end @implementation SaxMethodCallHandler static BOOL debugOn = NO; - (id)init { if ((self = [super init]) != nil) { self->delegate = self; self->fqNameToStartSel = NSCreateMapTable(NSObjectMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 64); self->selName = [[NSMutableString alloc] initWithCapacity:64]; self->tagStack = [[NSMutableArray alloc] initWithCapacity:16]; self->startKey = @"start_"; self->endKey = @"end_"; self->unknownNamespaceKey = @"any_"; self->ignoreLevel = -1; } return self; } - (void)dealloc { NSFreeMapTable(self->fqNameToStartSel); [self->tagStack release]; [self->unknownNamespaceKey release]; [self->startKey release]; [self->endKey release]; [self->selName release]; [self->namespaceToKey release]; [super dealloc]; } - (void)registerNamespace:(NSString *)_namespace withKey:(NSString *)_key { if (self->namespaceToKey == nil) self->namespaceToKey = [[NSMutableDictionary alloc] initWithCapacity:16]; [self->namespaceToKey setObject:_key forKey:_namespace]; } - (void)setDelegate:(id)_delegate { NSResetMapTable(self->fqNameToStartSel); self->delegate = _delegate; } - (id)delegate { return self->delegate; } - (void)setStartKey:(NSString *)_s { id o = self->startKey; self->startKey = [_s copy]; [o release]; } - (NSString *)startKey { return self->startKey; } - (void)setEndKey:(NSString *)_s { id o = self->endKey; self->endKey = [_s copy]; [o release]; } - (NSString *)endKey { return self->endKey; } - (void)setUnknownNamespaceKey:(NSString *)_s { id o = self->unknownNamespaceKey; self->unknownNamespaceKey = [_s copy]; [o release]; } - (NSString *)unknownNamespaceKey { return self->unknownNamespaceKey; } - (NSArray *)tagStack { return self->tagStack; } - (unsigned)depth { return [self->tagStack count]; } - (void)ignoreChildren { if (self->ignoreLevel == -1) self->ignoreLevel = [self depth]; } - (BOOL)doesIgnoreChildren { if (self->ignoreLevel == -1) return NO; return (int)[self depth] >= self->ignoreLevel ? YES : NO; } /* standard Sax callbacks */ - (void)endDocument { [super endDocument]; [selName setString:@""]; } static inline void _selAdd(SaxMethodCallHandler *self, NSString *_s) { [self->selName appendString:_s]; } static inline void _selAddEscaped(SaxMethodCallHandler *self, NSString *_s) { register unsigned i, len; unichar *buf16; BOOL needsEscape = NO; unichar *buf; unsigned j; NSString *s; if ((len = [_s length]) == 0) return; buf16 = calloc(len + 2, sizeof(unichar)); for (i = 0; i < len; i++) { // TODO: does isalnum work OK for Unicode? (at least it takes an int) if (!(isalnum(buf16[i]) || (buf16[i] == '_'))) { needsEscape = YES; break; } } if (!needsEscape) { /* no escaping required, stop processing */ if (buf16 != NULL) free(buf16); [self->selName appendString:_s]; return; } /* strip out all non-ASCII, non-alnum or _ chars */ buf = calloc(len + 2, sizeof(unichar)); for (i = 0, j = 0; i < len; i++) { register unichar c = buf16[i]; // TODO: isalnum() vs Unicode if (isalnum((int)c) || (c == '_')) { if (i > 0) { if (buf16[i - 1] == '-') c = toupper(c); } buf[j] = c; j++; } /* else: do nothing, leave out non-ASCII char */ } buf[j] = '\0'; if (buf16 != NULL) free(buf16); s = [[NSString alloc] initWithCharacters:buf length:j]; if (buf != NULL) free(buf); [self->selName appendString:s]; [s release]; } - (void)startElement:(NSString *)_localName namespace:(NSString *)_ns rawName:(NSString *)_rawName attributes:(id)_attrs { NSString *fqName; NSString *nskey; SEL sel; fqName = [[NSString alloc] initWithFormat:@"{%@}%@", _ns, _localName]; [self->tagStack addObject:fqName]; [fqName release]; // still retained by tagStack if ((int)[self depth] > self->ignoreLevel) return; if ((nskey = [self->namespaceToKey objectForKey:_ns]) == nil) { /* unknown namespace */ if (debugOn) NSLog(@"unknown namespace key %@ (tag=%@)", _ns, _rawName); [self->selName setString:@""]; _selAdd(self, self->startKey); } else if ((sel = NSMapGet(self->fqNameToStartSel, fqName))) { /* cached a selector .. */ [self->delegate performSelector:sel withObject:_attrs]; goto found; } else { [self->selName setString:self->startKey]; _selAdd(self, nskey); _selAddEscaped(self, _localName); _selAdd(self, @":"); sel = NSSelectorFromString(self->selName); if ([self->delegate respondsToSelector:sel]) { /* ok, found correct selector */ [self->delegate performSelector:sel withObject:_attrs]; NSMapInsert(self->fqNameToStartSel, fqName, sel); goto found; } /* check for 'start_nskey_unknownTag:attributes:' */ [self->selName setString:self->startKey]; _selAdd(self, nskey); _selAdd(self, @"unknownTag:attributes:"); sel = NSSelectorFromString(self->selName); if ([self->delegate respondsToSelector:sel]) { /* ok, found selector */ [self->delegate performSelector:sel withObject:_localName withObject:_attrs]; goto found; } /* check for 'start_tag:namespace:attributes:' */ [self->selName setString:self->startKey]; _selAdd(self, @"tag:namespace:attributes:"); sel = NSSelectorFromString(self->selName); if ([self->delegate respondsToSelector:sel]) { /* ok, found selector */ [self->delegate performSelector:sel withObject:_localName withObject:_ns withObject:_attrs]; goto found; } /* ignore tag */ } if (debugOn) { NSLog(@"%s: ignore tag: %@, sel %@", __PRETTY_FUNCTION__, fqName, self->selName); } return; found: ; // required for MacOSX gcc } - (void)endElement:(NSString *)_localName namespace:(NSString *)_ns rawName:(NSString *)_rawName { NSString *nskey; SEL sel; if ((int)[self depth] > self->ignoreLevel) { [self->tagStack removeLastObject]; return; } self->ignoreLevel = -1; if ((nskey = [self->namespaceToKey objectForKey:_ns]) == nil) { /* unknown namespace */ if (debugOn) NSLog(@"unknown namespace key %@ (tag=%@)", _ns, _rawName); [selName setString:self->endKey]; } else { [selName setString:self->endKey]; _selAdd(self, nskey); _selAdd(self, _localName); sel = NSSelectorFromString(self->selName); if ([self->delegate respondsToSelector:sel]) { /* ok, found correct selector */ [self->delegate performSelector:sel]; goto found; } /* check for 'end_nskey_unknownTag:' */ [self->selName setString:self->endKey]; _selAdd(self, nskey); _selAdd(self, @"unknownTag:"); sel = NSSelectorFromString(self->selName); if ([self->delegate respondsToSelector:sel]) { /* ok, found selector */ [self->delegate performSelector:sel withObject:_localName]; goto found; } /* check for 'end_tag:namespace:attributes:' */ [self->selName setString:self->endKey]; _selAdd(self, @"tag:namespace:"); sel = NSSelectorFromString(self->selName); if ([self->delegate respondsToSelector:sel]) { /* ok, found selector */ [self->delegate performSelector:sel withObject:_localName withObject:_ns]; goto found; } /* didn't find end tag .. */ } [self->tagStack removeLastObject]; return; found: [self->tagStack removeLastObject]; } @end /* SaxMethodCallHandler */ SOPE/sope-xml/SaxObjC/SaxNamespaceSupport.m0000644000000000000000000000300515004363604017501 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SaxNamespaceSupport.h" #include "common.h" @implementation SaxNamespaceSupport - (void)pushContext { [self doesNotRecognizeSelector:_cmd]; } - (void)popContext { [self doesNotRecognizeSelector:_cmd]; } - (BOOL)declarePrefix:(NSString *)_prefix uri:(NSString *)_uri { [self doesNotRecognizeSelector:_cmd]; return NO; } - (NSEnumerator *)prefixEnumerator { [self doesNotRecognizeSelector:_cmd]; return nil; } - (NSString *)getUriForPrefix:(NSString *)_prefix { [self doesNotRecognizeSelector:_cmd]; return nil; } - (void)reset { } - (NSArray *)processName:(NSString *)_rawName parts:(NSArray *)_parts isAttribute:(BOOL)_isAttribute { [self doesNotRecognizeSelector:_cmd]; return nil; } @end /* SaxNamespaceSupport */ SOPE/sope-xml/SaxObjC/SaxXMLReader.h0000644000000000000000000000543315004363604015775 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxXMLReader_H__ #define __SaxXMLReader_H__ #import #include #include #include #include /* new in SAX 2.0beta, replaces SaxParser Interface for reading an XML document using callbacks. This is a common interface that can be shared by many XML parsers. This interface allows an application to set and query features and properties in the parser, to register event handlers for document processing, and to initiate a document parse. This interface replaces the (now deprecated) SAX 1.0 Parser interface; it currently extends Parser to aid in the transition to SAX2, but it will likely not do so in any future versions of SAX. The Reader interface contains two important enhancements over the old Parser interface: 1. it adds a standard way to query and set features and properties; and 2. it adds Namespace support, which is required for many higher-level XML standards. There are adapters available to convert a SAX1 Parser to a SAX2 XMLReader and vice-versa. */ @protocol SaxXMLReader /* features & properties */ - (void)setFeature:(NSString *)_name to:(BOOL)_value; - (BOOL)feature:(NSString *)_name; - (void)setProperty:(NSString *)_name to:(id)_value; - (id)property:(NSString *)_name; /* handlers */ - (void)setContentHandler:(id)_handler; - (void)setDTDHandler:(id)_handler; - (void)setErrorHandler:(id)_handler; - (void)setEntityResolver:(id)_handler; - (id)contentHandler; - (id)dtdHandler; - (id)errorHandler; - (id)entityResolver; /* parsing */ - (void)parseFromSource:(id)_source; - (void)parseFromSource:(id)_source systemId:(NSString *)_sysId; - (void)parseFromSystemId:(NSString *)_sysId; @end #endif /* __SaxXMLReader_H__ */ SOPE/sope-xml/SaxObjC/SaxDeclHandler.h0000644000000000000000000000700615004363604016355 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxDeclHandler_H__ #define __SaxDeclHandler_H__ @class NSString; /* new in SAX 2.0beta In Java this class is in the ext-package, that is, implementation is optional. SAX2 extension handler for DTD declaration events. This is an optional extension handler for SAX2 to provide information about DTD declarations in an XML document. XML readers are not required to support this handler. Note that data-related DTD declarations (unparsed entities and notations) are already reported through the DTDHandler interface. If you are using the declaration handler together with a lexical handler, all of the events will occur between the startDTD and the endDTD events. To set the DeclHandler for an XML reader, use the setProperty method with the propertyId "http://xml.org/sax/handlers/DeclHandler". If the reader does not support declaration events, it will throw a SAXNotRecognizedException or a SAXNotSupportedException when you attempt to register the handler. */ @protocol SaxDeclHandler /* Report an attribute type declaration. Only the effective (first) declaration for an attribute will be reported. The type will be one of the strings "CDATA", "ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES", or "NOTATION", or a parenthesized token group with the separator "|" and all whitespace removed. valueDefault - A string representing the attribute default ("#IMPLIED", "#REQUIRED", or "#FIXED") or nil if none of these applies */ - (void)attributeDeclaration:(NSString *)_attributeName elementName:(NSString *)_elementName type:(NSString *)_type defaultType:(NSString *)_defType defaultValue:(NSString *)_defValue; /* Report an attribute type declaration. Only the effective (first) declaration for an attribute will be reported. The type will be one of the strings "CDATA", "ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES", or "NOTATION", or a parenthesized token group with the separator "|" and all whitespace removed. If it is a parameter entity, the name will begin with '%'. */ - (void)elementDeclaration:(NSString *)_name contentModel:(NSString *)_model; /* Report a parsed external entity declaration. Only the effective (first) declaration for each entity will be reported. If it is a parameter entity, the name will begin with '%'. */ - (void)externalEntityDeclaration:(NSString *)_name publicId:(NSString *)_pub systemId:(NSString *)_sys; /* Report an internal entity declaration. Only the effective (first) declaration for each entity will be reported. If it is a parameter entity, the name will begin with '%'. */ - (void)internalEntityDeclaration:(NSString *)_name value:(NSString *)_value; @end #endif /* __SaxDeclHandler_H__ */ SOPE/sope-xml/SaxObjC/SaxException.h0000644000000000000000000000216515004363604016147 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxException_H__ #define __SaxException_H__ #import @interface SaxException : NSException @end @interface SaxParseException : SaxException @end /* new in SAX 2.0beta */ @interface SaxNotSupportedException : SaxException @end @interface SaxNotRecognizedException : SaxException @end #endif /* __SaxException_H__ */ SOPE/sope-xml/SaxObjC/SaxXMLFilter.m0000644000000000000000000001270315004363604016023 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SaxXMLFilter.h" #include "common.h" @implementation SaxXMLFilter - (id)initWithParent:(id)_parent { if ((self = [self init])) { [self setParent:_parent]; } return self; } - (void)dealloc { [self->parent release]; [super dealloc]; } - (void)setParent:(id)_parent { if (self->parent == _parent) return; [self->parent setContentHandler:nil]; [self->parent setDTDHandler:nil]; [self->parent setErrorHandler:nil]; [self->parent setEntityResolver:nil]; ASSIGN(self->parent, _parent); [self->parent setContentHandler:self]; [self->parent setDTDHandler:self]; [self->parent setErrorHandler:self]; [self->parent setEntityResolver:self]; } - (id)parent { return self->parent; } /* features & properties */ - (void)setFeature:(NSString *)_name to:(BOOL)_value { [self->parent setFeature:_name to:_value]; } - (BOOL)feature:(NSString *)_name { return [self->parent feature:_name]; } - (void)setProperty:(NSString *)_name to:(id)_value { [self->parent setProperty:_name to:_value]; } - (id)property:(NSString *)_name { return [self->parent property:_name]; } /* handlers */ - (void)setDTDHandler:(id)_handler { ASSIGN(self->dtdHandler, _handler); } - (id)dtdHandler { return self->dtdHandler; } - (void)setErrorHandler:(id)_handler { ASSIGN(self->errorHandler, _handler); } - (id)errorHandler { return self->errorHandler; } - (void)setEntityResolver:(id)_handler { ASSIGN(self->entityResolver, _handler); } - (id)entityResolver { return self->entityResolver; } - (void)setContentHandler:(id)_handler { ASSIGN(self->contentHandler, _handler); } - (id)contentHandler { return self->contentHandler; } /* parsing */ - (void)parseFromSource:(id)_source { [self->parent parseFromSource:_source]; } - (void)parseFromSystemId:(NSString *)_sysId { [self->parent parseFromSystemId:_sysId]; } - (void)parseFromSource:(id)_source systemId:(NSString *)_sysId { [self->parent parseFromSource:_source systemId:_sysId]; } /* SaxEntityResolver */ - (id)resolveEntityWithPublicId:(NSString *)_pubId systemId:(NSString *)_sysId { return [self->entityResolver resolveEntityWithPublicId:_pubId systemId:_sysId]; } /* SaxContentHandler */ - (void)startDocument { [self->contentHandler startDocument]; } - (void)endDocument { [self->contentHandler endDocument]; } - (void)startPrefixMapping:(NSString *)_prefix uri:(NSString *)_uri { [self->contentHandler startPrefixMapping:_prefix uri:_uri]; } - (void)endPrefixMapping:(NSString *)_prefix { [self->contentHandler endPrefixMapping:_prefix]; } - (void)startElement:(NSString *)_localName namespace:(NSString *)_ns rawName:(NSString *)_rawName attributes:(id)_attributes { [self->contentHandler startElement:_localName namespace:_ns rawName:_rawName attributes:_attributes]; } - (void)endElement:(NSString *)_localName namespace:(NSString *)_ns rawName:(NSString *)_rawName { [self->contentHandler endElement:_localName namespace:_ns rawName:_rawName]; } - (void)characters:(unichar *)_chars length:(NSUInteger)_len { [self->contentHandler characters:_chars length:_len]; } - (void)ignorableWhitespace:(unichar *)_chars length:(NSUInteger)_len { [self->contentHandler ignorableWhitespace:_chars length:_len]; } - (void)processingInstruction:(NSString *)_pi data:(NSString *)_data { [self->contentHandler processingInstruction:_pi data:_data]; } - (void)setDocumentLocator:(id)_locator { [self->contentHandler setDocumentLocator:_locator]; } - (void)skippedEntity:(NSString *)_entityName { [self->contentHandler skippedEntity:_entityName]; } /* error-handler */ - (void)warning:(SaxParseException *)_exception { [self->errorHandler warning:_exception]; } - (void)error:(SaxParseException *)_exception { [self->errorHandler error:_exception]; } - (void)fatalError:(SaxParseException *)_exception { [self->errorHandler fatalError:_exception]; } /* dtd-handler */ - (void)notationDeclaration:(NSString *)_name publicId:(NSString *)_pubId systemId:(NSString *)_sysId { [self->dtdHandler notationDeclaration:_name publicId:_pubId systemId:_sysId]; } - (void)unparsedEntityDeclaration:(NSString *)_name publicId:(NSString *)_pubId systemId:(NSString *)_sysId notationName:(NSString *)_notName { [self->dtdHandler unparsedEntityDeclaration:_name publicId:_pubId systemId:_sysId notationName:_notName]; } @end /* SaxXMLFilter */ SOPE/sope-xml/SaxObjC/COPYRIGHT0000644000000000000000000000010615004363604014650 0ustar rootrootCopyright (C) 2000-2005 SKYRIX Software AG Contact: info@skyrix.com SOPE/sope-xml/SaxObjC/SaxNamespaceSupport.h0000644000000000000000000000754415004363604017510 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxNamespaceSupport_H__ #define __SaxNamespaceSupport_H__ #import @class NSString, NSEnumerator, NSArray; /* New in SAX2, defined in helpers/NamespaceSupport Encapsulate Namespace logic for use by SAX drivers. This class encapsulates the logic of Namespace processing: it tracks the declarations currently in force for each context and automatically processing raw XML 1.0 names into their Namespace parts. Namespace support objects are reusable, but the reset method must be invoked between each session. Here is a simple session: String parts[] = new String[3]; SaxNamespaceSupport support; support = [[SaxNamespaceSupport alloc] init]; [support pushContext]; [support declarePrefix:@"" uri:@"http://www.w3.org/1999/xhtml"]; [support declarePrefix:@"dc" uri:@"http://www.purl.org/dc#"]; String parts[] = support.processName("p", parts, false); System.out.println("Namespace URI: " + parts[0]); System.out.println("Local name: " + parts[1]); System.out.println("Raw name: " + parts[2]); String parts[] = support.processName("dc:title", parts, false); System.out.println("Namespace URI: " + parts[0]); System.out.println("Local name: " + parts[1]); System.out.println("Raw name: " + parts[2]); [support popContext]; Note that this class is optimized for the use case where most elements do not contain Namespace declarations: if the same prefix/URI mapping is repeated for each context (for example), this class will be somewhat less efficient. */ extern NSString *SaxXMLNS; @interface SaxNamespaceSupport : NSObject { @private } /* start a new ns context */ - (void)pushContext; /* revert to previous ns context */ - (void)popContext; /* Declare a Namespace prefix. */ - (BOOL)declarePrefix:(NSString *)_prefix uri:(NSString *)_uri; /* Return an enumeration of all prefixes declared in this context. */ - (NSEnumerator *)prefixEnumerator; /* Look up a prefix and get the currently-mapped Namespace URI. */ - (NSString *)getUriForPrefix:(NSString *)_prefix; /* Reset this Namespace support object for reuse. */ - (void)reset; /* Process a raw XML 1.0 name. This method processes a raw XML 1.0 name in the current context by removing the prefix and looking it up among the prefixes currently declared. The return value will be the array supplied by the caller, filled in as follows: parts[0] The Namespace URI, or an empty string if none is in use. parts[1] The local name (without prefix). parts[2] The original raw name. All of the strings in the array will be internalized. If the raw name has a prefix that has not been declared, then the return value will be null. Note that attribute names are processed differently than element names: an unprefixed element name will received the default Namespace (if any), while an unprefixed element name will not. */ - (NSArray *)processName:(NSString *)_rawName parts:(NSArray *)_parts isAttribute:(BOOL)_isAttribute; @end #endif /* __SaxNamespaceSupport_H__ */ SOPE/sope-xml/SaxObjC/SaxXMLReaderFactory.m0000644000000000000000000003210015004363604017321 0ustar rootroot/* Copyright (C) 2000-2006 SKYRIX Software AG Copyright (C) 2006 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SaxXMLReaderFactory.h" #include "common.h" #if GNUSTEP_BASE_LIBRARY @implementation NSBundle(Copying) - (id)copyWithZone:(NSZone *)_zone { return [self retain]; } @end #endif @implementation SaxXMLReaderFactory static BOOL coreOnMissingParser = NO; static BOOL debugOn = NO; static NSArray *searchPathes = nil; static NSNull *null = nil; static id factory = nil; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; coreOnMissingParser = [ud boolForKey:@"SaxCoreOnMissingParser"]; debugOn = [ud boolForKey:@"SaxDebugReaderFactory"]; } + (id)standardXMLReaderFactory { if (factory == nil) factory = [[self alloc] init]; return factory; } - (void)dealloc { [self->nameToBundle release]; [self->mimeTypeToName release]; [super dealloc]; } /* operations */ - (void)flush { [self->nameToBundle release]; self->nameToBundle = nil; [self->mimeTypeToName release]; self->mimeTypeToName = nil; } /* search path construction */ - (BOOL)searchFrameworkBundle { #if COMPILE_AS_FRAMEWORK return YES; #else return NO; #endif } - (NSString *)libraryDriversSubDir { return [NSString stringWithFormat:@"SaxDrivers-%i.%i", SOPE_MAJOR_VERSION, SOPE_MINOR_VERSION]; } - (void)addSearchPathesForCocoa:(NSMutableArray *)ma { /* for Cocoa */ id tmp; tmp = NSSearchPathForDirectoriesInDomains(NSAllLibrariesDirectory, NSAllDomainsMask, YES); if ([tmp count] > 0) { NSEnumerator *e; NSString *subdir; subdir = [self libraryDriversSubDir]; e = [tmp objectEnumerator]; while ((tmp = [e nextObject]) != nil) { tmp = [tmp stringByAppendingPathComponent:subdir]; if (![ma containsObject:tmp]) [ma addObject:tmp]; } } if ([self searchFrameworkBundle]) { NSBundle *fwBundle; /* no need to add 4.5 here, right? */ fwBundle = [NSBundle bundleForClass:[self class]]; tmp = [[fwBundle resourcePath] stringByAppendingPathComponent: @"SaxDrivers"]; [ma addObject:tmp]; } } - (void)addSearchPathesForStdLibPathes:(NSMutableArray *)ma { /* for gstep-base */ NSEnumerator *e; NSString *subdir; id tmp; #if !COCOA_Foundation_LIBRARY && !NeXT_Foundation_LIBRARY tmp = NSStandardLibraryPaths(); #else tmp = nil; /* not available on Cocoa? */ #endif if ([tmp count] == 0) return; subdir = [self libraryDriversSubDir]; e = [tmp objectEnumerator]; while ((tmp = [e nextObject]) != nil) { tmp = [tmp stringByAppendingPathComponent:subdir]; if ([ma containsObject:tmp]) continue; [ma addObject:tmp]; } } - (void)addSearchPathesForGNUstepEnv:(NSMutableArray *)ma { /* for libFoundation */ #if GNUSTEP_BASE_LIBRARY NSEnumerator *libraryPaths; NSString *directory, *suffix; suffix = [self libraryDriversSubDir]; libraryPaths = [NSStandardLibraryPaths() objectEnumerator]; while ((directory = [libraryPaths nextObject])) [ma addObject: [directory stringByAppendingPathComponent: suffix]]; #else NSString *subdir; NSEnumerator *e; NSDictionary *env; id tmp; env = [[NSProcessInfo processInfo] environment]; if ((tmp = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"]) == nil) tmp = [env objectForKey:@"GNUSTEP_PATHLIST"]; tmp = [tmp componentsSeparatedByString:@":"]; if ([tmp count] == 0) return; subdir = [@"Library/" stringByAppendingString:[self libraryDriversSubDir]]; e = [tmp objectEnumerator]; while ((tmp = [e nextObject]) != nil) { tmp = [tmp stringByAppendingPathComponent:subdir]; if ([ma containsObject:tmp]) continue; [ma addObject:tmp]; } #endif } - (NSArray *)saxReaderSearchPathes { NSMutableArray *ma; id tmp; if (searchPathes != nil) return searchPathes; ma = [NSMutableArray arrayWithCapacity:8]; #if COCOA_Foundation_LIBRARY /* Note: do not use NeXT_Foundation_LIBRARY, this is only for Xcode! */ [self addSearchPathesForCocoa:ma]; #elif GNUSTEP_BASE_LIBRARY [self addSearchPathesForStdLibPathes:ma]; #else [self addSearchPathesForGNUstepEnv:ma]; #endif /* FHS fallback */ tmp = [[NSString alloc] initWithFormat: #ifdef CGS_LIBDIR_NAME [CGS_LIBDIR_NAME stringByAppendingString:@"/sope-%i.%i/saxdrivers/"], #else @"lib/sope-%i.%i/saxdrivers/", #endif SOPE_MAJOR_VERSION, SOPE_MINOR_VERSION]; #ifdef FHS_INSTALL_ROOT [ma addObject:[FHS_INSTALL_ROOT stringByAppendingPathComponent:tmp]]; #endif // TODO: should we always add those? or maybe derive from PATH or // LD_LIBRARY_PATH? [ma addObject:[@"/usr/local/" stringByAppendingString:tmp]]; [ma addObject:[@"/usr/" stringByAppendingString:tmp]]; [tmp release]; tmp = nil; searchPathes = [ma copy]; if ([searchPathes count] == 0) NSLog(@"%s: no search pathes were found!", __PRETTY_FUNCTION__); return searchPathes; } /* loading */ - (void)_loadBundlePath:(NSString *)_bundlePath infoDictionary:(NSDictionary *)_info nameMap:(NSMutableDictionary *)_nameMap typeMap:(NSMutableDictionary *)_typeMap { NSArray *drivers; NSEnumerator *e; NSDictionary *driverInfo; NSBundle *bundle; _info = [_info objectForKey:@"provides"]; if ((drivers = [_info objectForKey:@"SAXDrivers"]) == nil) { NSLog(@"%s: .sax bundle '%@' does not provide any SAX drivers ...", __PRETTY_FUNCTION__, _bundlePath); return; } if ((bundle = [NSBundle bundleWithPath:_bundlePath]) == nil) { NSLog(@"%s: could not create bundle from path '%@'", __PRETTY_FUNCTION__, _bundlePath); return; } /* found a driver with valid info dict, process it ... */ e = [drivers objectEnumerator]; while ((driverInfo = [e nextObject]) != nil) { NSString *name, *tname; NSEnumerator *te; name = [driverInfo objectForKey:@"name"]; if ([name length] == 0) { NSLog(@"%s: missing name in sax driver section of bundle %@ ...", __PRETTY_FUNCTION__, _bundlePath); continue; } /* check if name is already registered */ if ([_nameMap objectForKey:name]) { if (debugOn) NSLog(@"%s: already have sax driver named '%@' ...", __PRETTY_FUNCTION__, name); continue; } /* register bundle for name */ [_nameMap setObject:bundle forKey:name]; /* register MIME-types */ te = [[driverInfo objectForKey:@"sourceTypes"] objectEnumerator]; while ((tname = [te nextObject])) { NSString *tmp; if ((tmp = [_typeMap objectForKey:tname])) { NSLog(@"WARNING(%s): multiple parsers available for MIME type '%@', " @"using '%@' as default for type %@.", __PRETTY_FUNCTION__, tname, tmp, tname); continue; } [_typeMap setObject:name forKey:tname]; } } } - (void)_loadLibraryPath:(NSString *)_libraryPath nameMap:(NSMutableDictionary *)_nameMap typeMap:(NSMutableDictionary *)_typeMap { NSFileManager *fm = [NSFileManager defaultManager]; NSEnumerator *e; NSString *p; e = [[fm directoryContentsAtPath:_libraryPath] objectEnumerator]; while ((p = [e nextObject]) != nil) { NSDictionary *info; NSString *infoPath; BOOL isDir; if (![p hasSuffix:@".sax"]) continue; p = [_libraryPath stringByAppendingPathComponent:p]; if (![fm fileExistsAtPath:p isDirectory:&isDir]) continue; if (!isDir) { /* info file is a directory ??? */ NSLog(@"%s: .sax is not a dir: '%@' ???", __PRETTY_FUNCTION__, p); continue; } infoPath = [p stringByAppendingPathComponent:@"bundle-info.plist"]; if (![fm fileExistsAtPath:infoPath]) { NSBundle *b; b = [NSBundle bundleWithPath:p]; infoPath = [b pathForResource:@"bundle-info" ofType:@"plist"]; if (![fm fileExistsAtPath:infoPath]) { NSLog(@"%s: did not find bundle-info dictionary in driver: '%@'", __PRETTY_FUNCTION__, infoPath); continue; } } if ((info = [NSDictionary dictionaryWithContentsOfFile:infoPath]) == nil) { NSLog(@"%s: could not parse bundle-info dictionary: '%@'", __PRETTY_FUNCTION__, infoPath); continue; } [self _loadBundlePath:p infoDictionary:info nameMap:_nameMap typeMap:_typeMap]; } } - (void)_loadAvailableBundles { NSAutoreleasePool *pool; /* setup globals */ if (null == nil) null = [[NSNull null] retain]; #if DEBUG NSAssert(self->nameToBundle == nil, @"already set up !"); NSAssert(self->mimeTypeToName == nil, @"partially set up !"); #else if (self->nameToBundle != nil) return; #endif pool = [[NSAutoreleasePool alloc] init]; { /* lookup bundle in Libary/SaxDrivers pathes */ NSEnumerator *pathes; NSString *path; NSMutableDictionary *nameMap, *typeMap; nameMap = [NSMutableDictionary dictionaryWithCapacity:16]; typeMap = [NSMutableDictionary dictionaryWithCapacity:16]; pathes = [[self saxReaderSearchPathes] objectEnumerator]; while ((path = [pathes nextObject])) [self _loadLibraryPath:path nameMap:nameMap typeMap:typeMap]; self->nameToBundle = [nameMap copy]; self->mimeTypeToName = [typeMap copy]; #if DEBUG if ([self->nameToBundle count] == 0) { NSLog(@"%s: no XML parser could be found in pathes: %@", __PRETTY_FUNCTION__, [self saxReaderSearchPathes]); } else if ([self->mimeTypeToName count] == 0) { NSLog(@"%s: no XML parser declared a MIME type ...",__PRETTY_FUNCTION__); } #endif } [pool release]; } - (id)createXMLReader { NSString *defReader; id reader; if (debugOn) NSLog(@"%s: lookup default XML reader ...",__PRETTY_FUNCTION__); defReader = [[NSUserDefaults standardUserDefaults] stringForKey:@"XMLReader"]; if (debugOn) NSLog(@"%s: '%@' default reader",__PRETTY_FUNCTION__, defReader); if (defReader) { if ((reader = [self createXMLReaderWithName:defReader])) return reader; NSLog(@"%s: could not create default XMLReader '%@' !", __PRETTY_FUNCTION__, defReader); } return [self createXMLReaderForMimeType:@"text/xml"]; } - (id)createXMLReaderWithName:(NSString *)_name { NSBundle *bundle; Class readerClass; if (debugOn) NSLog(@"%s: lookup XML reader with name: '%@'",__PRETTY_FUNCTION__,_name); if ([_name length] == 0) return [self createXMLReader]; if (self->nameToBundle == nil) [self _loadAvailableBundles]; if ((bundle = [self->nameToBundle objectForKey:_name]) == nil) return nil; /* load bundle executable code */ if (![bundle load]) { NSLog(@"%s: could not load SaxDriver bundle %@ !", __PRETTY_FUNCTION__, bundle); return nil; } NSAssert(bundle, @"should have a loaded bundle at this stage ..."); /* lookup class */ if ((readerClass = NSClassFromString(_name)) == Nil) { NSLog(@"WARNING(%s): could not find SAX reader class %@ (SAX bundle=%@)", __PRETTY_FUNCTION__, _name, bundle); return nil; } /* create instance */ return [[[readerClass alloc] init] autorelease]; } - (id)createXMLReaderForMimeType:(NSString *)_mtype { id reader; NSString *name; if (self->mimeTypeToName == nil) [self _loadAvailableBundles]; if (debugOn) NSLog(@"%s: lookup XML reader for type: '%@'",__PRETTY_FUNCTION__, _mtype); if ([_mtype respondsToSelector:@selector(stringValue)]) _mtype = [(id)_mtype stringValue]; if ([_mtype length] == 0) _mtype = @"text/xml"; if ((name = [self->mimeTypeToName objectForKey:_mtype]) == nil) { if (debugOn) { NSLog(@"%s: did not find SAX parser for MIME type %@ map: \n%@", __PRETTY_FUNCTION__, _mtype, self->mimeTypeToName); NSLog(@"%s: parsers: %@", __PRETTY_FUNCTION__, [self->nameToBundle allKeys]); } if (coreOnMissingParser) { NSLog(@"%s: aborting, because 'SaxCoreOnMissingParser' " @"default is enabled!", __PRETTY_FUNCTION__); abort(); } return nil; } if (debugOn) NSLog(@"%s: found XML reader named: '%@'", __PRETTY_FUNCTION__, name); reader = [self createXMLReaderWithName:name]; if (debugOn) NSLog(@"%s: created XML reader: %@", __PRETTY_FUNCTION__, reader); return reader; } - (NSArray *)availableXMLReaders { return [self->nameToBundle allKeys]; } @end /* SaxXMLReaderFactory */ SOPE/sope-xml/SaxObjC/libSAXObjC.def0000644000000000000000000000071215004363604015720 0ustar rootrootEXPORTS __objc_class_name_SaxAttributeList; __objc_class_name_SaxAttributes; __objc_class_name_SaxDefaultHandler; __objc_class_name_SaxException; __objc_class_name_SaxHandlerBase; __objc_class_name_SaxLocator; __objc_class_name_SaxNamespaceSupport; __objc_class_name_SaxNotRecognizedException; __objc_class_name_SaxNotSupportedException; __objc_class_name_SaxParseException; __objc_class_name_SaxXMLFilter; __objc_class_name_SaxXMLReaderFactory; SOPE/sope-xml/SaxObjC/SaxLocator.m0000644000000000000000000000367315004363604015626 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SaxLocator.h" #include "common.h" @implementation SaxLocator - (id)init { return self; } - (id)initWithLocator:(id)_locator { if ((self = [self init])) { self->column = [_locator columnNumber]; self->line = [_locator lineNumber]; self->pubId = [[_locator publicId] copy]; self->sysId = [[_locator systemId] copy]; } return self; } - (void)dealloc { [self->pubId release]; [self->sysId release]; [super dealloc]; } /* accessors */ - (void)setColumnNumber:(NSInteger)_col { self->column = _col; } - (NSInteger)columnNumber { return self->column; } - (void)setLineNumber:(NSInteger)_line { self->line = _line; } - (NSInteger)lineNumber { return self->line; } - (void)setPublicId:(NSString *)_pubId { id o = self->pubId; self->pubId = [_pubId copy]; [o release]; } - (NSString *)publicId { return self->pubId; } - (void)setSystemId:(NSString *)_sysId { id o = self->sysId; self->sysId = [_sysId copy]; [o release]; } - (NSString *)systemId { return self->sysId; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { return [[[self class] allocWithZone:_zone] initWithLocator:self]; } @end /* SaxLocator */ SOPE/sope-xml/SaxObjC/SaxDefaultHandler.h0000644000000000000000000000224515004363604017072 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxDefaultHandler_H__ #define __SaxDefaultHandler_H__ #import #include #include #include #include @interface SaxDefaultHandler : NSObject < SaxEntityResolver, SaxDTDHandler, SaxContentHandler, SaxErrorHandler > @end #endif /* __SaxDefaultHandler_H__ */ SOPE/sope-xml/SaxObjC/shared_debug_obj/0000755000000000000000000000000015004363604016626 5ustar rootrootSOPE/sope-xml/SaxObjC/shared_debug_obj/SaxObjectDecoder.d0000644000000000000000000002505315004363604022150 0ustar rootrootobj/SaxObjectDecoder.o: SaxObjectDecoder.m SaxObjectDecoder.h \ ../SaxObjC/SaxDefaultHandler.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h ../SaxObjC/SaxEntityResolver.h \ ../SaxObjC/SaxDTDHandler.h ../SaxObjC/SaxContentHandler.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h ../SaxObjC/SaxAttributes.h \ ../SaxObjC/SaxAttributeList.h ../SaxObjC/SaxLocator.h \ ../SaxObjC/SaxErrorHandler.h SaxObjectModel.h common.h \ /usr/include/GNUstep/Foundation/Foundation.h \ /usr/include/GNUstep/Foundation/FoundationErrors.h \ /usr/include/GNUstep/Foundation/NSDebug.h \ /usr/include/GNUstep/Foundation/NSProcessInfo.h \ /usr/include/GNUstep/Foundation/NSAffineTransform.h \ /usr/include/GNUstep/Foundation/NSGeometry.h \ /usr/include/GNUstep/Foundation/NSArchiver.h \ /usr/include/GNUstep/Foundation/NSCoder.h \ /usr/include/GNUstep/Foundation/NSArray.h \ /usr/include/GNUstep/Foundation/NSAttributedString.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/GNUstep/Foundation/NSAutoreleasePool.h \ /usr/include/GNUstep/Foundation/NSBundle.h \ /usr/include/GNUstep/Foundation/NSByteOrder.h \ /usr/include/GNUstep/Foundation/NSCalendarDate.h \ /usr/include/GNUstep/Foundation/NSCharacterSet.h \ /usr/include/GNUstep/Foundation/NSClassDescription.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/Foundation/NSComparisonPredicate.h \ /usr/include/GNUstep/Foundation/NSExpression.h \ /usr/include/GNUstep/Foundation/NSPredicate.h \ /usr/include/GNUstep/Foundation/NSCompoundPredicate.h \ /usr/include/GNUstep/Foundation/NSConnection.h \ /usr/include/GNUstep/Foundation/NSTimer.h \ /usr/include/GNUstep/Foundation/NSRunLoop.h \ /usr/include/GNUstep/Foundation/NSMapTable.h \ /usr/include/GNUstep/Foundation/NSData.h \ /usr/include/GNUstep/Foundation/NSSerialization.h \ /usr/include/GNUstep/Foundation/NSDateFormatter.h \ /usr/include/GNUstep/Foundation/NSFormatter.h \ /usr/include/GNUstep/Foundation/NSDecimalNumber.h \ /usr/include/GNUstep/Foundation/NSDecimal.h \ /usr/include/GNUstep/Foundation/NSValue.h \ /usr/include/GNUstep/Foundation/NSDistantObject.h \ /usr/include/GNUstep/Foundation/NSProxy.h \ /usr/include/GNUstep/Foundation/NSDistributedLock.h \ /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h \ /usr/include/GNUstep/Foundation/NSLock.h \ /usr/include/GNUstep/Foundation/NSNotification.h \ /usr/include/GNUstep/Foundation/NSEnumerator.h \ /usr/include/GNUstep/Foundation/NSError.h \ /usr/include/GNUstep/Foundation/NSFileHandle.h \ /usr/include/GNUstep/Foundation/NSFileManager.h \ /usr/include/GNUstep/Foundation/NSHashTable.h \ /usr/include/GNUstep/Foundation/NSHost.h \ /usr/include/GNUstep/Foundation/NSHTTPCookie.h \ /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h \ /usr/include/GNUstep/Foundation/NSIndexPath.h \ /usr/include/GNUstep/Foundation/NSIndexSet.h \ /usr/include/GNUstep/Foundation/NSInvocation.h \ /usr/include/GNUstep/Foundation/NSMethodSignature.h \ /usr/include/GNUstep/Foundation/NSKeyedArchiver.h \ /usr/include/GNUstep/Foundation/NSPropertyList.h \ /usr/include/GNUstep/Foundation/NSKeyValueCoding.h \ /usr/include/GNUstep/Foundation/NSNotificationQueue.h \ /usr/include/GNUstep/Foundation/NSNetServices.h \ /usr/include/GNUstep/Foundation/NSNull.h \ /usr/include/GNUstep/Foundation/NSNumberFormatter.h \ /usr/include/GNUstep/Foundation/NSPathUtilities.h \ /usr/include/GNUstep/Foundation/NSPortCoder.h \ /usr/include/GNUstep/Foundation/NSPortMessage.h \ /usr/include/GNUstep/Foundation/NSPort.h \ /usr/include/GNUstep/Foundation/NSPortNameServer.h \ /usr/include/GNUstep/Foundation/NSProtocolChecker.h \ /usr/include/GNUstep/Foundation/NSScanner.h \ /usr/include/GNUstep/Foundation/NSSet.h \ /usr/include/GNUstep/Foundation/NSSortDescriptor.h \ /usr/include/GNUstep/Foundation/NSSpellServer.h \ /usr/include/GNUstep/Foundation/NSStream.h \ /usr/include/GNUstep/Foundation/NSTask.h \ /usr/include/GNUstep/Foundation/NSThread.h \ /usr/include/GNUstep/Foundation/NSTimeZone.h \ /usr/include/GNUstep/Foundation/NSUndoManager.h \ /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h \ /usr/include/GNUstep/Foundation/NSURLCache.h \ /usr/include/GNUstep/Foundation/NSURLConnection.h \ /usr/include/GNUstep/Foundation/NSURLCredential.h \ /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h \ /usr/include/GNUstep/Foundation/NSURLDownload.h \ /usr/include/GNUstep/Foundation/NSURLError.h \ /usr/include/GNUstep/Foundation/NSURL.h \ /usr/include/GNUstep/Foundation/NSURLHandle.h \ /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h \ /usr/include/GNUstep/Foundation/NSURLProtocol.h \ /usr/include/GNUstep/Foundation/NSURLRequest.h \ /usr/include/GNUstep/Foundation/NSURLResponse.h \ /usr/include/GNUstep/Foundation/NSUserDefaults.h \ /usr/include/GNUstep/Foundation/NSValueTransformer.h \ /usr/include/GNUstep/Foundation/NSXMLParser.h SaxObjectDecoder.h: ../SaxObjC/SaxDefaultHandler.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: ../SaxObjC/SaxEntityResolver.h: ../SaxObjC/SaxDTDHandler.h: ../SaxObjC/SaxContentHandler.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: ../SaxObjC/SaxAttributes.h: ../SaxObjC/SaxAttributeList.h: ../SaxObjC/SaxLocator.h: ../SaxObjC/SaxErrorHandler.h: SaxObjectModel.h: common.h: /usr/include/GNUstep/Foundation/Foundation.h: /usr/include/GNUstep/Foundation/FoundationErrors.h: /usr/include/GNUstep/Foundation/NSDebug.h: /usr/include/GNUstep/Foundation/NSProcessInfo.h: /usr/include/GNUstep/Foundation/NSAffineTransform.h: /usr/include/GNUstep/Foundation/NSGeometry.h: /usr/include/GNUstep/Foundation/NSArchiver.h: /usr/include/GNUstep/Foundation/NSCoder.h: /usr/include/GNUstep/Foundation/NSArray.h: /usr/include/GNUstep/Foundation/NSAttributedString.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/GNUstep/Foundation/NSAutoreleasePool.h: /usr/include/GNUstep/Foundation/NSBundle.h: /usr/include/GNUstep/Foundation/NSByteOrder.h: /usr/include/GNUstep/Foundation/NSCalendarDate.h: /usr/include/GNUstep/Foundation/NSCharacterSet.h: /usr/include/GNUstep/Foundation/NSClassDescription.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/Foundation/NSComparisonPredicate.h: /usr/include/GNUstep/Foundation/NSExpression.h: /usr/include/GNUstep/Foundation/NSPredicate.h: /usr/include/GNUstep/Foundation/NSCompoundPredicate.h: /usr/include/GNUstep/Foundation/NSConnection.h: /usr/include/GNUstep/Foundation/NSTimer.h: /usr/include/GNUstep/Foundation/NSRunLoop.h: /usr/include/GNUstep/Foundation/NSMapTable.h: /usr/include/GNUstep/Foundation/NSData.h: /usr/include/GNUstep/Foundation/NSSerialization.h: /usr/include/GNUstep/Foundation/NSDateFormatter.h: /usr/include/GNUstep/Foundation/NSFormatter.h: /usr/include/GNUstep/Foundation/NSDecimalNumber.h: /usr/include/GNUstep/Foundation/NSDecimal.h: /usr/include/GNUstep/Foundation/NSValue.h: /usr/include/GNUstep/Foundation/NSDistantObject.h: /usr/include/GNUstep/Foundation/NSProxy.h: /usr/include/GNUstep/Foundation/NSDistributedLock.h: /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h: /usr/include/GNUstep/Foundation/NSLock.h: /usr/include/GNUstep/Foundation/NSNotification.h: /usr/include/GNUstep/Foundation/NSEnumerator.h: /usr/include/GNUstep/Foundation/NSError.h: /usr/include/GNUstep/Foundation/NSFileHandle.h: /usr/include/GNUstep/Foundation/NSFileManager.h: /usr/include/GNUstep/Foundation/NSHashTable.h: /usr/include/GNUstep/Foundation/NSHost.h: /usr/include/GNUstep/Foundation/NSHTTPCookie.h: /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h: /usr/include/GNUstep/Foundation/NSIndexPath.h: /usr/include/GNUstep/Foundation/NSIndexSet.h: /usr/include/GNUstep/Foundation/NSInvocation.h: /usr/include/GNUstep/Foundation/NSMethodSignature.h: /usr/include/GNUstep/Foundation/NSKeyedArchiver.h: /usr/include/GNUstep/Foundation/NSPropertyList.h: /usr/include/GNUstep/Foundation/NSKeyValueCoding.h: /usr/include/GNUstep/Foundation/NSNotificationQueue.h: /usr/include/GNUstep/Foundation/NSNetServices.h: /usr/include/GNUstep/Foundation/NSNull.h: /usr/include/GNUstep/Foundation/NSNumberFormatter.h: /usr/include/GNUstep/Foundation/NSPathUtilities.h: /usr/include/GNUstep/Foundation/NSPortCoder.h: /usr/include/GNUstep/Foundation/NSPortMessage.h: /usr/include/GNUstep/Foundation/NSPort.h: /usr/include/GNUstep/Foundation/NSPortNameServer.h: /usr/include/GNUstep/Foundation/NSProtocolChecker.h: /usr/include/GNUstep/Foundation/NSScanner.h: /usr/include/GNUstep/Foundation/NSSet.h: /usr/include/GNUstep/Foundation/NSSortDescriptor.h: /usr/include/GNUstep/Foundation/NSSpellServer.h: /usr/include/GNUstep/Foundation/NSStream.h: /usr/include/GNUstep/Foundation/NSTask.h: /usr/include/GNUstep/Foundation/NSThread.h: /usr/include/GNUstep/Foundation/NSTimeZone.h: /usr/include/GNUstep/Foundation/NSUndoManager.h: /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h: /usr/include/GNUstep/Foundation/NSURLCache.h: /usr/include/GNUstep/Foundation/NSURLConnection.h: /usr/include/GNUstep/Foundation/NSURLCredential.h: /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h: /usr/include/GNUstep/Foundation/NSURLDownload.h: /usr/include/GNUstep/Foundation/NSURLError.h: /usr/include/GNUstep/Foundation/NSURL.h: /usr/include/GNUstep/Foundation/NSURLHandle.h: /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h: /usr/include/GNUstep/Foundation/NSURLProtocol.h: /usr/include/GNUstep/Foundation/NSURLRequest.h: /usr/include/GNUstep/Foundation/NSURLResponse.h: /usr/include/GNUstep/Foundation/NSUserDefaults.h: /usr/include/GNUstep/Foundation/NSValueTransformer.h: /usr/include/GNUstep/Foundation/NSXMLParser.h: SOPE/sope-xml/SaxObjC/shared_debug_obj/SaxAttributes.d0000644000000000000000000002421115004363604021575 0ustar rootrootobj/SaxAttributes.o: SaxAttributes.m SaxAttributes.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h ../SaxObjC/SaxAttributeList.h \ ../SaxObjC/SaxAttributes.h common.h \ /usr/include/GNUstep/Foundation/Foundation.h \ /usr/include/GNUstep/Foundation/FoundationErrors.h \ /usr/include/GNUstep/Foundation/NSDebug.h \ /usr/include/GNUstep/Foundation/NSProcessInfo.h \ /usr/include/GNUstep/Foundation/NSAffineTransform.h \ /usr/include/GNUstep/Foundation/NSGeometry.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h \ /usr/include/GNUstep/Foundation/NSArchiver.h \ /usr/include/GNUstep/Foundation/NSCoder.h \ /usr/include/GNUstep/Foundation/NSArray.h \ /usr/include/GNUstep/Foundation/NSAttributedString.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/GNUstep/Foundation/NSAutoreleasePool.h \ /usr/include/GNUstep/Foundation/NSBundle.h \ /usr/include/GNUstep/Foundation/NSByteOrder.h \ /usr/include/GNUstep/Foundation/NSCalendarDate.h \ /usr/include/GNUstep/Foundation/NSCharacterSet.h \ /usr/include/GNUstep/Foundation/NSClassDescription.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/Foundation/NSComparisonPredicate.h \ /usr/include/GNUstep/Foundation/NSExpression.h \ /usr/include/GNUstep/Foundation/NSPredicate.h \ /usr/include/GNUstep/Foundation/NSCompoundPredicate.h \ /usr/include/GNUstep/Foundation/NSConnection.h \ /usr/include/GNUstep/Foundation/NSTimer.h \ /usr/include/GNUstep/Foundation/NSRunLoop.h \ /usr/include/GNUstep/Foundation/NSMapTable.h \ /usr/include/GNUstep/Foundation/NSData.h \ /usr/include/GNUstep/Foundation/NSSerialization.h \ /usr/include/GNUstep/Foundation/NSDateFormatter.h \ /usr/include/GNUstep/Foundation/NSFormatter.h \ /usr/include/GNUstep/Foundation/NSDecimalNumber.h \ /usr/include/GNUstep/Foundation/NSDecimal.h \ /usr/include/GNUstep/Foundation/NSValue.h \ /usr/include/GNUstep/Foundation/NSDistantObject.h \ /usr/include/GNUstep/Foundation/NSProxy.h \ /usr/include/GNUstep/Foundation/NSDistributedLock.h \ /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h \ /usr/include/GNUstep/Foundation/NSLock.h \ /usr/include/GNUstep/Foundation/NSNotification.h \ /usr/include/GNUstep/Foundation/NSEnumerator.h \ /usr/include/GNUstep/Foundation/NSError.h \ /usr/include/GNUstep/Foundation/NSFileHandle.h \ /usr/include/GNUstep/Foundation/NSFileManager.h \ /usr/include/GNUstep/Foundation/NSHashTable.h \ /usr/include/GNUstep/Foundation/NSHost.h \ /usr/include/GNUstep/Foundation/NSHTTPCookie.h \ /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h \ /usr/include/GNUstep/Foundation/NSIndexPath.h \ /usr/include/GNUstep/Foundation/NSIndexSet.h \ /usr/include/GNUstep/Foundation/NSInvocation.h \ /usr/include/GNUstep/Foundation/NSMethodSignature.h \ /usr/include/GNUstep/Foundation/NSKeyedArchiver.h \ /usr/include/GNUstep/Foundation/NSPropertyList.h \ /usr/include/GNUstep/Foundation/NSKeyValueCoding.h \ /usr/include/GNUstep/Foundation/NSNotificationQueue.h \ /usr/include/GNUstep/Foundation/NSNetServices.h \ /usr/include/GNUstep/Foundation/NSNull.h \ /usr/include/GNUstep/Foundation/NSNumberFormatter.h \ /usr/include/GNUstep/Foundation/NSPathUtilities.h \ /usr/include/GNUstep/Foundation/NSPortCoder.h \ /usr/include/GNUstep/Foundation/NSPortMessage.h \ /usr/include/GNUstep/Foundation/NSPort.h \ /usr/include/GNUstep/Foundation/NSPortNameServer.h \ /usr/include/GNUstep/Foundation/NSProtocolChecker.h \ /usr/include/GNUstep/Foundation/NSScanner.h \ /usr/include/GNUstep/Foundation/NSSet.h \ /usr/include/GNUstep/Foundation/NSSortDescriptor.h \ /usr/include/GNUstep/Foundation/NSSpellServer.h \ /usr/include/GNUstep/Foundation/NSStream.h \ /usr/include/GNUstep/Foundation/NSTask.h \ /usr/include/GNUstep/Foundation/NSThread.h \ /usr/include/GNUstep/Foundation/NSTimeZone.h \ /usr/include/GNUstep/Foundation/NSUndoManager.h \ /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h \ /usr/include/GNUstep/Foundation/NSURLCache.h \ /usr/include/GNUstep/Foundation/NSURLConnection.h \ /usr/include/GNUstep/Foundation/NSURLCredential.h \ /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h \ /usr/include/GNUstep/Foundation/NSURLDownload.h \ /usr/include/GNUstep/Foundation/NSURLError.h \ /usr/include/GNUstep/Foundation/NSURL.h \ /usr/include/GNUstep/Foundation/NSURLHandle.h \ /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h \ /usr/include/GNUstep/Foundation/NSURLProtocol.h \ /usr/include/GNUstep/Foundation/NSURLRequest.h \ /usr/include/GNUstep/Foundation/NSURLResponse.h \ /usr/include/GNUstep/Foundation/NSUserDefaults.h \ /usr/include/GNUstep/Foundation/NSValueTransformer.h \ /usr/include/GNUstep/Foundation/NSXMLParser.h SaxAttributes.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: ../SaxObjC/SaxAttributeList.h: ../SaxObjC/SaxAttributes.h: common.h: /usr/include/GNUstep/Foundation/Foundation.h: /usr/include/GNUstep/Foundation/FoundationErrors.h: /usr/include/GNUstep/Foundation/NSDebug.h: /usr/include/GNUstep/Foundation/NSProcessInfo.h: /usr/include/GNUstep/Foundation/NSAffineTransform.h: /usr/include/GNUstep/Foundation/NSGeometry.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: /usr/include/GNUstep/Foundation/NSArchiver.h: /usr/include/GNUstep/Foundation/NSCoder.h: /usr/include/GNUstep/Foundation/NSArray.h: /usr/include/GNUstep/Foundation/NSAttributedString.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/GNUstep/Foundation/NSAutoreleasePool.h: /usr/include/GNUstep/Foundation/NSBundle.h: /usr/include/GNUstep/Foundation/NSByteOrder.h: /usr/include/GNUstep/Foundation/NSCalendarDate.h: /usr/include/GNUstep/Foundation/NSCharacterSet.h: /usr/include/GNUstep/Foundation/NSClassDescription.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/Foundation/NSComparisonPredicate.h: /usr/include/GNUstep/Foundation/NSExpression.h: /usr/include/GNUstep/Foundation/NSPredicate.h: /usr/include/GNUstep/Foundation/NSCompoundPredicate.h: /usr/include/GNUstep/Foundation/NSConnection.h: /usr/include/GNUstep/Foundation/NSTimer.h: /usr/include/GNUstep/Foundation/NSRunLoop.h: /usr/include/GNUstep/Foundation/NSMapTable.h: /usr/include/GNUstep/Foundation/NSData.h: /usr/include/GNUstep/Foundation/NSSerialization.h: /usr/include/GNUstep/Foundation/NSDateFormatter.h: /usr/include/GNUstep/Foundation/NSFormatter.h: /usr/include/GNUstep/Foundation/NSDecimalNumber.h: /usr/include/GNUstep/Foundation/NSDecimal.h: /usr/include/GNUstep/Foundation/NSValue.h: /usr/include/GNUstep/Foundation/NSDistantObject.h: /usr/include/GNUstep/Foundation/NSProxy.h: /usr/include/GNUstep/Foundation/NSDistributedLock.h: /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h: /usr/include/GNUstep/Foundation/NSLock.h: /usr/include/GNUstep/Foundation/NSNotification.h: /usr/include/GNUstep/Foundation/NSEnumerator.h: /usr/include/GNUstep/Foundation/NSError.h: /usr/include/GNUstep/Foundation/NSFileHandle.h: /usr/include/GNUstep/Foundation/NSFileManager.h: /usr/include/GNUstep/Foundation/NSHashTable.h: /usr/include/GNUstep/Foundation/NSHost.h: /usr/include/GNUstep/Foundation/NSHTTPCookie.h: /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h: /usr/include/GNUstep/Foundation/NSIndexPath.h: /usr/include/GNUstep/Foundation/NSIndexSet.h: /usr/include/GNUstep/Foundation/NSInvocation.h: /usr/include/GNUstep/Foundation/NSMethodSignature.h: /usr/include/GNUstep/Foundation/NSKeyedArchiver.h: /usr/include/GNUstep/Foundation/NSPropertyList.h: /usr/include/GNUstep/Foundation/NSKeyValueCoding.h: /usr/include/GNUstep/Foundation/NSNotificationQueue.h: /usr/include/GNUstep/Foundation/NSNetServices.h: /usr/include/GNUstep/Foundation/NSNull.h: /usr/include/GNUstep/Foundation/NSNumberFormatter.h: /usr/include/GNUstep/Foundation/NSPathUtilities.h: /usr/include/GNUstep/Foundation/NSPortCoder.h: /usr/include/GNUstep/Foundation/NSPortMessage.h: /usr/include/GNUstep/Foundation/NSPort.h: /usr/include/GNUstep/Foundation/NSPortNameServer.h: /usr/include/GNUstep/Foundation/NSProtocolChecker.h: /usr/include/GNUstep/Foundation/NSScanner.h: /usr/include/GNUstep/Foundation/NSSet.h: /usr/include/GNUstep/Foundation/NSSortDescriptor.h: /usr/include/GNUstep/Foundation/NSSpellServer.h: /usr/include/GNUstep/Foundation/NSStream.h: /usr/include/GNUstep/Foundation/NSTask.h: /usr/include/GNUstep/Foundation/NSThread.h: /usr/include/GNUstep/Foundation/NSTimeZone.h: /usr/include/GNUstep/Foundation/NSUndoManager.h: /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h: /usr/include/GNUstep/Foundation/NSURLCache.h: /usr/include/GNUstep/Foundation/NSURLConnection.h: /usr/include/GNUstep/Foundation/NSURLCredential.h: /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h: /usr/include/GNUstep/Foundation/NSURLDownload.h: /usr/include/GNUstep/Foundation/NSURLError.h: /usr/include/GNUstep/Foundation/NSURL.h: /usr/include/GNUstep/Foundation/NSURLHandle.h: /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h: /usr/include/GNUstep/Foundation/NSURLProtocol.h: /usr/include/GNUstep/Foundation/NSURLRequest.h: /usr/include/GNUstep/Foundation/NSURLResponse.h: /usr/include/GNUstep/Foundation/NSUserDefaults.h: /usr/include/GNUstep/Foundation/NSValueTransformer.h: /usr/include/GNUstep/Foundation/NSXMLParser.h: SOPE/sope-xml/SaxObjC/shared_debug_obj/SaxDefaultHandler.d0000644000000000000000000000337315004363604022337 0ustar rootrootobj/SaxDefaultHandler.o: SaxDefaultHandler.m SaxDefaultHandler.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h ../SaxObjC/SaxEntityResolver.h \ ../SaxObjC/SaxDTDHandler.h ../SaxObjC/SaxContentHandler.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h ../SaxObjC/SaxAttributes.h \ ../SaxObjC/SaxAttributeList.h ../SaxObjC/SaxLocator.h \ ../SaxObjC/SaxErrorHandler.h SaxException.h \ /usr/include/GNUstep/Foundation/NSException.h SaxDefaultHandler.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: ../SaxObjC/SaxEntityResolver.h: ../SaxObjC/SaxDTDHandler.h: ../SaxObjC/SaxContentHandler.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: ../SaxObjC/SaxAttributes.h: ../SaxObjC/SaxAttributeList.h: ../SaxObjC/SaxLocator.h: ../SaxObjC/SaxErrorHandler.h: SaxException.h: /usr/include/GNUstep/Foundation/NSException.h: SOPE/sope-xml/SaxObjC/shared_debug_obj/SaxObjectModel.d0000644000000000000000000002402315004363604021637 0ustar rootrootobj/SaxObjectModel.o: SaxObjectModel.m SaxObjectModel.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h common.h \ /usr/include/GNUstep/Foundation/Foundation.h \ /usr/include/GNUstep/Foundation/FoundationErrors.h \ /usr/include/GNUstep/Foundation/NSDebug.h \ /usr/include/GNUstep/Foundation/NSProcessInfo.h \ /usr/include/GNUstep/Foundation/NSAffineTransform.h \ /usr/include/GNUstep/Foundation/NSGeometry.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h \ /usr/include/GNUstep/Foundation/NSArchiver.h \ /usr/include/GNUstep/Foundation/NSCoder.h \ /usr/include/GNUstep/Foundation/NSArray.h \ /usr/include/GNUstep/Foundation/NSAttributedString.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/GNUstep/Foundation/NSAutoreleasePool.h \ /usr/include/GNUstep/Foundation/NSBundle.h \ /usr/include/GNUstep/Foundation/NSByteOrder.h \ /usr/include/GNUstep/Foundation/NSCalendarDate.h \ /usr/include/GNUstep/Foundation/NSCharacterSet.h \ /usr/include/GNUstep/Foundation/NSClassDescription.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/Foundation/NSComparisonPredicate.h \ /usr/include/GNUstep/Foundation/NSExpression.h \ /usr/include/GNUstep/Foundation/NSPredicate.h \ /usr/include/GNUstep/Foundation/NSCompoundPredicate.h \ /usr/include/GNUstep/Foundation/NSConnection.h \ /usr/include/GNUstep/Foundation/NSTimer.h \ /usr/include/GNUstep/Foundation/NSRunLoop.h \ /usr/include/GNUstep/Foundation/NSMapTable.h \ /usr/include/GNUstep/Foundation/NSData.h \ /usr/include/GNUstep/Foundation/NSSerialization.h \ /usr/include/GNUstep/Foundation/NSDateFormatter.h \ /usr/include/GNUstep/Foundation/NSFormatter.h \ /usr/include/GNUstep/Foundation/NSDecimalNumber.h \ /usr/include/GNUstep/Foundation/NSDecimal.h \ /usr/include/GNUstep/Foundation/NSValue.h \ /usr/include/GNUstep/Foundation/NSDistantObject.h \ /usr/include/GNUstep/Foundation/NSProxy.h \ /usr/include/GNUstep/Foundation/NSDistributedLock.h \ /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h \ /usr/include/GNUstep/Foundation/NSLock.h \ /usr/include/GNUstep/Foundation/NSNotification.h \ /usr/include/GNUstep/Foundation/NSEnumerator.h \ /usr/include/GNUstep/Foundation/NSError.h \ /usr/include/GNUstep/Foundation/NSFileHandle.h \ /usr/include/GNUstep/Foundation/NSFileManager.h \ /usr/include/GNUstep/Foundation/NSHashTable.h \ /usr/include/GNUstep/Foundation/NSHost.h \ /usr/include/GNUstep/Foundation/NSHTTPCookie.h \ /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h \ /usr/include/GNUstep/Foundation/NSIndexPath.h \ /usr/include/GNUstep/Foundation/NSIndexSet.h \ /usr/include/GNUstep/Foundation/NSInvocation.h \ /usr/include/GNUstep/Foundation/NSMethodSignature.h \ /usr/include/GNUstep/Foundation/NSKeyedArchiver.h \ /usr/include/GNUstep/Foundation/NSPropertyList.h \ /usr/include/GNUstep/Foundation/NSKeyValueCoding.h \ /usr/include/GNUstep/Foundation/NSNotificationQueue.h \ /usr/include/GNUstep/Foundation/NSNetServices.h \ /usr/include/GNUstep/Foundation/NSNull.h \ /usr/include/GNUstep/Foundation/NSNumberFormatter.h \ /usr/include/GNUstep/Foundation/NSPathUtilities.h \ /usr/include/GNUstep/Foundation/NSPortCoder.h \ /usr/include/GNUstep/Foundation/NSPortMessage.h \ /usr/include/GNUstep/Foundation/NSPort.h \ /usr/include/GNUstep/Foundation/NSPortNameServer.h \ /usr/include/GNUstep/Foundation/NSProtocolChecker.h \ /usr/include/GNUstep/Foundation/NSScanner.h \ /usr/include/GNUstep/Foundation/NSSet.h \ /usr/include/GNUstep/Foundation/NSSortDescriptor.h \ /usr/include/GNUstep/Foundation/NSSpellServer.h \ /usr/include/GNUstep/Foundation/NSStream.h \ /usr/include/GNUstep/Foundation/NSTask.h \ /usr/include/GNUstep/Foundation/NSThread.h \ /usr/include/GNUstep/Foundation/NSTimeZone.h \ /usr/include/GNUstep/Foundation/NSUndoManager.h \ /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h \ /usr/include/GNUstep/Foundation/NSURLCache.h \ /usr/include/GNUstep/Foundation/NSURLConnection.h \ /usr/include/GNUstep/Foundation/NSURLCredential.h \ /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h \ /usr/include/GNUstep/Foundation/NSURLDownload.h \ /usr/include/GNUstep/Foundation/NSURLError.h \ /usr/include/GNUstep/Foundation/NSURL.h \ /usr/include/GNUstep/Foundation/NSURLHandle.h \ /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h \ /usr/include/GNUstep/Foundation/NSURLProtocol.h \ /usr/include/GNUstep/Foundation/NSURLRequest.h \ /usr/include/GNUstep/Foundation/NSURLResponse.h \ /usr/include/GNUstep/Foundation/NSUserDefaults.h \ /usr/include/GNUstep/Foundation/NSValueTransformer.h \ /usr/include/GNUstep/Foundation/NSXMLParser.h SaxObjectModel.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: common.h: /usr/include/GNUstep/Foundation/Foundation.h: /usr/include/GNUstep/Foundation/FoundationErrors.h: /usr/include/GNUstep/Foundation/NSDebug.h: /usr/include/GNUstep/Foundation/NSProcessInfo.h: /usr/include/GNUstep/Foundation/NSAffineTransform.h: /usr/include/GNUstep/Foundation/NSGeometry.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: /usr/include/GNUstep/Foundation/NSArchiver.h: /usr/include/GNUstep/Foundation/NSCoder.h: /usr/include/GNUstep/Foundation/NSArray.h: /usr/include/GNUstep/Foundation/NSAttributedString.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/GNUstep/Foundation/NSAutoreleasePool.h: /usr/include/GNUstep/Foundation/NSBundle.h: /usr/include/GNUstep/Foundation/NSByteOrder.h: /usr/include/GNUstep/Foundation/NSCalendarDate.h: /usr/include/GNUstep/Foundation/NSCharacterSet.h: /usr/include/GNUstep/Foundation/NSClassDescription.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/Foundation/NSComparisonPredicate.h: /usr/include/GNUstep/Foundation/NSExpression.h: /usr/include/GNUstep/Foundation/NSPredicate.h: /usr/include/GNUstep/Foundation/NSCompoundPredicate.h: /usr/include/GNUstep/Foundation/NSConnection.h: /usr/include/GNUstep/Foundation/NSTimer.h: /usr/include/GNUstep/Foundation/NSRunLoop.h: /usr/include/GNUstep/Foundation/NSMapTable.h: /usr/include/GNUstep/Foundation/NSData.h: /usr/include/GNUstep/Foundation/NSSerialization.h: /usr/include/GNUstep/Foundation/NSDateFormatter.h: /usr/include/GNUstep/Foundation/NSFormatter.h: /usr/include/GNUstep/Foundation/NSDecimalNumber.h: /usr/include/GNUstep/Foundation/NSDecimal.h: /usr/include/GNUstep/Foundation/NSValue.h: /usr/include/GNUstep/Foundation/NSDistantObject.h: /usr/include/GNUstep/Foundation/NSProxy.h: /usr/include/GNUstep/Foundation/NSDistributedLock.h: /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h: /usr/include/GNUstep/Foundation/NSLock.h: /usr/include/GNUstep/Foundation/NSNotification.h: /usr/include/GNUstep/Foundation/NSEnumerator.h: /usr/include/GNUstep/Foundation/NSError.h: /usr/include/GNUstep/Foundation/NSFileHandle.h: /usr/include/GNUstep/Foundation/NSFileManager.h: /usr/include/GNUstep/Foundation/NSHashTable.h: /usr/include/GNUstep/Foundation/NSHost.h: /usr/include/GNUstep/Foundation/NSHTTPCookie.h: /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h: /usr/include/GNUstep/Foundation/NSIndexPath.h: /usr/include/GNUstep/Foundation/NSIndexSet.h: /usr/include/GNUstep/Foundation/NSInvocation.h: /usr/include/GNUstep/Foundation/NSMethodSignature.h: /usr/include/GNUstep/Foundation/NSKeyedArchiver.h: /usr/include/GNUstep/Foundation/NSPropertyList.h: /usr/include/GNUstep/Foundation/NSKeyValueCoding.h: /usr/include/GNUstep/Foundation/NSNotificationQueue.h: /usr/include/GNUstep/Foundation/NSNetServices.h: /usr/include/GNUstep/Foundation/NSNull.h: /usr/include/GNUstep/Foundation/NSNumberFormatter.h: /usr/include/GNUstep/Foundation/NSPathUtilities.h: /usr/include/GNUstep/Foundation/NSPortCoder.h: /usr/include/GNUstep/Foundation/NSPortMessage.h: /usr/include/GNUstep/Foundation/NSPort.h: /usr/include/GNUstep/Foundation/NSPortNameServer.h: /usr/include/GNUstep/Foundation/NSProtocolChecker.h: /usr/include/GNUstep/Foundation/NSScanner.h: /usr/include/GNUstep/Foundation/NSSet.h: /usr/include/GNUstep/Foundation/NSSortDescriptor.h: /usr/include/GNUstep/Foundation/NSSpellServer.h: /usr/include/GNUstep/Foundation/NSStream.h: /usr/include/GNUstep/Foundation/NSTask.h: /usr/include/GNUstep/Foundation/NSThread.h: /usr/include/GNUstep/Foundation/NSTimeZone.h: /usr/include/GNUstep/Foundation/NSUndoManager.h: /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h: /usr/include/GNUstep/Foundation/NSURLCache.h: /usr/include/GNUstep/Foundation/NSURLConnection.h: /usr/include/GNUstep/Foundation/NSURLCredential.h: /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h: /usr/include/GNUstep/Foundation/NSURLDownload.h: /usr/include/GNUstep/Foundation/NSURLError.h: /usr/include/GNUstep/Foundation/NSURL.h: /usr/include/GNUstep/Foundation/NSURLHandle.h: /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h: /usr/include/GNUstep/Foundation/NSURLProtocol.h: /usr/include/GNUstep/Foundation/NSURLRequest.h: /usr/include/GNUstep/Foundation/NSURLResponse.h: /usr/include/GNUstep/Foundation/NSUserDefaults.h: /usr/include/GNUstep/Foundation/NSValueTransformer.h: /usr/include/GNUstep/Foundation/NSXMLParser.h: SOPE/sope-xml/SaxObjC/shared_debug_obj/SaxXMLReaderFactory.d0000644000000000000000000002501115004363604022561 0ustar rootrootobj/SaxXMLReaderFactory.o: SaxXMLReaderFactory.m SaxXMLReaderFactory.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h ../SaxObjC/SaxXMLReader.h \ ../SaxObjC/SaxContentHandler.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h ../SaxObjC/SaxAttributes.h \ ../SaxObjC/SaxAttributeList.h ../SaxObjC/SaxLocator.h \ ../SaxObjC/SaxDTDHandler.h ../SaxObjC/SaxErrorHandler.h \ ../SaxObjC/SaxEntityResolver.h common.h \ /usr/include/GNUstep/Foundation/Foundation.h \ /usr/include/GNUstep/Foundation/FoundationErrors.h \ /usr/include/GNUstep/Foundation/NSDebug.h \ /usr/include/GNUstep/Foundation/NSProcessInfo.h \ /usr/include/GNUstep/Foundation/NSAffineTransform.h \ /usr/include/GNUstep/Foundation/NSGeometry.h \ /usr/include/GNUstep/Foundation/NSArchiver.h \ /usr/include/GNUstep/Foundation/NSCoder.h \ /usr/include/GNUstep/Foundation/NSArray.h \ /usr/include/GNUstep/Foundation/NSAttributedString.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/GNUstep/Foundation/NSAutoreleasePool.h \ /usr/include/GNUstep/Foundation/NSBundle.h \ /usr/include/GNUstep/Foundation/NSByteOrder.h \ /usr/include/GNUstep/Foundation/NSCalendarDate.h \ /usr/include/GNUstep/Foundation/NSCharacterSet.h \ /usr/include/GNUstep/Foundation/NSClassDescription.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/Foundation/NSComparisonPredicate.h \ /usr/include/GNUstep/Foundation/NSExpression.h \ /usr/include/GNUstep/Foundation/NSPredicate.h \ /usr/include/GNUstep/Foundation/NSCompoundPredicate.h \ /usr/include/GNUstep/Foundation/NSConnection.h \ /usr/include/GNUstep/Foundation/NSTimer.h \ /usr/include/GNUstep/Foundation/NSRunLoop.h \ /usr/include/GNUstep/Foundation/NSMapTable.h \ /usr/include/GNUstep/Foundation/NSData.h \ /usr/include/GNUstep/Foundation/NSSerialization.h \ /usr/include/GNUstep/Foundation/NSDateFormatter.h \ /usr/include/GNUstep/Foundation/NSFormatter.h \ /usr/include/GNUstep/Foundation/NSDecimalNumber.h \ /usr/include/GNUstep/Foundation/NSDecimal.h \ /usr/include/GNUstep/Foundation/NSValue.h \ /usr/include/GNUstep/Foundation/NSDistantObject.h \ /usr/include/GNUstep/Foundation/NSProxy.h \ /usr/include/GNUstep/Foundation/NSDistributedLock.h \ /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h \ /usr/include/GNUstep/Foundation/NSLock.h \ /usr/include/GNUstep/Foundation/NSNotification.h \ /usr/include/GNUstep/Foundation/NSEnumerator.h \ /usr/include/GNUstep/Foundation/NSError.h \ /usr/include/GNUstep/Foundation/NSFileHandle.h \ /usr/include/GNUstep/Foundation/NSFileManager.h \ /usr/include/GNUstep/Foundation/NSHashTable.h \ /usr/include/GNUstep/Foundation/NSHost.h \ /usr/include/GNUstep/Foundation/NSHTTPCookie.h \ /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h \ /usr/include/GNUstep/Foundation/NSIndexPath.h \ /usr/include/GNUstep/Foundation/NSIndexSet.h \ /usr/include/GNUstep/Foundation/NSInvocation.h \ /usr/include/GNUstep/Foundation/NSMethodSignature.h \ /usr/include/GNUstep/Foundation/NSKeyedArchiver.h \ /usr/include/GNUstep/Foundation/NSPropertyList.h \ /usr/include/GNUstep/Foundation/NSKeyValueCoding.h \ /usr/include/GNUstep/Foundation/NSNotificationQueue.h \ /usr/include/GNUstep/Foundation/NSNetServices.h \ /usr/include/GNUstep/Foundation/NSNull.h \ /usr/include/GNUstep/Foundation/NSNumberFormatter.h \ /usr/include/GNUstep/Foundation/NSPathUtilities.h \ /usr/include/GNUstep/Foundation/NSPortCoder.h \ /usr/include/GNUstep/Foundation/NSPortMessage.h \ /usr/include/GNUstep/Foundation/NSPort.h \ /usr/include/GNUstep/Foundation/NSPortNameServer.h \ /usr/include/GNUstep/Foundation/NSProtocolChecker.h \ /usr/include/GNUstep/Foundation/NSScanner.h \ /usr/include/GNUstep/Foundation/NSSet.h \ /usr/include/GNUstep/Foundation/NSSortDescriptor.h \ /usr/include/GNUstep/Foundation/NSSpellServer.h \ /usr/include/GNUstep/Foundation/NSStream.h \ /usr/include/GNUstep/Foundation/NSTask.h \ /usr/include/GNUstep/Foundation/NSThread.h \ /usr/include/GNUstep/Foundation/NSTimeZone.h \ /usr/include/GNUstep/Foundation/NSUndoManager.h \ /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h \ /usr/include/GNUstep/Foundation/NSURLCache.h \ /usr/include/GNUstep/Foundation/NSURLConnection.h \ /usr/include/GNUstep/Foundation/NSURLCredential.h \ /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h \ /usr/include/GNUstep/Foundation/NSURLDownload.h \ /usr/include/GNUstep/Foundation/NSURLError.h \ /usr/include/GNUstep/Foundation/NSURL.h \ /usr/include/GNUstep/Foundation/NSURLHandle.h \ /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h \ /usr/include/GNUstep/Foundation/NSURLProtocol.h \ /usr/include/GNUstep/Foundation/NSURLRequest.h \ /usr/include/GNUstep/Foundation/NSURLResponse.h \ /usr/include/GNUstep/Foundation/NSUserDefaults.h \ /usr/include/GNUstep/Foundation/NSValueTransformer.h \ /usr/include/GNUstep/Foundation/NSXMLParser.h SaxXMLReaderFactory.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: ../SaxObjC/SaxXMLReader.h: ../SaxObjC/SaxContentHandler.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: ../SaxObjC/SaxAttributes.h: ../SaxObjC/SaxAttributeList.h: ../SaxObjC/SaxLocator.h: ../SaxObjC/SaxDTDHandler.h: ../SaxObjC/SaxErrorHandler.h: ../SaxObjC/SaxEntityResolver.h: common.h: /usr/include/GNUstep/Foundation/Foundation.h: /usr/include/GNUstep/Foundation/FoundationErrors.h: /usr/include/GNUstep/Foundation/NSDebug.h: /usr/include/GNUstep/Foundation/NSProcessInfo.h: /usr/include/GNUstep/Foundation/NSAffineTransform.h: /usr/include/GNUstep/Foundation/NSGeometry.h: /usr/include/GNUstep/Foundation/NSArchiver.h: /usr/include/GNUstep/Foundation/NSCoder.h: /usr/include/GNUstep/Foundation/NSArray.h: /usr/include/GNUstep/Foundation/NSAttributedString.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/GNUstep/Foundation/NSAutoreleasePool.h: /usr/include/GNUstep/Foundation/NSBundle.h: /usr/include/GNUstep/Foundation/NSByteOrder.h: /usr/include/GNUstep/Foundation/NSCalendarDate.h: /usr/include/GNUstep/Foundation/NSCharacterSet.h: /usr/include/GNUstep/Foundation/NSClassDescription.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/Foundation/NSComparisonPredicate.h: /usr/include/GNUstep/Foundation/NSExpression.h: /usr/include/GNUstep/Foundation/NSPredicate.h: /usr/include/GNUstep/Foundation/NSCompoundPredicate.h: /usr/include/GNUstep/Foundation/NSConnection.h: /usr/include/GNUstep/Foundation/NSTimer.h: /usr/include/GNUstep/Foundation/NSRunLoop.h: /usr/include/GNUstep/Foundation/NSMapTable.h: /usr/include/GNUstep/Foundation/NSData.h: /usr/include/GNUstep/Foundation/NSSerialization.h: /usr/include/GNUstep/Foundation/NSDateFormatter.h: /usr/include/GNUstep/Foundation/NSFormatter.h: /usr/include/GNUstep/Foundation/NSDecimalNumber.h: /usr/include/GNUstep/Foundation/NSDecimal.h: /usr/include/GNUstep/Foundation/NSValue.h: /usr/include/GNUstep/Foundation/NSDistantObject.h: /usr/include/GNUstep/Foundation/NSProxy.h: /usr/include/GNUstep/Foundation/NSDistributedLock.h: /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h: /usr/include/GNUstep/Foundation/NSLock.h: /usr/include/GNUstep/Foundation/NSNotification.h: /usr/include/GNUstep/Foundation/NSEnumerator.h: /usr/include/GNUstep/Foundation/NSError.h: /usr/include/GNUstep/Foundation/NSFileHandle.h: /usr/include/GNUstep/Foundation/NSFileManager.h: /usr/include/GNUstep/Foundation/NSHashTable.h: /usr/include/GNUstep/Foundation/NSHost.h: /usr/include/GNUstep/Foundation/NSHTTPCookie.h: /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h: /usr/include/GNUstep/Foundation/NSIndexPath.h: /usr/include/GNUstep/Foundation/NSIndexSet.h: /usr/include/GNUstep/Foundation/NSInvocation.h: /usr/include/GNUstep/Foundation/NSMethodSignature.h: /usr/include/GNUstep/Foundation/NSKeyedArchiver.h: /usr/include/GNUstep/Foundation/NSPropertyList.h: /usr/include/GNUstep/Foundation/NSKeyValueCoding.h: /usr/include/GNUstep/Foundation/NSNotificationQueue.h: /usr/include/GNUstep/Foundation/NSNetServices.h: /usr/include/GNUstep/Foundation/NSNull.h: /usr/include/GNUstep/Foundation/NSNumberFormatter.h: /usr/include/GNUstep/Foundation/NSPathUtilities.h: /usr/include/GNUstep/Foundation/NSPortCoder.h: /usr/include/GNUstep/Foundation/NSPortMessage.h: /usr/include/GNUstep/Foundation/NSPort.h: /usr/include/GNUstep/Foundation/NSPortNameServer.h: /usr/include/GNUstep/Foundation/NSProtocolChecker.h: /usr/include/GNUstep/Foundation/NSScanner.h: /usr/include/GNUstep/Foundation/NSSet.h: /usr/include/GNUstep/Foundation/NSSortDescriptor.h: /usr/include/GNUstep/Foundation/NSSpellServer.h: /usr/include/GNUstep/Foundation/NSStream.h: /usr/include/GNUstep/Foundation/NSTask.h: /usr/include/GNUstep/Foundation/NSThread.h: /usr/include/GNUstep/Foundation/NSTimeZone.h: /usr/include/GNUstep/Foundation/NSUndoManager.h: /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h: /usr/include/GNUstep/Foundation/NSURLCache.h: /usr/include/GNUstep/Foundation/NSURLConnection.h: /usr/include/GNUstep/Foundation/NSURLCredential.h: /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h: /usr/include/GNUstep/Foundation/NSURLDownload.h: /usr/include/GNUstep/Foundation/NSURLError.h: /usr/include/GNUstep/Foundation/NSURL.h: /usr/include/GNUstep/Foundation/NSURLHandle.h: /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h: /usr/include/GNUstep/Foundation/NSURLProtocol.h: /usr/include/GNUstep/Foundation/NSURLRequest.h: /usr/include/GNUstep/Foundation/NSURLResponse.h: /usr/include/GNUstep/Foundation/NSUserDefaults.h: /usr/include/GNUstep/Foundation/NSValueTransformer.h: /usr/include/GNUstep/Foundation/NSXMLParser.h: SOPE/sope-xml/SaxObjC/shared_debug_obj/SaxNamespaceSupport.d0000644000000000000000000002404715004363604022747 0ustar rootrootobj/SaxNamespaceSupport.o: SaxNamespaceSupport.m SaxNamespaceSupport.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h common.h \ /usr/include/GNUstep/Foundation/Foundation.h \ /usr/include/GNUstep/Foundation/FoundationErrors.h \ /usr/include/GNUstep/Foundation/NSDebug.h \ /usr/include/GNUstep/Foundation/NSProcessInfo.h \ /usr/include/GNUstep/Foundation/NSAffineTransform.h \ /usr/include/GNUstep/Foundation/NSGeometry.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h \ /usr/include/GNUstep/Foundation/NSArchiver.h \ /usr/include/GNUstep/Foundation/NSCoder.h \ /usr/include/GNUstep/Foundation/NSArray.h \ /usr/include/GNUstep/Foundation/NSAttributedString.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/GNUstep/Foundation/NSAutoreleasePool.h \ /usr/include/GNUstep/Foundation/NSBundle.h \ /usr/include/GNUstep/Foundation/NSByteOrder.h \ /usr/include/GNUstep/Foundation/NSCalendarDate.h \ /usr/include/GNUstep/Foundation/NSCharacterSet.h \ /usr/include/GNUstep/Foundation/NSClassDescription.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/Foundation/NSComparisonPredicate.h \ /usr/include/GNUstep/Foundation/NSExpression.h \ /usr/include/GNUstep/Foundation/NSPredicate.h \ /usr/include/GNUstep/Foundation/NSCompoundPredicate.h \ /usr/include/GNUstep/Foundation/NSConnection.h \ /usr/include/GNUstep/Foundation/NSTimer.h \ /usr/include/GNUstep/Foundation/NSRunLoop.h \ /usr/include/GNUstep/Foundation/NSMapTable.h \ /usr/include/GNUstep/Foundation/NSData.h \ /usr/include/GNUstep/Foundation/NSSerialization.h \ /usr/include/GNUstep/Foundation/NSDateFormatter.h \ /usr/include/GNUstep/Foundation/NSFormatter.h \ /usr/include/GNUstep/Foundation/NSDecimalNumber.h \ /usr/include/GNUstep/Foundation/NSDecimal.h \ /usr/include/GNUstep/Foundation/NSValue.h \ /usr/include/GNUstep/Foundation/NSDistantObject.h \ /usr/include/GNUstep/Foundation/NSProxy.h \ /usr/include/GNUstep/Foundation/NSDistributedLock.h \ /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h \ /usr/include/GNUstep/Foundation/NSLock.h \ /usr/include/GNUstep/Foundation/NSNotification.h \ /usr/include/GNUstep/Foundation/NSEnumerator.h \ /usr/include/GNUstep/Foundation/NSError.h \ /usr/include/GNUstep/Foundation/NSFileHandle.h \ /usr/include/GNUstep/Foundation/NSFileManager.h \ /usr/include/GNUstep/Foundation/NSHashTable.h \ /usr/include/GNUstep/Foundation/NSHost.h \ /usr/include/GNUstep/Foundation/NSHTTPCookie.h \ /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h \ /usr/include/GNUstep/Foundation/NSIndexPath.h \ /usr/include/GNUstep/Foundation/NSIndexSet.h \ /usr/include/GNUstep/Foundation/NSInvocation.h \ /usr/include/GNUstep/Foundation/NSMethodSignature.h \ /usr/include/GNUstep/Foundation/NSKeyedArchiver.h \ /usr/include/GNUstep/Foundation/NSPropertyList.h \ /usr/include/GNUstep/Foundation/NSKeyValueCoding.h \ /usr/include/GNUstep/Foundation/NSNotificationQueue.h \ /usr/include/GNUstep/Foundation/NSNetServices.h \ /usr/include/GNUstep/Foundation/NSNull.h \ /usr/include/GNUstep/Foundation/NSNumberFormatter.h \ /usr/include/GNUstep/Foundation/NSPathUtilities.h \ /usr/include/GNUstep/Foundation/NSPortCoder.h \ /usr/include/GNUstep/Foundation/NSPortMessage.h \ /usr/include/GNUstep/Foundation/NSPort.h \ /usr/include/GNUstep/Foundation/NSPortNameServer.h \ /usr/include/GNUstep/Foundation/NSProtocolChecker.h \ /usr/include/GNUstep/Foundation/NSScanner.h \ /usr/include/GNUstep/Foundation/NSSet.h \ /usr/include/GNUstep/Foundation/NSSortDescriptor.h \ /usr/include/GNUstep/Foundation/NSSpellServer.h \ /usr/include/GNUstep/Foundation/NSStream.h \ /usr/include/GNUstep/Foundation/NSTask.h \ /usr/include/GNUstep/Foundation/NSThread.h \ /usr/include/GNUstep/Foundation/NSTimeZone.h \ /usr/include/GNUstep/Foundation/NSUndoManager.h \ /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h \ /usr/include/GNUstep/Foundation/NSURLCache.h \ /usr/include/GNUstep/Foundation/NSURLConnection.h \ /usr/include/GNUstep/Foundation/NSURLCredential.h \ /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h \ /usr/include/GNUstep/Foundation/NSURLDownload.h \ /usr/include/GNUstep/Foundation/NSURLError.h \ /usr/include/GNUstep/Foundation/NSURL.h \ /usr/include/GNUstep/Foundation/NSURLHandle.h \ /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h \ /usr/include/GNUstep/Foundation/NSURLProtocol.h \ /usr/include/GNUstep/Foundation/NSURLRequest.h \ /usr/include/GNUstep/Foundation/NSURLResponse.h \ /usr/include/GNUstep/Foundation/NSUserDefaults.h \ /usr/include/GNUstep/Foundation/NSValueTransformer.h \ /usr/include/GNUstep/Foundation/NSXMLParser.h SaxNamespaceSupport.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: common.h: /usr/include/GNUstep/Foundation/Foundation.h: /usr/include/GNUstep/Foundation/FoundationErrors.h: /usr/include/GNUstep/Foundation/NSDebug.h: /usr/include/GNUstep/Foundation/NSProcessInfo.h: /usr/include/GNUstep/Foundation/NSAffineTransform.h: /usr/include/GNUstep/Foundation/NSGeometry.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: /usr/include/GNUstep/Foundation/NSArchiver.h: /usr/include/GNUstep/Foundation/NSCoder.h: /usr/include/GNUstep/Foundation/NSArray.h: /usr/include/GNUstep/Foundation/NSAttributedString.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/GNUstep/Foundation/NSAutoreleasePool.h: /usr/include/GNUstep/Foundation/NSBundle.h: /usr/include/GNUstep/Foundation/NSByteOrder.h: /usr/include/GNUstep/Foundation/NSCalendarDate.h: /usr/include/GNUstep/Foundation/NSCharacterSet.h: /usr/include/GNUstep/Foundation/NSClassDescription.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/Foundation/NSComparisonPredicate.h: /usr/include/GNUstep/Foundation/NSExpression.h: /usr/include/GNUstep/Foundation/NSPredicate.h: /usr/include/GNUstep/Foundation/NSCompoundPredicate.h: /usr/include/GNUstep/Foundation/NSConnection.h: /usr/include/GNUstep/Foundation/NSTimer.h: /usr/include/GNUstep/Foundation/NSRunLoop.h: /usr/include/GNUstep/Foundation/NSMapTable.h: /usr/include/GNUstep/Foundation/NSData.h: /usr/include/GNUstep/Foundation/NSSerialization.h: /usr/include/GNUstep/Foundation/NSDateFormatter.h: /usr/include/GNUstep/Foundation/NSFormatter.h: /usr/include/GNUstep/Foundation/NSDecimalNumber.h: /usr/include/GNUstep/Foundation/NSDecimal.h: /usr/include/GNUstep/Foundation/NSValue.h: /usr/include/GNUstep/Foundation/NSDistantObject.h: /usr/include/GNUstep/Foundation/NSProxy.h: /usr/include/GNUstep/Foundation/NSDistributedLock.h: /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h: /usr/include/GNUstep/Foundation/NSLock.h: /usr/include/GNUstep/Foundation/NSNotification.h: /usr/include/GNUstep/Foundation/NSEnumerator.h: /usr/include/GNUstep/Foundation/NSError.h: /usr/include/GNUstep/Foundation/NSFileHandle.h: /usr/include/GNUstep/Foundation/NSFileManager.h: /usr/include/GNUstep/Foundation/NSHashTable.h: /usr/include/GNUstep/Foundation/NSHost.h: /usr/include/GNUstep/Foundation/NSHTTPCookie.h: /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h: /usr/include/GNUstep/Foundation/NSIndexPath.h: /usr/include/GNUstep/Foundation/NSIndexSet.h: /usr/include/GNUstep/Foundation/NSInvocation.h: /usr/include/GNUstep/Foundation/NSMethodSignature.h: /usr/include/GNUstep/Foundation/NSKeyedArchiver.h: /usr/include/GNUstep/Foundation/NSPropertyList.h: /usr/include/GNUstep/Foundation/NSKeyValueCoding.h: /usr/include/GNUstep/Foundation/NSNotificationQueue.h: /usr/include/GNUstep/Foundation/NSNetServices.h: /usr/include/GNUstep/Foundation/NSNull.h: /usr/include/GNUstep/Foundation/NSNumberFormatter.h: /usr/include/GNUstep/Foundation/NSPathUtilities.h: /usr/include/GNUstep/Foundation/NSPortCoder.h: /usr/include/GNUstep/Foundation/NSPortMessage.h: /usr/include/GNUstep/Foundation/NSPort.h: /usr/include/GNUstep/Foundation/NSPortNameServer.h: /usr/include/GNUstep/Foundation/NSProtocolChecker.h: /usr/include/GNUstep/Foundation/NSScanner.h: /usr/include/GNUstep/Foundation/NSSet.h: /usr/include/GNUstep/Foundation/NSSortDescriptor.h: /usr/include/GNUstep/Foundation/NSSpellServer.h: /usr/include/GNUstep/Foundation/NSStream.h: /usr/include/GNUstep/Foundation/NSTask.h: /usr/include/GNUstep/Foundation/NSThread.h: /usr/include/GNUstep/Foundation/NSTimeZone.h: /usr/include/GNUstep/Foundation/NSUndoManager.h: /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h: /usr/include/GNUstep/Foundation/NSURLCache.h: /usr/include/GNUstep/Foundation/NSURLConnection.h: /usr/include/GNUstep/Foundation/NSURLCredential.h: /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h: /usr/include/GNUstep/Foundation/NSURLDownload.h: /usr/include/GNUstep/Foundation/NSURLError.h: /usr/include/GNUstep/Foundation/NSURL.h: /usr/include/GNUstep/Foundation/NSURLHandle.h: /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h: /usr/include/GNUstep/Foundation/NSURLProtocol.h: /usr/include/GNUstep/Foundation/NSURLRequest.h: /usr/include/GNUstep/Foundation/NSURLResponse.h: /usr/include/GNUstep/Foundation/NSUserDefaults.h: /usr/include/GNUstep/Foundation/NSValueTransformer.h: /usr/include/GNUstep/Foundation/NSXMLParser.h: SOPE/sope-xml/SaxObjC/shared_debug_obj/SaxMethodCallHandler.d0000644000000000000000000002502715004363604022767 0ustar rootrootobj/SaxMethodCallHandler.o: SaxMethodCallHandler.m SaxMethodCallHandler.h \ ../SaxObjC/SaxDefaultHandler.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h ../SaxObjC/SaxEntityResolver.h \ ../SaxObjC/SaxDTDHandler.h ../SaxObjC/SaxContentHandler.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h ../SaxObjC/SaxAttributes.h \ ../SaxObjC/SaxAttributeList.h ../SaxObjC/SaxLocator.h \ ../SaxObjC/SaxErrorHandler.h \ /usr/include/GNUstep/Foundation/NSMapTable.h \ /usr/include/GNUstep/Foundation/NSArray.h common.h \ /usr/include/GNUstep/Foundation/Foundation.h \ /usr/include/GNUstep/Foundation/FoundationErrors.h \ /usr/include/GNUstep/Foundation/NSDebug.h \ /usr/include/GNUstep/Foundation/NSProcessInfo.h \ /usr/include/GNUstep/Foundation/NSAffineTransform.h \ /usr/include/GNUstep/Foundation/NSGeometry.h \ /usr/include/GNUstep/Foundation/NSArchiver.h \ /usr/include/GNUstep/Foundation/NSCoder.h \ /usr/include/GNUstep/Foundation/NSAttributedString.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/GNUstep/Foundation/NSAutoreleasePool.h \ /usr/include/GNUstep/Foundation/NSBundle.h \ /usr/include/GNUstep/Foundation/NSByteOrder.h \ /usr/include/GNUstep/Foundation/NSCalendarDate.h \ /usr/include/GNUstep/Foundation/NSCharacterSet.h \ /usr/include/GNUstep/Foundation/NSClassDescription.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/Foundation/NSComparisonPredicate.h \ /usr/include/GNUstep/Foundation/NSExpression.h \ /usr/include/GNUstep/Foundation/NSPredicate.h \ /usr/include/GNUstep/Foundation/NSCompoundPredicate.h \ /usr/include/GNUstep/Foundation/NSConnection.h \ /usr/include/GNUstep/Foundation/NSTimer.h \ /usr/include/GNUstep/Foundation/NSRunLoop.h \ /usr/include/GNUstep/Foundation/NSData.h \ /usr/include/GNUstep/Foundation/NSSerialization.h \ /usr/include/GNUstep/Foundation/NSDateFormatter.h \ /usr/include/GNUstep/Foundation/NSFormatter.h \ /usr/include/GNUstep/Foundation/NSDecimalNumber.h \ /usr/include/GNUstep/Foundation/NSDecimal.h \ /usr/include/GNUstep/Foundation/NSValue.h \ /usr/include/GNUstep/Foundation/NSDistantObject.h \ /usr/include/GNUstep/Foundation/NSProxy.h \ /usr/include/GNUstep/Foundation/NSDistributedLock.h \ /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h \ /usr/include/GNUstep/Foundation/NSLock.h \ /usr/include/GNUstep/Foundation/NSNotification.h \ /usr/include/GNUstep/Foundation/NSEnumerator.h \ /usr/include/GNUstep/Foundation/NSError.h \ /usr/include/GNUstep/Foundation/NSFileHandle.h \ /usr/include/GNUstep/Foundation/NSFileManager.h \ /usr/include/GNUstep/Foundation/NSHashTable.h \ /usr/include/GNUstep/Foundation/NSHost.h \ /usr/include/GNUstep/Foundation/NSHTTPCookie.h \ /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h \ /usr/include/GNUstep/Foundation/NSIndexPath.h \ /usr/include/GNUstep/Foundation/NSIndexSet.h \ /usr/include/GNUstep/Foundation/NSInvocation.h \ /usr/include/GNUstep/Foundation/NSMethodSignature.h \ /usr/include/GNUstep/Foundation/NSKeyedArchiver.h \ /usr/include/GNUstep/Foundation/NSPropertyList.h \ /usr/include/GNUstep/Foundation/NSKeyValueCoding.h \ /usr/include/GNUstep/Foundation/NSNotificationQueue.h \ /usr/include/GNUstep/Foundation/NSNetServices.h \ /usr/include/GNUstep/Foundation/NSNull.h \ /usr/include/GNUstep/Foundation/NSNumberFormatter.h \ /usr/include/GNUstep/Foundation/NSPathUtilities.h \ /usr/include/GNUstep/Foundation/NSPortCoder.h \ /usr/include/GNUstep/Foundation/NSPortMessage.h \ /usr/include/GNUstep/Foundation/NSPort.h \ /usr/include/GNUstep/Foundation/NSPortNameServer.h \ /usr/include/GNUstep/Foundation/NSProtocolChecker.h \ /usr/include/GNUstep/Foundation/NSScanner.h \ /usr/include/GNUstep/Foundation/NSSet.h \ /usr/include/GNUstep/Foundation/NSSortDescriptor.h \ /usr/include/GNUstep/Foundation/NSSpellServer.h \ /usr/include/GNUstep/Foundation/NSStream.h \ /usr/include/GNUstep/Foundation/NSTask.h \ /usr/include/GNUstep/Foundation/NSThread.h \ /usr/include/GNUstep/Foundation/NSTimeZone.h \ /usr/include/GNUstep/Foundation/NSUndoManager.h \ /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h \ /usr/include/GNUstep/Foundation/NSURLCache.h \ /usr/include/GNUstep/Foundation/NSURLConnection.h \ /usr/include/GNUstep/Foundation/NSURLCredential.h \ /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h \ /usr/include/GNUstep/Foundation/NSURLDownload.h \ /usr/include/GNUstep/Foundation/NSURLError.h \ /usr/include/GNUstep/Foundation/NSURL.h \ /usr/include/GNUstep/Foundation/NSURLHandle.h \ /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h \ /usr/include/GNUstep/Foundation/NSURLProtocol.h \ /usr/include/GNUstep/Foundation/NSURLRequest.h \ /usr/include/GNUstep/Foundation/NSURLResponse.h \ /usr/include/GNUstep/Foundation/NSUserDefaults.h \ /usr/include/GNUstep/Foundation/NSValueTransformer.h \ /usr/include/GNUstep/Foundation/NSXMLParser.h SaxMethodCallHandler.h: ../SaxObjC/SaxDefaultHandler.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: ../SaxObjC/SaxEntityResolver.h: ../SaxObjC/SaxDTDHandler.h: ../SaxObjC/SaxContentHandler.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: ../SaxObjC/SaxAttributes.h: ../SaxObjC/SaxAttributeList.h: ../SaxObjC/SaxLocator.h: ../SaxObjC/SaxErrorHandler.h: /usr/include/GNUstep/Foundation/NSMapTable.h: /usr/include/GNUstep/Foundation/NSArray.h: common.h: /usr/include/GNUstep/Foundation/Foundation.h: /usr/include/GNUstep/Foundation/FoundationErrors.h: /usr/include/GNUstep/Foundation/NSDebug.h: /usr/include/GNUstep/Foundation/NSProcessInfo.h: /usr/include/GNUstep/Foundation/NSAffineTransform.h: /usr/include/GNUstep/Foundation/NSGeometry.h: /usr/include/GNUstep/Foundation/NSArchiver.h: /usr/include/GNUstep/Foundation/NSCoder.h: /usr/include/GNUstep/Foundation/NSAttributedString.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/GNUstep/Foundation/NSAutoreleasePool.h: /usr/include/GNUstep/Foundation/NSBundle.h: /usr/include/GNUstep/Foundation/NSByteOrder.h: /usr/include/GNUstep/Foundation/NSCalendarDate.h: /usr/include/GNUstep/Foundation/NSCharacterSet.h: /usr/include/GNUstep/Foundation/NSClassDescription.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/Foundation/NSComparisonPredicate.h: /usr/include/GNUstep/Foundation/NSExpression.h: /usr/include/GNUstep/Foundation/NSPredicate.h: /usr/include/GNUstep/Foundation/NSCompoundPredicate.h: /usr/include/GNUstep/Foundation/NSConnection.h: /usr/include/GNUstep/Foundation/NSTimer.h: /usr/include/GNUstep/Foundation/NSRunLoop.h: /usr/include/GNUstep/Foundation/NSData.h: /usr/include/GNUstep/Foundation/NSSerialization.h: /usr/include/GNUstep/Foundation/NSDateFormatter.h: /usr/include/GNUstep/Foundation/NSFormatter.h: /usr/include/GNUstep/Foundation/NSDecimalNumber.h: /usr/include/GNUstep/Foundation/NSDecimal.h: /usr/include/GNUstep/Foundation/NSValue.h: /usr/include/GNUstep/Foundation/NSDistantObject.h: /usr/include/GNUstep/Foundation/NSProxy.h: /usr/include/GNUstep/Foundation/NSDistributedLock.h: /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h: /usr/include/GNUstep/Foundation/NSLock.h: /usr/include/GNUstep/Foundation/NSNotification.h: /usr/include/GNUstep/Foundation/NSEnumerator.h: /usr/include/GNUstep/Foundation/NSError.h: /usr/include/GNUstep/Foundation/NSFileHandle.h: /usr/include/GNUstep/Foundation/NSFileManager.h: /usr/include/GNUstep/Foundation/NSHashTable.h: /usr/include/GNUstep/Foundation/NSHost.h: /usr/include/GNUstep/Foundation/NSHTTPCookie.h: /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h: /usr/include/GNUstep/Foundation/NSIndexPath.h: /usr/include/GNUstep/Foundation/NSIndexSet.h: /usr/include/GNUstep/Foundation/NSInvocation.h: /usr/include/GNUstep/Foundation/NSMethodSignature.h: /usr/include/GNUstep/Foundation/NSKeyedArchiver.h: /usr/include/GNUstep/Foundation/NSPropertyList.h: /usr/include/GNUstep/Foundation/NSKeyValueCoding.h: /usr/include/GNUstep/Foundation/NSNotificationQueue.h: /usr/include/GNUstep/Foundation/NSNetServices.h: /usr/include/GNUstep/Foundation/NSNull.h: /usr/include/GNUstep/Foundation/NSNumberFormatter.h: /usr/include/GNUstep/Foundation/NSPathUtilities.h: /usr/include/GNUstep/Foundation/NSPortCoder.h: /usr/include/GNUstep/Foundation/NSPortMessage.h: /usr/include/GNUstep/Foundation/NSPort.h: /usr/include/GNUstep/Foundation/NSPortNameServer.h: /usr/include/GNUstep/Foundation/NSProtocolChecker.h: /usr/include/GNUstep/Foundation/NSScanner.h: /usr/include/GNUstep/Foundation/NSSet.h: /usr/include/GNUstep/Foundation/NSSortDescriptor.h: /usr/include/GNUstep/Foundation/NSSpellServer.h: /usr/include/GNUstep/Foundation/NSStream.h: /usr/include/GNUstep/Foundation/NSTask.h: /usr/include/GNUstep/Foundation/NSThread.h: /usr/include/GNUstep/Foundation/NSTimeZone.h: /usr/include/GNUstep/Foundation/NSUndoManager.h: /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h: /usr/include/GNUstep/Foundation/NSURLCache.h: /usr/include/GNUstep/Foundation/NSURLConnection.h: /usr/include/GNUstep/Foundation/NSURLCredential.h: /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h: /usr/include/GNUstep/Foundation/NSURLDownload.h: /usr/include/GNUstep/Foundation/NSURLError.h: /usr/include/GNUstep/Foundation/NSURL.h: /usr/include/GNUstep/Foundation/NSURLHandle.h: /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h: /usr/include/GNUstep/Foundation/NSURLProtocol.h: /usr/include/GNUstep/Foundation/NSURLRequest.h: /usr/include/GNUstep/Foundation/NSURLResponse.h: /usr/include/GNUstep/Foundation/NSUserDefaults.h: /usr/include/GNUstep/Foundation/NSValueTransformer.h: /usr/include/GNUstep/Foundation/NSXMLParser.h: SOPE/sope-xml/SaxObjC/shared_debug_obj/SaxXMLFilter.d0000644000000000000000000002521515004363604021262 0ustar rootrootobj/SaxXMLFilter.o: SaxXMLFilter.m SaxXMLFilter.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h ../SaxObjC/SaxXMLReader.h \ ../SaxObjC/SaxContentHandler.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h ../SaxObjC/SaxAttributes.h \ ../SaxObjC/SaxAttributeList.h ../SaxObjC/SaxLocator.h \ ../SaxObjC/SaxDTDHandler.h ../SaxObjC/SaxErrorHandler.h \ ../SaxObjC/SaxEntityResolver.h SaxEntityResolver.h SaxDTDHandler.h \ SaxContentHandler.h SaxErrorHandler.h common.h \ /usr/include/GNUstep/Foundation/Foundation.h \ /usr/include/GNUstep/Foundation/FoundationErrors.h \ /usr/include/GNUstep/Foundation/NSDebug.h \ /usr/include/GNUstep/Foundation/NSProcessInfo.h \ /usr/include/GNUstep/Foundation/NSAffineTransform.h \ /usr/include/GNUstep/Foundation/NSGeometry.h \ /usr/include/GNUstep/Foundation/NSArchiver.h \ /usr/include/GNUstep/Foundation/NSCoder.h \ /usr/include/GNUstep/Foundation/NSArray.h \ /usr/include/GNUstep/Foundation/NSAttributedString.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/GNUstep/Foundation/NSAutoreleasePool.h \ /usr/include/GNUstep/Foundation/NSBundle.h \ /usr/include/GNUstep/Foundation/NSByteOrder.h \ /usr/include/GNUstep/Foundation/NSCalendarDate.h \ /usr/include/GNUstep/Foundation/NSCharacterSet.h \ /usr/include/GNUstep/Foundation/NSClassDescription.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/Foundation/NSComparisonPredicate.h \ /usr/include/GNUstep/Foundation/NSExpression.h \ /usr/include/GNUstep/Foundation/NSPredicate.h \ /usr/include/GNUstep/Foundation/NSCompoundPredicate.h \ /usr/include/GNUstep/Foundation/NSConnection.h \ /usr/include/GNUstep/Foundation/NSTimer.h \ /usr/include/GNUstep/Foundation/NSRunLoop.h \ /usr/include/GNUstep/Foundation/NSMapTable.h \ /usr/include/GNUstep/Foundation/NSData.h \ /usr/include/GNUstep/Foundation/NSSerialization.h \ /usr/include/GNUstep/Foundation/NSDateFormatter.h \ /usr/include/GNUstep/Foundation/NSFormatter.h \ /usr/include/GNUstep/Foundation/NSDecimalNumber.h \ /usr/include/GNUstep/Foundation/NSDecimal.h \ /usr/include/GNUstep/Foundation/NSValue.h \ /usr/include/GNUstep/Foundation/NSDistantObject.h \ /usr/include/GNUstep/Foundation/NSProxy.h \ /usr/include/GNUstep/Foundation/NSDistributedLock.h \ /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h \ /usr/include/GNUstep/Foundation/NSLock.h \ /usr/include/GNUstep/Foundation/NSNotification.h \ /usr/include/GNUstep/Foundation/NSEnumerator.h \ /usr/include/GNUstep/Foundation/NSError.h \ /usr/include/GNUstep/Foundation/NSFileHandle.h \ /usr/include/GNUstep/Foundation/NSFileManager.h \ /usr/include/GNUstep/Foundation/NSHashTable.h \ /usr/include/GNUstep/Foundation/NSHost.h \ /usr/include/GNUstep/Foundation/NSHTTPCookie.h \ /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h \ /usr/include/GNUstep/Foundation/NSIndexPath.h \ /usr/include/GNUstep/Foundation/NSIndexSet.h \ /usr/include/GNUstep/Foundation/NSInvocation.h \ /usr/include/GNUstep/Foundation/NSMethodSignature.h \ /usr/include/GNUstep/Foundation/NSKeyedArchiver.h \ /usr/include/GNUstep/Foundation/NSPropertyList.h \ /usr/include/GNUstep/Foundation/NSKeyValueCoding.h \ /usr/include/GNUstep/Foundation/NSNotificationQueue.h \ /usr/include/GNUstep/Foundation/NSNetServices.h \ /usr/include/GNUstep/Foundation/NSNull.h \ /usr/include/GNUstep/Foundation/NSNumberFormatter.h \ /usr/include/GNUstep/Foundation/NSPathUtilities.h \ /usr/include/GNUstep/Foundation/NSPortCoder.h \ /usr/include/GNUstep/Foundation/NSPortMessage.h \ /usr/include/GNUstep/Foundation/NSPort.h \ /usr/include/GNUstep/Foundation/NSPortNameServer.h \ /usr/include/GNUstep/Foundation/NSProtocolChecker.h \ /usr/include/GNUstep/Foundation/NSScanner.h \ /usr/include/GNUstep/Foundation/NSSet.h \ /usr/include/GNUstep/Foundation/NSSortDescriptor.h \ /usr/include/GNUstep/Foundation/NSSpellServer.h \ /usr/include/GNUstep/Foundation/NSStream.h \ /usr/include/GNUstep/Foundation/NSTask.h \ /usr/include/GNUstep/Foundation/NSThread.h \ /usr/include/GNUstep/Foundation/NSTimeZone.h \ /usr/include/GNUstep/Foundation/NSUndoManager.h \ /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h \ /usr/include/GNUstep/Foundation/NSURLCache.h \ /usr/include/GNUstep/Foundation/NSURLConnection.h \ /usr/include/GNUstep/Foundation/NSURLCredential.h \ /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h \ /usr/include/GNUstep/Foundation/NSURLDownload.h \ /usr/include/GNUstep/Foundation/NSURLError.h \ /usr/include/GNUstep/Foundation/NSURL.h \ /usr/include/GNUstep/Foundation/NSURLHandle.h \ /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h \ /usr/include/GNUstep/Foundation/NSURLProtocol.h \ /usr/include/GNUstep/Foundation/NSURLRequest.h \ /usr/include/GNUstep/Foundation/NSURLResponse.h \ /usr/include/GNUstep/Foundation/NSUserDefaults.h \ /usr/include/GNUstep/Foundation/NSValueTransformer.h \ /usr/include/GNUstep/Foundation/NSXMLParser.h SaxXMLFilter.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: ../SaxObjC/SaxXMLReader.h: ../SaxObjC/SaxContentHandler.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: ../SaxObjC/SaxAttributes.h: ../SaxObjC/SaxAttributeList.h: ../SaxObjC/SaxLocator.h: ../SaxObjC/SaxDTDHandler.h: ../SaxObjC/SaxErrorHandler.h: ../SaxObjC/SaxEntityResolver.h: SaxEntityResolver.h: SaxDTDHandler.h: SaxContentHandler.h: SaxErrorHandler.h: common.h: /usr/include/GNUstep/Foundation/Foundation.h: /usr/include/GNUstep/Foundation/FoundationErrors.h: /usr/include/GNUstep/Foundation/NSDebug.h: /usr/include/GNUstep/Foundation/NSProcessInfo.h: /usr/include/GNUstep/Foundation/NSAffineTransform.h: /usr/include/GNUstep/Foundation/NSGeometry.h: /usr/include/GNUstep/Foundation/NSArchiver.h: /usr/include/GNUstep/Foundation/NSCoder.h: /usr/include/GNUstep/Foundation/NSArray.h: /usr/include/GNUstep/Foundation/NSAttributedString.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/GNUstep/Foundation/NSAutoreleasePool.h: /usr/include/GNUstep/Foundation/NSBundle.h: /usr/include/GNUstep/Foundation/NSByteOrder.h: /usr/include/GNUstep/Foundation/NSCalendarDate.h: /usr/include/GNUstep/Foundation/NSCharacterSet.h: /usr/include/GNUstep/Foundation/NSClassDescription.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/Foundation/NSComparisonPredicate.h: /usr/include/GNUstep/Foundation/NSExpression.h: /usr/include/GNUstep/Foundation/NSPredicate.h: /usr/include/GNUstep/Foundation/NSCompoundPredicate.h: /usr/include/GNUstep/Foundation/NSConnection.h: /usr/include/GNUstep/Foundation/NSTimer.h: /usr/include/GNUstep/Foundation/NSRunLoop.h: /usr/include/GNUstep/Foundation/NSMapTable.h: /usr/include/GNUstep/Foundation/NSData.h: /usr/include/GNUstep/Foundation/NSSerialization.h: /usr/include/GNUstep/Foundation/NSDateFormatter.h: /usr/include/GNUstep/Foundation/NSFormatter.h: /usr/include/GNUstep/Foundation/NSDecimalNumber.h: /usr/include/GNUstep/Foundation/NSDecimal.h: /usr/include/GNUstep/Foundation/NSValue.h: /usr/include/GNUstep/Foundation/NSDistantObject.h: /usr/include/GNUstep/Foundation/NSProxy.h: /usr/include/GNUstep/Foundation/NSDistributedLock.h: /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h: /usr/include/GNUstep/Foundation/NSLock.h: /usr/include/GNUstep/Foundation/NSNotification.h: /usr/include/GNUstep/Foundation/NSEnumerator.h: /usr/include/GNUstep/Foundation/NSError.h: /usr/include/GNUstep/Foundation/NSFileHandle.h: /usr/include/GNUstep/Foundation/NSFileManager.h: /usr/include/GNUstep/Foundation/NSHashTable.h: /usr/include/GNUstep/Foundation/NSHost.h: /usr/include/GNUstep/Foundation/NSHTTPCookie.h: /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h: /usr/include/GNUstep/Foundation/NSIndexPath.h: /usr/include/GNUstep/Foundation/NSIndexSet.h: /usr/include/GNUstep/Foundation/NSInvocation.h: /usr/include/GNUstep/Foundation/NSMethodSignature.h: /usr/include/GNUstep/Foundation/NSKeyedArchiver.h: /usr/include/GNUstep/Foundation/NSPropertyList.h: /usr/include/GNUstep/Foundation/NSKeyValueCoding.h: /usr/include/GNUstep/Foundation/NSNotificationQueue.h: /usr/include/GNUstep/Foundation/NSNetServices.h: /usr/include/GNUstep/Foundation/NSNull.h: /usr/include/GNUstep/Foundation/NSNumberFormatter.h: /usr/include/GNUstep/Foundation/NSPathUtilities.h: /usr/include/GNUstep/Foundation/NSPortCoder.h: /usr/include/GNUstep/Foundation/NSPortMessage.h: /usr/include/GNUstep/Foundation/NSPort.h: /usr/include/GNUstep/Foundation/NSPortNameServer.h: /usr/include/GNUstep/Foundation/NSProtocolChecker.h: /usr/include/GNUstep/Foundation/NSScanner.h: /usr/include/GNUstep/Foundation/NSSet.h: /usr/include/GNUstep/Foundation/NSSortDescriptor.h: /usr/include/GNUstep/Foundation/NSSpellServer.h: /usr/include/GNUstep/Foundation/NSStream.h: /usr/include/GNUstep/Foundation/NSTask.h: /usr/include/GNUstep/Foundation/NSThread.h: /usr/include/GNUstep/Foundation/NSTimeZone.h: /usr/include/GNUstep/Foundation/NSUndoManager.h: /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h: /usr/include/GNUstep/Foundation/NSURLCache.h: /usr/include/GNUstep/Foundation/NSURLConnection.h: /usr/include/GNUstep/Foundation/NSURLCredential.h: /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h: /usr/include/GNUstep/Foundation/NSURLDownload.h: /usr/include/GNUstep/Foundation/NSURLError.h: /usr/include/GNUstep/Foundation/NSURL.h: /usr/include/GNUstep/Foundation/NSURLHandle.h: /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h: /usr/include/GNUstep/Foundation/NSURLProtocol.h: /usr/include/GNUstep/Foundation/NSURLRequest.h: /usr/include/GNUstep/Foundation/NSURLResponse.h: /usr/include/GNUstep/Foundation/NSUserDefaults.h: /usr/include/GNUstep/Foundation/NSValueTransformer.h: /usr/include/GNUstep/Foundation/NSXMLParser.h: SOPE/sope-xml/SaxObjC/shared_debug_obj/SaxHandlerBase.d0000644000000000000000000000336115004363604021622 0ustar rootrootobj/SaxHandlerBase.o: SaxHandlerBase.m SaxHandlerBase.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h ../SaxObjC/SaxEntityResolver.h \ ../SaxObjC/SaxDTDHandler.h ../SaxObjC/SaxDocumentHandler.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h ../SaxObjC/SaxAttributeList.h \ ../SaxObjC/SaxAttributes.h ../SaxObjC/SaxLocator.h \ ../SaxObjC/SaxErrorHandler.h SaxException.h \ /usr/include/GNUstep/Foundation/NSException.h SaxHandlerBase.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: ../SaxObjC/SaxEntityResolver.h: ../SaxObjC/SaxDTDHandler.h: ../SaxObjC/SaxDocumentHandler.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: ../SaxObjC/SaxAttributeList.h: ../SaxObjC/SaxAttributes.h: ../SaxObjC/SaxLocator.h: ../SaxObjC/SaxErrorHandler.h: SaxException.h: /usr/include/GNUstep/Foundation/NSException.h: SOPE/sope-xml/SaxObjC/shared_debug_obj/SaxLocator.d0000644000000000000000000002400315004363604021051 0ustar rootrootobj/SaxLocator.o: SaxLocator.m SaxLocator.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h common.h \ /usr/include/GNUstep/Foundation/Foundation.h \ /usr/include/GNUstep/Foundation/FoundationErrors.h \ /usr/include/GNUstep/Foundation/NSDebug.h \ /usr/include/GNUstep/Foundation/NSProcessInfo.h \ /usr/include/GNUstep/Foundation/NSAffineTransform.h \ /usr/include/GNUstep/Foundation/NSGeometry.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h \ /usr/include/GNUstep/Foundation/NSArchiver.h \ /usr/include/GNUstep/Foundation/NSCoder.h \ /usr/include/GNUstep/Foundation/NSArray.h \ /usr/include/GNUstep/Foundation/NSAttributedString.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/GNUstep/Foundation/NSAutoreleasePool.h \ /usr/include/GNUstep/Foundation/NSBundle.h \ /usr/include/GNUstep/Foundation/NSByteOrder.h \ /usr/include/GNUstep/Foundation/NSCalendarDate.h \ /usr/include/GNUstep/Foundation/NSCharacterSet.h \ /usr/include/GNUstep/Foundation/NSClassDescription.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/Foundation/NSComparisonPredicate.h \ /usr/include/GNUstep/Foundation/NSExpression.h \ /usr/include/GNUstep/Foundation/NSPredicate.h \ /usr/include/GNUstep/Foundation/NSCompoundPredicate.h \ /usr/include/GNUstep/Foundation/NSConnection.h \ /usr/include/GNUstep/Foundation/NSTimer.h \ /usr/include/GNUstep/Foundation/NSRunLoop.h \ /usr/include/GNUstep/Foundation/NSMapTable.h \ /usr/include/GNUstep/Foundation/NSData.h \ /usr/include/GNUstep/Foundation/NSSerialization.h \ /usr/include/GNUstep/Foundation/NSDateFormatter.h \ /usr/include/GNUstep/Foundation/NSFormatter.h \ /usr/include/GNUstep/Foundation/NSDecimalNumber.h \ /usr/include/GNUstep/Foundation/NSDecimal.h \ /usr/include/GNUstep/Foundation/NSValue.h \ /usr/include/GNUstep/Foundation/NSDistantObject.h \ /usr/include/GNUstep/Foundation/NSProxy.h \ /usr/include/GNUstep/Foundation/NSDistributedLock.h \ /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h \ /usr/include/GNUstep/Foundation/NSLock.h \ /usr/include/GNUstep/Foundation/NSNotification.h \ /usr/include/GNUstep/Foundation/NSEnumerator.h \ /usr/include/GNUstep/Foundation/NSError.h \ /usr/include/GNUstep/Foundation/NSFileHandle.h \ /usr/include/GNUstep/Foundation/NSFileManager.h \ /usr/include/GNUstep/Foundation/NSHashTable.h \ /usr/include/GNUstep/Foundation/NSHost.h \ /usr/include/GNUstep/Foundation/NSHTTPCookie.h \ /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h \ /usr/include/GNUstep/Foundation/NSIndexPath.h \ /usr/include/GNUstep/Foundation/NSIndexSet.h \ /usr/include/GNUstep/Foundation/NSInvocation.h \ /usr/include/GNUstep/Foundation/NSMethodSignature.h \ /usr/include/GNUstep/Foundation/NSKeyedArchiver.h \ /usr/include/GNUstep/Foundation/NSPropertyList.h \ /usr/include/GNUstep/Foundation/NSKeyValueCoding.h \ /usr/include/GNUstep/Foundation/NSNotificationQueue.h \ /usr/include/GNUstep/Foundation/NSNetServices.h \ /usr/include/GNUstep/Foundation/NSNull.h \ /usr/include/GNUstep/Foundation/NSNumberFormatter.h \ /usr/include/GNUstep/Foundation/NSPathUtilities.h \ /usr/include/GNUstep/Foundation/NSPortCoder.h \ /usr/include/GNUstep/Foundation/NSPortMessage.h \ /usr/include/GNUstep/Foundation/NSPort.h \ /usr/include/GNUstep/Foundation/NSPortNameServer.h \ /usr/include/GNUstep/Foundation/NSProtocolChecker.h \ /usr/include/GNUstep/Foundation/NSScanner.h \ /usr/include/GNUstep/Foundation/NSSet.h \ /usr/include/GNUstep/Foundation/NSSortDescriptor.h \ /usr/include/GNUstep/Foundation/NSSpellServer.h \ /usr/include/GNUstep/Foundation/NSStream.h \ /usr/include/GNUstep/Foundation/NSTask.h \ /usr/include/GNUstep/Foundation/NSThread.h \ /usr/include/GNUstep/Foundation/NSTimeZone.h \ /usr/include/GNUstep/Foundation/NSUndoManager.h \ /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h \ /usr/include/GNUstep/Foundation/NSURLCache.h \ /usr/include/GNUstep/Foundation/NSURLConnection.h \ /usr/include/GNUstep/Foundation/NSURLCredential.h \ /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h \ /usr/include/GNUstep/Foundation/NSURLDownload.h \ /usr/include/GNUstep/Foundation/NSURLError.h \ /usr/include/GNUstep/Foundation/NSURL.h \ /usr/include/GNUstep/Foundation/NSURLHandle.h \ /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h \ /usr/include/GNUstep/Foundation/NSURLProtocol.h \ /usr/include/GNUstep/Foundation/NSURLRequest.h \ /usr/include/GNUstep/Foundation/NSURLResponse.h \ /usr/include/GNUstep/Foundation/NSUserDefaults.h \ /usr/include/GNUstep/Foundation/NSValueTransformer.h \ /usr/include/GNUstep/Foundation/NSXMLParser.h SaxLocator.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: common.h: /usr/include/GNUstep/Foundation/Foundation.h: /usr/include/GNUstep/Foundation/FoundationErrors.h: /usr/include/GNUstep/Foundation/NSDebug.h: /usr/include/GNUstep/Foundation/NSProcessInfo.h: /usr/include/GNUstep/Foundation/NSAffineTransform.h: /usr/include/GNUstep/Foundation/NSGeometry.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: /usr/include/GNUstep/Foundation/NSArchiver.h: /usr/include/GNUstep/Foundation/NSCoder.h: /usr/include/GNUstep/Foundation/NSArray.h: /usr/include/GNUstep/Foundation/NSAttributedString.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/GNUstep/Foundation/NSAutoreleasePool.h: /usr/include/GNUstep/Foundation/NSBundle.h: /usr/include/GNUstep/Foundation/NSByteOrder.h: /usr/include/GNUstep/Foundation/NSCalendarDate.h: /usr/include/GNUstep/Foundation/NSCharacterSet.h: /usr/include/GNUstep/Foundation/NSClassDescription.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/Foundation/NSComparisonPredicate.h: /usr/include/GNUstep/Foundation/NSExpression.h: /usr/include/GNUstep/Foundation/NSPredicate.h: /usr/include/GNUstep/Foundation/NSCompoundPredicate.h: /usr/include/GNUstep/Foundation/NSConnection.h: /usr/include/GNUstep/Foundation/NSTimer.h: /usr/include/GNUstep/Foundation/NSRunLoop.h: /usr/include/GNUstep/Foundation/NSMapTable.h: /usr/include/GNUstep/Foundation/NSData.h: /usr/include/GNUstep/Foundation/NSSerialization.h: /usr/include/GNUstep/Foundation/NSDateFormatter.h: /usr/include/GNUstep/Foundation/NSFormatter.h: /usr/include/GNUstep/Foundation/NSDecimalNumber.h: /usr/include/GNUstep/Foundation/NSDecimal.h: /usr/include/GNUstep/Foundation/NSValue.h: /usr/include/GNUstep/Foundation/NSDistantObject.h: /usr/include/GNUstep/Foundation/NSProxy.h: /usr/include/GNUstep/Foundation/NSDistributedLock.h: /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h: /usr/include/GNUstep/Foundation/NSLock.h: /usr/include/GNUstep/Foundation/NSNotification.h: /usr/include/GNUstep/Foundation/NSEnumerator.h: /usr/include/GNUstep/Foundation/NSError.h: /usr/include/GNUstep/Foundation/NSFileHandle.h: /usr/include/GNUstep/Foundation/NSFileManager.h: /usr/include/GNUstep/Foundation/NSHashTable.h: /usr/include/GNUstep/Foundation/NSHost.h: /usr/include/GNUstep/Foundation/NSHTTPCookie.h: /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h: /usr/include/GNUstep/Foundation/NSIndexPath.h: /usr/include/GNUstep/Foundation/NSIndexSet.h: /usr/include/GNUstep/Foundation/NSInvocation.h: /usr/include/GNUstep/Foundation/NSMethodSignature.h: /usr/include/GNUstep/Foundation/NSKeyedArchiver.h: /usr/include/GNUstep/Foundation/NSPropertyList.h: /usr/include/GNUstep/Foundation/NSKeyValueCoding.h: /usr/include/GNUstep/Foundation/NSNotificationQueue.h: /usr/include/GNUstep/Foundation/NSNetServices.h: /usr/include/GNUstep/Foundation/NSNull.h: /usr/include/GNUstep/Foundation/NSNumberFormatter.h: /usr/include/GNUstep/Foundation/NSPathUtilities.h: /usr/include/GNUstep/Foundation/NSPortCoder.h: /usr/include/GNUstep/Foundation/NSPortMessage.h: /usr/include/GNUstep/Foundation/NSPort.h: /usr/include/GNUstep/Foundation/NSPortNameServer.h: /usr/include/GNUstep/Foundation/NSProtocolChecker.h: /usr/include/GNUstep/Foundation/NSScanner.h: /usr/include/GNUstep/Foundation/NSSet.h: /usr/include/GNUstep/Foundation/NSSortDescriptor.h: /usr/include/GNUstep/Foundation/NSSpellServer.h: /usr/include/GNUstep/Foundation/NSStream.h: /usr/include/GNUstep/Foundation/NSTask.h: /usr/include/GNUstep/Foundation/NSThread.h: /usr/include/GNUstep/Foundation/NSTimeZone.h: /usr/include/GNUstep/Foundation/NSUndoManager.h: /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h: /usr/include/GNUstep/Foundation/NSURLCache.h: /usr/include/GNUstep/Foundation/NSURLConnection.h: /usr/include/GNUstep/Foundation/NSURLCredential.h: /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h: /usr/include/GNUstep/Foundation/NSURLDownload.h: /usr/include/GNUstep/Foundation/NSURLError.h: /usr/include/GNUstep/Foundation/NSURL.h: /usr/include/GNUstep/Foundation/NSURLHandle.h: /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h: /usr/include/GNUstep/Foundation/NSURLProtocol.h: /usr/include/GNUstep/Foundation/NSURLRequest.h: /usr/include/GNUstep/Foundation/NSURLResponse.h: /usr/include/GNUstep/Foundation/NSUserDefaults.h: /usr/include/GNUstep/Foundation/NSValueTransformer.h: /usr/include/GNUstep/Foundation/NSXMLParser.h: SOPE/sope-xml/SaxObjC/shared_debug_obj/SaxAttributeList.d0000644000000000000000000002426715004363604022261 0ustar rootrootobj/SaxAttributeList.o: SaxAttributeList.m SaxAttributeList.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h ../SaxObjC/SaxAttributes.h \ ../SaxObjC/SaxAttributeList.h SaxAttributes.h common.h \ /usr/include/GNUstep/Foundation/Foundation.h \ /usr/include/GNUstep/Foundation/FoundationErrors.h \ /usr/include/GNUstep/Foundation/NSDebug.h \ /usr/include/GNUstep/Foundation/NSProcessInfo.h \ /usr/include/GNUstep/Foundation/NSAffineTransform.h \ /usr/include/GNUstep/Foundation/NSGeometry.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h \ /usr/include/GNUstep/Foundation/NSArchiver.h \ /usr/include/GNUstep/Foundation/NSCoder.h \ /usr/include/GNUstep/Foundation/NSArray.h \ /usr/include/GNUstep/Foundation/NSAttributedString.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/GNUstep/Foundation/NSAutoreleasePool.h \ /usr/include/GNUstep/Foundation/NSBundle.h \ /usr/include/GNUstep/Foundation/NSByteOrder.h \ /usr/include/GNUstep/Foundation/NSCalendarDate.h \ /usr/include/GNUstep/Foundation/NSCharacterSet.h \ /usr/include/GNUstep/Foundation/NSClassDescription.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/Foundation/NSComparisonPredicate.h \ /usr/include/GNUstep/Foundation/NSExpression.h \ /usr/include/GNUstep/Foundation/NSPredicate.h \ /usr/include/GNUstep/Foundation/NSCompoundPredicate.h \ /usr/include/GNUstep/Foundation/NSConnection.h \ /usr/include/GNUstep/Foundation/NSTimer.h \ /usr/include/GNUstep/Foundation/NSRunLoop.h \ /usr/include/GNUstep/Foundation/NSMapTable.h \ /usr/include/GNUstep/Foundation/NSData.h \ /usr/include/GNUstep/Foundation/NSSerialization.h \ /usr/include/GNUstep/Foundation/NSDateFormatter.h \ /usr/include/GNUstep/Foundation/NSFormatter.h \ /usr/include/GNUstep/Foundation/NSDecimalNumber.h \ /usr/include/GNUstep/Foundation/NSDecimal.h \ /usr/include/GNUstep/Foundation/NSValue.h \ /usr/include/GNUstep/Foundation/NSDistantObject.h \ /usr/include/GNUstep/Foundation/NSProxy.h \ /usr/include/GNUstep/Foundation/NSDistributedLock.h \ /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h \ /usr/include/GNUstep/Foundation/NSLock.h \ /usr/include/GNUstep/Foundation/NSNotification.h \ /usr/include/GNUstep/Foundation/NSEnumerator.h \ /usr/include/GNUstep/Foundation/NSError.h \ /usr/include/GNUstep/Foundation/NSFileHandle.h \ /usr/include/GNUstep/Foundation/NSFileManager.h \ /usr/include/GNUstep/Foundation/NSHashTable.h \ /usr/include/GNUstep/Foundation/NSHost.h \ /usr/include/GNUstep/Foundation/NSHTTPCookie.h \ /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h \ /usr/include/GNUstep/Foundation/NSIndexPath.h \ /usr/include/GNUstep/Foundation/NSIndexSet.h \ /usr/include/GNUstep/Foundation/NSInvocation.h \ /usr/include/GNUstep/Foundation/NSMethodSignature.h \ /usr/include/GNUstep/Foundation/NSKeyedArchiver.h \ /usr/include/GNUstep/Foundation/NSPropertyList.h \ /usr/include/GNUstep/Foundation/NSKeyValueCoding.h \ /usr/include/GNUstep/Foundation/NSNotificationQueue.h \ /usr/include/GNUstep/Foundation/NSNetServices.h \ /usr/include/GNUstep/Foundation/NSNull.h \ /usr/include/GNUstep/Foundation/NSNumberFormatter.h \ /usr/include/GNUstep/Foundation/NSPathUtilities.h \ /usr/include/GNUstep/Foundation/NSPortCoder.h \ /usr/include/GNUstep/Foundation/NSPortMessage.h \ /usr/include/GNUstep/Foundation/NSPort.h \ /usr/include/GNUstep/Foundation/NSPortNameServer.h \ /usr/include/GNUstep/Foundation/NSProtocolChecker.h \ /usr/include/GNUstep/Foundation/NSScanner.h \ /usr/include/GNUstep/Foundation/NSSet.h \ /usr/include/GNUstep/Foundation/NSSortDescriptor.h \ /usr/include/GNUstep/Foundation/NSSpellServer.h \ /usr/include/GNUstep/Foundation/NSStream.h \ /usr/include/GNUstep/Foundation/NSTask.h \ /usr/include/GNUstep/Foundation/NSThread.h \ /usr/include/GNUstep/Foundation/NSTimeZone.h \ /usr/include/GNUstep/Foundation/NSUndoManager.h \ /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h \ /usr/include/GNUstep/Foundation/NSURLCache.h \ /usr/include/GNUstep/Foundation/NSURLConnection.h \ /usr/include/GNUstep/Foundation/NSURLCredential.h \ /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h \ /usr/include/GNUstep/Foundation/NSURLDownload.h \ /usr/include/GNUstep/Foundation/NSURLError.h \ /usr/include/GNUstep/Foundation/NSURL.h \ /usr/include/GNUstep/Foundation/NSURLHandle.h \ /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h \ /usr/include/GNUstep/Foundation/NSURLProtocol.h \ /usr/include/GNUstep/Foundation/NSURLRequest.h \ /usr/include/GNUstep/Foundation/NSURLResponse.h \ /usr/include/GNUstep/Foundation/NSUserDefaults.h \ /usr/include/GNUstep/Foundation/NSValueTransformer.h \ /usr/include/GNUstep/Foundation/NSXMLParser.h SaxAttributeList.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: ../SaxObjC/SaxAttributes.h: ../SaxObjC/SaxAttributeList.h: SaxAttributes.h: common.h: /usr/include/GNUstep/Foundation/Foundation.h: /usr/include/GNUstep/Foundation/FoundationErrors.h: /usr/include/GNUstep/Foundation/NSDebug.h: /usr/include/GNUstep/Foundation/NSProcessInfo.h: /usr/include/GNUstep/Foundation/NSAffineTransform.h: /usr/include/GNUstep/Foundation/NSGeometry.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: /usr/include/GNUstep/Foundation/NSArchiver.h: /usr/include/GNUstep/Foundation/NSCoder.h: /usr/include/GNUstep/Foundation/NSArray.h: /usr/include/GNUstep/Foundation/NSAttributedString.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/GNUstep/Foundation/NSAutoreleasePool.h: /usr/include/GNUstep/Foundation/NSBundle.h: /usr/include/GNUstep/Foundation/NSByteOrder.h: /usr/include/GNUstep/Foundation/NSCalendarDate.h: /usr/include/GNUstep/Foundation/NSCharacterSet.h: /usr/include/GNUstep/Foundation/NSClassDescription.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/Foundation/NSComparisonPredicate.h: /usr/include/GNUstep/Foundation/NSExpression.h: /usr/include/GNUstep/Foundation/NSPredicate.h: /usr/include/GNUstep/Foundation/NSCompoundPredicate.h: /usr/include/GNUstep/Foundation/NSConnection.h: /usr/include/GNUstep/Foundation/NSTimer.h: /usr/include/GNUstep/Foundation/NSRunLoop.h: /usr/include/GNUstep/Foundation/NSMapTable.h: /usr/include/GNUstep/Foundation/NSData.h: /usr/include/GNUstep/Foundation/NSSerialization.h: /usr/include/GNUstep/Foundation/NSDateFormatter.h: /usr/include/GNUstep/Foundation/NSFormatter.h: /usr/include/GNUstep/Foundation/NSDecimalNumber.h: /usr/include/GNUstep/Foundation/NSDecimal.h: /usr/include/GNUstep/Foundation/NSValue.h: /usr/include/GNUstep/Foundation/NSDistantObject.h: /usr/include/GNUstep/Foundation/NSProxy.h: /usr/include/GNUstep/Foundation/NSDistributedLock.h: /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h: /usr/include/GNUstep/Foundation/NSLock.h: /usr/include/GNUstep/Foundation/NSNotification.h: /usr/include/GNUstep/Foundation/NSEnumerator.h: /usr/include/GNUstep/Foundation/NSError.h: /usr/include/GNUstep/Foundation/NSFileHandle.h: /usr/include/GNUstep/Foundation/NSFileManager.h: /usr/include/GNUstep/Foundation/NSHashTable.h: /usr/include/GNUstep/Foundation/NSHost.h: /usr/include/GNUstep/Foundation/NSHTTPCookie.h: /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h: /usr/include/GNUstep/Foundation/NSIndexPath.h: /usr/include/GNUstep/Foundation/NSIndexSet.h: /usr/include/GNUstep/Foundation/NSInvocation.h: /usr/include/GNUstep/Foundation/NSMethodSignature.h: /usr/include/GNUstep/Foundation/NSKeyedArchiver.h: /usr/include/GNUstep/Foundation/NSPropertyList.h: /usr/include/GNUstep/Foundation/NSKeyValueCoding.h: /usr/include/GNUstep/Foundation/NSNotificationQueue.h: /usr/include/GNUstep/Foundation/NSNetServices.h: /usr/include/GNUstep/Foundation/NSNull.h: /usr/include/GNUstep/Foundation/NSNumberFormatter.h: /usr/include/GNUstep/Foundation/NSPathUtilities.h: /usr/include/GNUstep/Foundation/NSPortCoder.h: /usr/include/GNUstep/Foundation/NSPortMessage.h: /usr/include/GNUstep/Foundation/NSPort.h: /usr/include/GNUstep/Foundation/NSPortNameServer.h: /usr/include/GNUstep/Foundation/NSProtocolChecker.h: /usr/include/GNUstep/Foundation/NSScanner.h: /usr/include/GNUstep/Foundation/NSSet.h: /usr/include/GNUstep/Foundation/NSSortDescriptor.h: /usr/include/GNUstep/Foundation/NSSpellServer.h: /usr/include/GNUstep/Foundation/NSStream.h: /usr/include/GNUstep/Foundation/NSTask.h: /usr/include/GNUstep/Foundation/NSThread.h: /usr/include/GNUstep/Foundation/NSTimeZone.h: /usr/include/GNUstep/Foundation/NSUndoManager.h: /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h: /usr/include/GNUstep/Foundation/NSURLCache.h: /usr/include/GNUstep/Foundation/NSURLConnection.h: /usr/include/GNUstep/Foundation/NSURLCredential.h: /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h: /usr/include/GNUstep/Foundation/NSURLDownload.h: /usr/include/GNUstep/Foundation/NSURLError.h: /usr/include/GNUstep/Foundation/NSURL.h: /usr/include/GNUstep/Foundation/NSURLHandle.h: /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h: /usr/include/GNUstep/Foundation/NSURLProtocol.h: /usr/include/GNUstep/Foundation/NSURLRequest.h: /usr/include/GNUstep/Foundation/NSURLResponse.h: /usr/include/GNUstep/Foundation/NSUserDefaults.h: /usr/include/GNUstep/Foundation/NSValueTransformer.h: /usr/include/GNUstep/Foundation/NSXMLParser.h: SOPE/sope-xml/SaxObjC/shared_debug_obj/SaxException.d0000644000000000000000000000243715004363604021413 0ustar rootrootobj/SaxException.o: SaxException.m SaxException.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h \ /usr/include/GNUstep/Foundation/NSRange.h SaxException.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: /usr/include/GNUstep/Foundation/NSRange.h: SOPE/sope-xml/SaxObjC/TODO0000644000000000000000000000016515004363604014052 0ustar rootrootTODOs for SaxObjC ================= - find out whether SaxObjC is deprecated due to NSXMLParser (probably not ;-) SOPE/sope-xml/SaxObjC/SaxDocumentHandler.h0000644000000000000000000000307015004363604017261 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxDocumentHandler_H__ #define __SaxDocumentHandler_H__ #import #include #include /* deprecated in SAX 2.0beta (replaced by SaxXMLContentHandler) */ @protocol SaxDocumentHandler - (void)startDocument; - (void)endDocument; - (void)startElement:(NSString *)_tagName attributes:(id)_attrs; - (void)endElement:(NSString *)_tagName; /* CDATA */ - (void)characters:(unichar *)_chars length:(NSUInteger)_len; - (void)ignorableWhitespace:(unichar *)_chars length:(NSUInteger)_len; /* PIs */ - (void)processingInstruction:(NSString *)_pi data:(NSString *)_data; /* positioning info */ - (void)setDocumentLocator:(id)_locator; @end #endif /* __SaxDocumentHandler_H__ */ SOPE/sope-xml/SaxObjC/GNUmakefile.preamble0000644000000000000000000000350115004363604017217 0ustar rootroot# compilation settings include ./Version libSaxObjC_DLL_DEF = libSaxObjC.def libSaxObjC_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION) libSaxObjC_INSTALL_DIR=$(SOPE_SYSLIBDIR) libSaxObjC_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION) SaxObjC_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION) SaxObjC_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION) libSaxObjC_HEADER_FILES_DIR = . libSaxObjC_HEADER_FILES_INSTALL_DIR = /SaxObjC # framework support SaxObjC_HEADER_FILES = $(libSaxObjC_HEADER_FILES) SaxObjC_OBJC_FILES = $(libSaxObjC_OBJC_FILES) ADDITIONAL_CPPFLAGS += \ -O2 \ -Wall -DCOMPILE_FOR_GSTEP_MAKE=1 \ -DSOPE_MAJOR_VERSION=$(MAJOR_VERSION) \ -DSOPE_MINOR_VERSION=$(MINOR_VERSION) \ -DSOPE_SUBMINOR_VERSION=$(SUBMINOR_VERSION) ADDITIONAL_CPPFLAGS += -Wno-protocol ifeq ($(frameworks),yes) ADDITIONAL_CPPFLAGS += -DCOMPILE_AS_FRAMEWORK=1 ifeq ($(FOUNDATION_LIB),apple) ADDITIONAL_CPPFLAGS += -DCOCOA_Foundation_LIBRARY=1 endif endif saxxml_INCLUDE_DIRS += -I.. saxxml_LIB_DIRS += -L./$(GNUSTEP_OBJ_DIR) saxxml_TOOL_LIBS += -lSaxObjC xmln_INCLUDE_DIRS += -I.. xmln_LIB_DIRS += -L./$(GNUSTEP_OBJ_DIR) xmln_TOOL_LIBS += -lSaxObjC # Parameters for SaxDriver lookup ifneq ($(FHS_INSTALL_ROOT),) ADDITIONAL_CPPFLAGS += -DFHS_INSTALL_ROOT=\@\"$(FHS_INSTALL_ROOT)\" endif ifneq ($(CGS_LIBDIR_NAME),) ADDITIONAL_CPPFLAGS += -DCGS_LIBDIR_NAME=\@\"$(CGS_LIBDIR_NAME)\" endif # Apple ifeq ($(FOUNDATION_LIB),apple) libSaxObjC_PREBIND_ADDR="0xC0000000" libSaxObjC_LDFLAGS += -seg1addr $(libSaxObjC_PREBIND_ADDR) SaxObjC_LDFLAGS += -seg1addr $(libSaxObjC_PREBIND_ADDR) endif ifeq ($(FOUNDATION_LIB),nx) saxxml_LDFLAGS += -framework Foundation xmln_LDFLAGS += -framework Foundation endif libSaxObjC_LIBRARIES_DEPEND_UPON += $(BASE_LIBS) SOPE/sope-xml/SaxObjC/SaxDefaultHandler+NSXML.m0000644000000000000000000001246615004363604020002 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SaxDefaultHandler.h" #include "SaxException.h" @implementation SaxDefaultHandler(NSXML) static BOOL doDebug = NO; - (void)parserDidStartDocument:(id)_parser { if (doDebug) NSLog(@"parser: startdoc %@", _parser); [self startDocument]; } - (void)parserDidEndDocument:(id)_parser { if (doDebug) NSLog(@"parser: endoc %@", _parser); [self endDocument]; } - (id)_wrapAttributes:(NSDictionary *)_attrs { // TODO: implement .. return [[SaxAttributes alloc] initWithDictionary:_attrs]; } - (void)parser:(id)_parser didStartElement:(NSString *)_tag namespaceURI:(NSString *)_nsuri qualifiedName:(NSString *)_rawName attributes:(NSDictionary *)_attrs { id attrs; if ([_rawName length] == 0) _rawName = _tag; if (doDebug) NSLog(@"parser: start %@ raw %@ uri %@", _tag, _rawName, _nsuri); attrs = [self _wrapAttributes:_attrs]; [self startElement:_tag namespace:_nsuri rawName:_rawName attributes:attrs]; [attrs release]; } - (void)parser:(id)_parser didEndElement:(NSString *)_tag namespaceURI:(NSString *)_nsuri qualifiedName:(NSString *)_rawName { if ([_rawName length] == 0) _rawName = _tag; if (doDebug) NSLog(@"parser: end %@ raw %@ uri %@", _tag, _rawName, _nsuri); [self endElement:_tag namespace:_nsuri rawName:_rawName]; } - (void)parser:(id)_parser didStartMappingPrefix:(NSString *)_prefix toURI:(NSString *)_uri { [self startPrefixMapping:_prefix uri:_uri]; } - (void)parser:(id)_parser didEndMappingPrefix:(NSString *)_prefix { [self endPrefixMapping:_prefix]; } - (void)parser:(id)_parser foundCharacters:(NSString *)_string { /* Note: expensive ..., decompose string into chars */ NSUInteger len; unichar *buf = NULL; if ((len = [_string length]) > 0) { buf = calloc(len + 2, sizeof(unichar)); [_string getCharacters:buf]; } [self characters:buf length:len]; if (buf) free(buf); } - (void)parser:(id)_parser foundIgnorableWhitespace:(NSString *)_ws { /* Note: expensive ..., decompose string into chars */ NSUInteger len; unichar *buf = NULL; if ((len = [_ws length]) > 0) { buf = calloc(len + 2, sizeof(unichar)); [_ws getCharacters:buf]; } [self ignorableWhitespace:buf length:len]; if (buf) free(buf); } - (void)parser:(id)_parser foundCDATA:(NSData *)_data { /* TODO: what about that? */ NSLog(@"ERROR(%s): CDATA section ignored!", __PRETTY_FUNCTION__); } #if 0 /* TODO: implement */ - (void)parser:(id)_parser foundComment:(NSString *)comment { } #endif - (void)parser:(id)_parser foundProcessingInstructionWithTarget:(NSString *)_target data:(NSString *)_data { [self processingInstruction:_target data:_data]; } /* entity resolver */ - (NSData *)parser:(id)_parser resolveExternalEntityName:(NSString *)_name systemID:(NSString *)_sysId { return [self resolveEntityWithPublicId:_name systemId:_sysId]; } /* handle errors */ - (SaxParseException *)_wrapErrorIntoException:(NSError *)_error { // TODO: perform proper wrapping or conversion return (id)_error; } - (void)parser:(id)_parser parseErrorOccurred:(NSError *)_error { if (doDebug) NSLog(@"parser: error %@", _error); [self error:[self _wrapErrorIntoException:_error]]; } - (void)parser:(id)_parser validationErrorOccurred:(NSError *)_error { if (doDebug) NSLog(@"parser: validation error %@", _error); [self error:[self _wrapErrorIntoException:_error]]; } /* DTD processing */ - (void)parser:(id)_parser foundNotationDeclarationWithName:(NSString *)_name publicID:(NSString *)_pubId systemID:(NSString *)_sysId { [self notationDeclaration:_name publicId:_pubId systemId:_sysId]; } - (void)parser:(id)_parser foundUnparsedEntityDeclarationWithName:(NSString *)_name publicID:(NSString *)_pubId systemID:(NSString *)_sysId notationName:(NSString *)_notName { [self unparsedEntityDeclaration:_name publicId:_pubId systemId:_sysId notationName:_notName]; } #if 0 /* TODO: DTD processing ... */ - (void)parser:(id)_parser foundAttributeDeclarationWithName:(NSString *)attributeName forElement:(NSString *)_tag type:(NSString *)type defaultValue:(NSString *)defaultValue; - (void)parser:(id)_parser foundElementDeclarationWithName:(NSString *)_tag model:(NSString *)model; - (void)parser:(id)_parser foundInternalEntityDeclarationWithName:(NSString *)name value:(NSString *)value; - (void)parser:(id)_parser foundExternalEntityDeclarationWithName:(NSString *)name publicID:(NSString *)publicID systemID:(NSString *)systemID; #endif @end /* SaxDefaultHandler(NSXML) */ SOPE/sope-xml/SaxObjC/SaxHandlerBase.h0000644000000000000000000000232215004363604016354 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SaxHandlerBase_H__ #define __SaxHandlerBase_H__ #import #include #include #include #include /* deprecated in SAX 2.0beta */ @interface SaxHandlerBase : NSObject < SaxEntityResolver, SaxDTDHandler, SaxDocumentHandler, SaxErrorHandler > @end /* SaxHandlerBase */ #endif /* __SaxHandlerBase_H__ */ SOPE/sope-xml/Version0000644000000000000000000000037715004363604013446 0ustar rootroot# # This file is included by library makefiles to set the version information # of the executable. MAJOR_VERSION=4 MINOR_VERSION=9 # subminor versions are set in the Version files contained in the library path SOPE_MAJOR_VERSION=4 SOPE_MINOR_VERSION=9 SOPE/sope-xml/umbrella.make0000644000000000000000000000136715004363604014540 0ustar rootroot# build umbrella framework for this subproject ifeq ($(frameworks),yes) FRAMEWORK_NAME = sope-xml sope-xml_RESOURCE_FILES += Version sope-xml_C_FILES = dummy.c sope-xml_UMBRELLA_FRAMEWORKS = \ SaxObjC \ DOM \ XmlRpc sope-xml_PREBIND_ADDR = 0xC0FF0000 # generic (consolidate in gstep-make) $(FRAMEWORK_NAME)_LDFLAGS += \ $(foreach fwname,$($(FRAMEWORK_NAME)_UMBRELLA_FRAMEWORKS),\ -framework $(fwname)) \ $(foreach fwname,$($(FRAMEWORK_NAME)_UMBRELLA_FRAMEWORKS),\ -sub_umbrella $(fwname)) \ -headerpad_max_install_names \ -seg1addr $($(FRAMEWORK_NAME)_PREBIND_ADDR) # library/framework search pathes DEP_DIRS += SaxObjC DOM XmlRpc ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir)) endif SOPE/sope-xml/libxmlSAXDriver/0000755000000000000000000000000015004363604015106 5ustar rootrootSOPE/sope-xml/libxmlSAXDriver/bundle-info.plist0000644000000000000000000000100515004363604020361 0ustar rootroot{ requires = { bundleManagerVersion = 1; classes = ( { name = NSObject; } ); }; provides = { SAXDrivers = ( { name = libxmlSAXDriver; sourceTypes = ( "text/xml" ); }, { name = libxmlHTMLSAXDriver; sourceTypes = ( "text/html" ); }, ); classes = ( { name = libxmlSAXDriver; }, { name = libxmlDocSAXDriver; }, { name = libxmlHTMLSAXDriver; }, ); }; } SOPE/sope-xml/libxmlSAXDriver/GNUmakefile0000644000000000000000000000114715004363604017163 0ustar rootroot# GNUstep makefile include ../../config.make include $(GNUSTEP_MAKEFILES)/common.make include ../Version include ./Version BUNDLE_NAME = libxmlSAXDriver BUNDLE_EXTENSION = .sax BUNDLE_INSTALL_DIR = $(SOPE_SAXDRIVERS) libxmlSAXDriver_PCH_FILE = common.h libxmlSAXDriver_OBJC_FILES = \ libxmlSAXDriver.m \ libxmlHTMLSAXDriver.m \ libxmlDocSAXDriver.m \ libxmlSAXLocator.m \ TableCallbacks.m \ libxmlSAXDriver_RESOURCE_FILES = bundle-info.plist Version libxmlSAXDriver_LOCALIZED_RESOURCE_FILES = -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/bundle.make -include GNUmakefile.postamble SOPE/sope-xml/libxmlSAXDriver/libxmlDocSAXDriver.h0000644000000000000000000000306515004363604020730 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include /* recognized properties: http://xml.org/sax/properties/declaration-handler http://xml.org/sax/properties/lexical-handler http://www.skyrix.com/sax/properties/html-namespace */ @class libxmlSAXLocator; @interface libxmlDocSAXDriver : NSObject < SaxXMLReader > { id contentHandler; id dtdHandler; id errorHandler; id entityResolver; id lexicalHandler; id declHandler; unsigned depth; BOOL encodeEntities; libxmlSAXLocator *locator; /* libxml */ void *doc; void *ctxt; } @end SOPE/sope-xml/libxmlSAXDriver/ChangeLog0000644000000000000000000002320515004363604016662 0ustar rootroot2009-03-24 Wolfgang Sourdeau * libxmlHTMLSAXDriver.m: added a hack to allow the content-handler to specify the input charset (hh: this hack should be fixed) (v4.7.29) 2009-03-24 Wolfgang Sourdeau * libxmlSAXDriver.m (_startElement): autorelease "nsDict" when its instantiated from a copy of "ns" (v4.7.28) 2006-07-03 Helge Hess * libXMLSaxDriver.m: fixed last changes for libFoundation (v4.5.24) 2007-03-18 Marcus Mueller * libxmlSAXDriver.m: rewrote decoding of hexadecimal entities as this used functionality not present in libFoundation (v4.7.26) 2007-03-15 Marcus Mueller * libxmlSAXDriver.m: properly decode #%i; values in attributes - libxml2 doesn't decode them properly, but the driver is expected to do so. While fixing this also refrained from using the global uniqued string cache for these values (I guess the former is correct for tags and attribute names, but using it for values feels somewhat odd). (v4.7.25) 2006-07-03 Helge Hess * v4.5.24 * use %p for pointer formats, fixed gcc 4.1 warnings * improved retain-count for exception userInfo dicts 2005-11-17 Helge Hess * properly include string.h to avoid warnings (v4.5.23) 2005-09-14 Helge Hess * libxmlSAXDriver.m: improved 'activeDriver' handling in some edge condition (v4.5.22) 2005-08-16 Helge Hess * install into SaxObjC framework Resources when being used with OSX (v4.5.21) 2005-07-20 Helge Hess * TableCallbacks.m: fixed a compilation issues with either gcc 4.0.1 or Sarge (v4.5.20) 2005-05-06 Helge Hess * libxmlSAXDriver.m: minor improvements to error messages (v4.5.19) 2005-05-03 Helge Hess * fixed loads of gcc 4.0 warnings (v4.5.18) 2004-12-14 Marcus Mueller * libxmlSAXDriver.xcode: minor fixes 2004-11-04 Helge Hess * use Version file for install directory location 2004-11-04 Helge Hess * fhs.make, GNUmakefile: use Version file to set install dir 2004-09-22 Marcus Mueller * libxmlSAXDriver.xcode: minor fixes 2004-09-21 Marcus Mueller * libxmlSAXDriver.xcode: Fixed library search path * libxmlSAXDriver.xcode: Fixed dependencies to resemble the make process more closely. Our aim should be to stick to the make process as closely as possible, so we shouldn't introduce dependencies in non-toplevel projects. Also added a new copy files phase to copy the resulting bundle to a well-known place where the SaxObjC framework can later pick it up for inclusion in its framework wrapper. 2004-08-29 Helge Hess * added hack to install the project in FHS locations - the SAX driver will be installed in FHS_INSTALL_ROOT if specified (eg make FHS_INSTALL_ROOT=/usr/local) (v4.3.17) 2004-08-26 Marcus Mueller * libxmlSAXDriver.xcode: new Xcode project 2004-08-25 Helge Hess * v4.3.16 * libxmlHTMLSAXDriver.m: generate SAX events (HTML/BODY) for empty documents * libxmlDocSAXDriver.m, libxmlHTMLSAXDriver.m: allows NSURL objects as the source for parsing 2004-08-24 Helge Hess * GNUmakefile: install SAX driver in Library/SaxDrivers-4.3/ (v4.3.15) * GNUmakefile: install SAX driver in Library/SaxDrivers/4.3/ (v4.3.14) 2004-05-07 Helge Hess * libxmlHTMLSAXDriver.m: do not report unclosed entity references (as they often appear as query parameters in URLs) per default, can be enabled using the libxmlHTMLSAXDriverReportUnclosedEntityRefs default (v4.2.13) * libxmlHTMLSAXDriver.m: invalid tags are now reported to the SAX error handler if you enable the libxmlHTMLSAXDriverReportInvalidTags default (v4.2.12) 2004-05-05 Marcus Mueller * v4.2.11 * GNUmakefile, GNUmakefile.preamble: added support for building with GNUSTEP_BUILD_DIR environment variable set for recent gnustep-make package. * GNUmakefile.preamble: get libxml_INCLUDE_DIR and libxml_LIBS via xml2-config instead of hardcoding. This plays nicely on systems that use their own libxml as well as on GNUstep installations that install an own copy of libxml2 in GNUSTEP_ROOT, because xml2-config will be found in PATH prior to the system one. 2003-12-10 Helge Hess * GNUmakefile: install driver in GNUSTEP_INSTALLATION_DIR instead of GNUSTEP_USER_DIR, as "demanded" by Nicola ;-) (v4.2.10) 2003-12-03 Helge Hess * GNUmakefile: include common.make from GNUSTEP_MAKEFILES (v4.2.9) 2003-10-15 Helge Hess * created GNUmakefile.preamble, look for libxml2 in Fink (/sw/lib) if we are building on darwin6 (v4.2.8) 2003-10-13 Helge Hess * libxmlSAXDriver.m: fixed a void-return issue (v4.2.7) 2003-08-29 Helge Hess * libxmlSAXDriver.m: fixed compilation on Cocoa (v4.2.6) 2003-07-21 Helge Hess * libxmlSAXDriver.m: improved XML charset detection (v4.2.5) 2003-07-02 Helge Hess * libxmlHTMLSAXDriver.m: proper handling of system-id (v4.2.4) * libxmlHTMLSAXDriver.m: changed not to report "invalid tag" errors, used for allowing SKYOBJ tags in .html files (v4.2.3) * unicode.h: removed some unused statics 2003-06-23 Helge Hess * v4.2.2 * added Version file to bundle * libxmlHTMLSAXDriver.m: do not log unsupported features 2003-01-14 Helge Hess * GNUmakefile (ADDITIONAL_INCLUDE_DIRS): added /usr/include/libxml2 for cases were we compile without sxsys-libxml2 2003-01-07 Helge Hess * removed dependency on FoundationExt on MacOSX Thu Jan 2 10:53:25 2003 Helge Hess * replaced usage of RETAIN macros with method calls Thu Oct 17 20:27:14 2002 Helge Hess * libxmlSAXDriver.m: fixed a rare problem where an element was popped from the namespace stack in endDocument, but the stack was empty 2002-06-04 Helge Hess * GNUmakefile: fixed linking of libSaxObjC if SaxObjC isn't installed yet Sun May 5 18:57:02 2002 Helge Hess * removed SAX1 document handler Thu May 2 12:21:48 2002 Helge Hess * added own NSMapTable callbacks since NSNonOwnedCStringMapKeyCallBacks aren't available on MacOSX and gstep-base * changed bundle to use -rangeOfString: instead of -indexOfString: Mon Feb 11 17:33:52 2002 Helge Hess * libxmlSAXDriver.m: fixed bug in XML charset detection Sat Feb 9 13:39:55 2002 Helge Hess * libxmlSAXDriver.m: made less sensible regarding whitespace before XML declaration * libxmlSAXDriver.m: added charset detection for NSString's containing XML Wed Nov 14 13:02:13 2001 Helge Hess * libxmlHTMLSAXDriver.m: fixed bug: unicode length was incorrectly calculated * libxmlHTMLSAXDriver.m: check for empty text nodes Tue Nov 13 16:22:13 2001 Helge Hess * libxmlHTMLSAXDriver.m: don't throw exception on unrecognized features Mon Nov 5 14:13:45 2001 Helge Hess * libxmlSAXDriver.m: fixed bug (_cdataBlock called libxml characters()) Fri Nov 2 12:56:54 2001 Helge Hess * libxmlSAXDriver.m: prefix all libxml SAX callbacks with underscore (libxml 2.4.7 compatibility) Wed Oct 24 18:31:52 2001 Helge Hess * all drivers: fixed bug in UTF8-UTF16 conversion (incorrect length was passed to -characters:length: SAX callback !!!) Mon Aug 27 19:39:07 2001 Helge Hess * libxmlHTMLSAXDriver.m: use UTF8 for parsing Mon Aug 27 18:25:41 2001 Helge Hess * again: more stable in error conditions ;-) Fri Aug 24 19:50:44 2001 Helge Hess * libxmlHTMLSAXDriver.m: more stable in error conditions Fri Aug 17 18:35:56 2001 Helge Hess * libxmlHTMLSAXDriver.m: place autorelease pool around parsing Fri Aug 17 18:18:35 2001 Helge Hess * libxmlHTMLSAXDriver.m: added string uniquing table * libxmlSAXDriver.m: added string uniquing table Thu Aug 16 13:46:06 2001 Helge Hess * libxmlSAXDriver.m: cache SaxAttributes for efficiency, SAX callbacks may not reuse SaxAttributes objects but must copy them ... Thu Aug 9 20:11:01 2001 Helge Hess * libxmlSAXDriver.m: reduced use of autorelease Fri Mar 9 10:40:53 2001 Helge Hess * libxmlSAXDriver.m: fixed bug with declaration of default-namespace Wed Feb 7 10:33:39 2001 Helge Hess * libxmlSAXDriver.m: add support for NSURL Fri Jan 12 16:36:42 2001 Helge Hess * libxmlSAXDriver.m: changed locator handling, lost reentrancy Wed Jan 3 14:50:07 2001 Helge Hess * libxmlSAXDriver.m: removed caching of SaxAttrs Tue Dec 12 20:20:02 2000 Helge Hess * added a driver for the libxml's HTML parser 2000-10-09 * libxmlSAXDriver.m: fixed bug with NSData parsing SOPE/sope-xml/libxmlSAXDriver/common.h0000644000000000000000000000230215004363604016544 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __libxmlSAXDriver_common_H__ #define __libxmlSAXDriver_common_H__ #import #ifndef ASSIGN # define ASSIGN(object, value) \ ({id __object = (id)object; \ id __value = (id)value; \ if (__value != __object) { if (__value) [__value retain]; \ if (__object) [__object release]; \ object = __value;}}) #endif #endif /* __libxmlSAXDriver_common_H__ */ SOPE/sope-xml/libxmlSAXDriver/COPYING0000644000000000000000000006130315004363604016144 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-xml/libxmlSAXDriver/fhs.make0000644000000000000000000000136215004363604016527 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib64/ else FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib/ endif FHS_SAX_DIR=$(FHS_LIB_DIR)sope-$(MAJOR_VERSION).$(MINOR_VERSION)/saxdrivers/ fhs-sax-dirs :: $(MKDIRS) $(FHS_SAX_DIR) move-bundles-to-fhs :: fhs-sax-dirs @echo "moving bundles $(BUNDLE_INSTALL_DIR) to $(FHS_SAX_DIR) .." for i in $(BUNDLE_NAME); do \ j="$(FHS_SAX_DIR)/$${i}$(BUNDLE_EXTENSION)"; \ if test -d $$j; then rm -r $$j; fi; \ mv "$(BUNDLE_INSTALL_DIR)/$${i}$(BUNDLE_EXTENSION)" $$j; \ done move-to-fhs :: move-bundles-to-fhs after-install :: move-to-fhs endif SOPE/sope-xml/libxmlSAXDriver/README0000644000000000000000000000033615004363604015770 0ustar rootrootlibxmlSAXDriver =============== This directory contains the sources for a SAX driver bundle that works on top of the libxml2 library. It can be used for processing XML, but also for parsing HTML. Requirements: - libxml2 SOPE/sope-xml/libxmlSAXDriver/unicode.h0000644000000000000000000000652715004363604016717 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Unicode support */ typedef unsigned long UCS4; typedef unsigned short UCS2; typedef unsigned short UTF16; typedef unsigned char UTF8; #define unichar UTF16 static const int halfShift = 10; static const UCS4 halfBase = 0x0010000UL; static const UCS4 halfMask = 0x3FFUL; static const UCS4 kSurrogateHighStart = 0xD800UL; static const UCS4 kSurrogateLowStart = 0xDC00UL; static const UCS4 kReplacementCharacter = 0x0000FFFDUL; static const UCS4 kMaximumUCS2 = 0x0000FFFFUL; static const UCS4 kMaximumUTF16 = 0x0010FFFFUL; static UCS4 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; static char bytesFromUTF8[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; static int _UTF8ToUTF16(unsigned char **sourceStart, unsigned char *sourceEnd, unichar **targetStart, const unichar *targetEnd) { int result = 0; register UTF8 *source = *sourceStart; register UTF16 *target = *targetStart; while (source < sourceEnd) { register UCS4 ch = 0; register unsigned short extraBytesToWrite = bytesFromUTF8[*source]; if (source + extraBytesToWrite > sourceEnd) { result = 1; break; }; switch(extraBytesToWrite) { /* note: code falls through cases! */ case 5: ch += *source++; ch <<= 6; case 4: ch += *source++; ch <<= 6; case 3: ch += *source++; ch <<= 6; case 2: ch += *source++; ch <<= 6; case 1: ch += *source++; ch <<= 6; case 0: ch += *source++; }; ch -= offsetsFromUTF8[extraBytesToWrite]; if (target >= targetEnd) { result = 2; break; }; if (ch <= kMaximumUCS2) { *target++ = ch; } else if (ch > kMaximumUTF16) { *target++ = kReplacementCharacter; } else { if (target + 1 >= targetEnd) { result = 2; break; }; ch -= halfBase; *target++ = (ch >> halfShift) + kSurrogateHighStart; *target++ = (ch & halfMask) + kSurrogateLowStart; }; }; *sourceStart = source; *targetStart = target; return result; } SOPE/sope-xml/libxmlSAXDriver/libxmlHTMLSAXDriver.h0000644000000000000000000000321115004363604020760 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include /* recognized properties: http://xml.org/sax/properties/declaration-handler http://xml.org/sax/properties/lexical-handler http://www.skyrix.com/sax/properties/html-namespace */ @class libxmlSAXLocator; @interface libxmlHTMLSAXDriver : NSObject < SaxXMLReader > { NSObject *contentHandler; id dtdHandler; id errorHandler; id entityResolver; id lexicalHandler; id declHandler; NSString *namespaceURI; unsigned depth; BOOL encodeEntities; libxmlSAXLocator *locator; /* libxml */ void *doc; void *ctxt; SaxAttributes *attributes; } @end SOPE/sope-xml/libxmlSAXDriver/libxmlSAXDriver.h0000644000000000000000000000372715004363604020307 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __libxmlSAXDriver_H__ #define __libxmlSAXDriver_H__ #import #include #include #include #include #include #include #include #include @class NSMutableArray; @class SaxAttributes; @class libxmlSAXLocator; @interface libxmlSAXDriver : NSObject < SaxXMLReader > { @private id contentHandler; id dtdHandler; id errorHandler; id entityResolver; id lexicalHandler; id declHandler; void *sax; /* ptr to libxml sax structure */ void *ctxt; /* libxml parser context */ void *entity; /* used during entity lookup */ int depth; NSMutableArray *nsStack; BOOL fNamespaces; BOOL fNamespacePrefixes; /* cache */ libxmlSAXLocator *locator; SaxAttributes *attrs; } @end #endif /* __libxmlSAXDriver_H__ */ SOPE/sope-xml/libxmlSAXDriver/GNUmakefile.postamble0000644000000000000000000000042115004363604021142 0ustar rootroot# postprocessing # add bundle-info.plist file ifneq ($(GNUSTEP_BUILD_DIR),) after-all :: @(cp bundle-info.plist \ $(GNUSTEP_BUILD_DIR)/$(BUNDLE_NAME)$(BUNDLE_EXTENSION)) else after-all :: @(cd $(BUNDLE_NAME)$(BUNDLE_EXTENSION);\ cp ../bundle-info.plist .) endif SOPE/sope-xml/libxmlSAXDriver/Version0000644000000000000000000000004015004363604016450 0ustar rootroot# version SUBMINOR_VERSION:=29 SOPE/sope-xml/libxmlSAXDriver/libxmlSAXLocator.m0000644000000000000000000000441415004363604020456 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "libxmlSAXLocator.h" #include "common.h" @implementation libxmlSAXLocator - (id)initWithSaxLocator:(xmlSAXLocatorPtr)_loc parser:(id)_parser { if (_loc == NULL) { [self release]; return nil; } self->parser = _parser; self->getPublicId = _loc->getPublicId; self->getSystemId = _loc->getSystemId; self->getLineNumber = _loc->getLineNumber; self->getColumnNumber = _loc->getColumnNumber; return self; } - (void)clear { self->parser = nil; } /* accessors */ - (int)columnNumber { //return -1; NSAssert(self->ctx, @"missing locator ctx .."); return self->getColumnNumber ? self->getColumnNumber(self->ctx) : -1; } - (int)lineNumber { //return -1; NSAssert(self->ctx, @"missing locator ctx .."); return self->getLineNumber ? self->getLineNumber(self->ctx) : -1; } - (NSString *)publicId { const xmlChar *s; //return nil; s = self->getPublicId ? self->getPublicId(self->ctx) : NULL; return s ? [NSString stringWithCString:(const char *)s] : nil; } - (NSString *)systemId { const xmlChar *s; //return nil; s = self->getSystemId ? self->getSystemId(self->ctx) : NULL; return s ? [NSString stringWithCString:(const char *)s] : nil; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"<0x%p[%@]: pub=%@ sys=%@ L%i C%i>", self, NSStringFromClass([self class]), [self publicId], [self systemId], [self lineNumber], [self columnNumber]]; } @end /* libxmlSaxLocator */ SOPE/sope-xml/libxmlSAXDriver/TableCallbacks.h0000644000000000000000000000176015004363604020112 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __libxml_TableCallbacks_H__ #define __libxml_TableCallbacks_H__ #import extern const NSMapTableKeyCallBacks libxmlNonOwnedCStringMapKeyCallBacks; #endif /* __libxml_TableCallbacks_H__ */ SOPE/sope-xml/libxmlSAXDriver/libxmlSAXDriver.m0000644000000000000000000013031515004363604020306 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "libxmlSAXDriver.h" #include "libxmlSAXLocator.h" #include "TableCallbacks.h" #include #include #include "common.h" #include #include /* TODO: xmlChar is really UTF-8, not cString !!! */ static NSString *SaxDeclHandlerProperty = @"http://xml.org/sax/properties/declaration-handler"; static NSString *SaxLexicalHandlerProperty = @"http://xml.org/sax/properties/lexical-handler"; #if 0 static NSString *SaxDOMNodeProperty = @"http://xml.org/sax/properties/dom-node"; static NSString *SaxXMLStringProperty = @"http://xml.org/sax/properties/xml-string"; #endif static int _UTF8ToUTF16(unsigned char **sourceStart, unsigned char *sourceEnd, unichar **targetStart, const unichar *targetEnd); static NSMapTable *uniqueStrings = NULL; // THREAD static Class NSStringClass = Nil; static inline NSString *xmlCharsToString(const xmlChar *_s) { NSString *s; char *newkey; if (_s == NULL) return nil; // TODO: does the uniquer really make sense? // best would to have an -initWithUTF...nocopy:YES if (uniqueStrings == NULL) { uniqueStrings = NSCreateMapTable(libxmlNonOwnedCStringMapKeyCallBacks, NSObjectMapValueCallBacks, 128); } else if ((s = NSMapGet(uniqueStrings, _s))) { /* found a string in cache ... */ return [s retain]; } newkey = malloc(strlen((const char *)_s) + 2); strcpy(newkey, (const char *)_s); if (NSStringClass == Nil) NSStringClass = [NSString class]; s = [[NSStringClass alloc] initWithUTF8String:(const char *)_s]; NSMapInsert(uniqueStrings, newkey, s); return s; } static inline NSString *xmlCharsToDecodedString(const xmlChar *_s) { NSString *s; BOOL needsDecoding = NO; unichar (*charAt)(id, SEL, unsigned int); unsigned i, len, last; if (_s == NULL) return nil; if (NSStringClass == Nil) NSStringClass = [NSString class]; s = [[NSStringClass alloc] initWithUTF8String:(const char *)_s]; len = [s length]; charAt = (void *)[s methodForSelector:@selector(characterAtIndex:)]; for (i = 0; i < len; i++) { if (charAt(s, @selector(characterAtIndex:), i) == '&') { needsDecoding = YES; last = 0; break; } } if (needsDecoding) { // TODO: This needs *serious* cleanup. Two small unichar buffers // would be 10x faster and half the codesize. NSMutableString *ds; ds = [[NSMutableString alloc] initWithCapacity:len]; for (; i < len; i++) { if (charAt(s, @selector(characterAtIndex:), i) == '&') { NSRange r; r = NSMakeRange(last, i - last); [ds appendString:[s substringWithRange:r]]; if (charAt(s, @selector(characterAtIndex:), i + 1) == '#') { NSRange vr; unichar c; r = NSMakeRange(i + 2, len - i - 2); r = [s rangeOfString:@";" options:0 range:r]; c = (unichar)charAt(s, @selector(characterAtIndex:), i + 2); /* hex value? */ if (c == 'x' || c == 'X') { const char *shex; unsigned value; vr = NSMakeRange(i + 3, r.location - i - 3); shex = [[s substringWithRange:vr] cString]; sscanf(shex, "%x", &value); c = (unichar)value; } else { vr = NSMakeRange(i + 2, r.location - i - 2); c = (unichar)[[s substringWithRange:vr] intValue]; } [ds appendString:[NSString stringWithCharacters:&c length:1]]; i = NSMaxRange(r); last = i; } else { if ((charAt(s, @selector(characterAtIndex:), i + 1) == 'a') && (charAt(s, @selector(characterAtIndex:), i + 2) == 'm') && (charAt(s, @selector(characterAtIndex:), i + 3) == 'p')) { [ds appendString:@"&"]; i += 5; } else if ((charAt(s, @selector(characterAtIndex:), i + 1) == 'q') && (charAt(s, @selector(characterAtIndex:), i + 2) == 'u') && (charAt(s, @selector(characterAtIndex:), i + 3) == 'o') && (charAt(s, @selector(characterAtIndex:), i + 4) == 't')) { [ds appendString:@"\""]; i += 6; } else if ((charAt(s, @selector(characterAtIndex:), i + 1) == 'a') && (charAt(s, @selector(characterAtIndex:), i + 2) == 'p') && (charAt(s, @selector(characterAtIndex:), i + 3) == 'o') && (charAt(s, @selector(characterAtIndex:), i + 4) == 's')) { [ds appendString:@"'"]; i += 6; } else if ((charAt(s, @selector(characterAtIndex:), i + 1) == 'l') && (charAt(s, @selector(characterAtIndex:), i + 2) == 't')) { [ds appendString:@"<"]; i += 4; } else if ((charAt(s, @selector(characterAtIndex:), i + 1) == 'g') && (charAt(s, @selector(characterAtIndex:), i + 2) == 't')) { [ds appendString:@">"]; i += 4; } else { NSRange r; r = NSMakeRange(i + 1, len - i - 1); r = [s rangeOfString:@";" options:0 range:r]; r = NSMakeRange(i, r.location - i); [ds appendString:[s substringWithRange:r]]; i = NSMaxRange(r); } last = i; } } } if (last != (len - 1)) [ds appendString:[s substringFromIndex:last]]; [s release]; s = ds; } return s; } extern xmlParserCtxtPtr xmlCreateMemoryParserCtxt(char *buffer, int size); @implementation libxmlSAXDriver static libxmlSAXDriver *activeDriver = nil; // THREAD #define SETUP_ACTDRIVER \ { if (activeDriver != nil) { \ NSLog(@"ERROR(%s): %@ there is an active driver set (0x%p), " \ @"override!", \ __PRETTY_FUNCTION__, self, activeDriver);\ }\ activeDriver = self;} #define TEARDOWN_ACTDRIVER \ { if (activeDriver == self) activeDriver = nil; \ else if (activeDriver != nil) { \ NSLog(@"ERROR(%s): %@ activeDriver global var mixed up 0x%p, " \ @"probably a THREAD issue.", \ __PRETTY_FUNCTION__, self, activeDriver); } } static void _startElement(libxmlSAXDriver *self, const xmlChar *name, const xmlChar **atts); static void _endElement(libxmlSAXDriver *self, const xmlChar *name); static void _startDocument(libxmlSAXDriver *self); static void _endDocument(libxmlSAXDriver *self); static void _characters(libxmlSAXDriver *self, const xmlChar *chars, NSUInteger len); static void _ignorableWhiteSpace(libxmlSAXDriver *self, const xmlChar *chars, NSUInteger len); static void __pi(libxmlSAXDriver *self, const xmlChar *target, const xmlChar *data); static void _comment(libxmlSAXDriver *self, const xmlChar *value); static xmlParserInputPtr _resolveEntity(libxmlSAXDriver *self, const xmlChar *pub, const xmlChar *sys) __attribute__((unused)); static xmlEntityPtr _getEntity(libxmlSAXDriver *self, const xmlChar *name) __attribute__((unused)); static void _warning(libxmlSAXDriver *self, const char *msg, ...); static void _error(libxmlSAXDriver *self, const char *msg, ...); static void _fatalError(libxmlSAXDriver *self, const char *msg, ...); static void _setLocator(void *udata, xmlSAXLocatorPtr _locator); static void _cdataBlock(libxmlSAXDriver *self, const xmlChar *value, NSUInteger len); static void _entityDecl(libxmlSAXDriver *self, const xmlChar *name, int type, const xmlChar *publicId, const xmlChar *systemId, xmlChar *content) __attribute__((unused)); static void _notationDecl(libxmlSAXDriver *self, const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId) __attribute__((unused)); static void _unparsedEntityDecl(libxmlSAXDriver *self, const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId, const xmlChar *notationName) __attribute__((unused)); static void _elementDecl(libxmlSAXDriver *self, const xmlChar *name, int type, xmlElementContentPtr content) __attribute__((unused)); static void _attrDecl(libxmlSAXDriver *self, const xmlChar *elem, const xmlChar *name, int type, int def, const xmlChar *defaultValue, xmlEnumerationPtr tree) __attribute__((unused)); static void _internalSubset(libxmlSAXDriver *ctx, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID); static void _externalSubset(libxmlSAXDriver *ctx, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID); static void _reference(libxmlSAXDriver *ctx, const xmlChar *name); #if 0 static int _isStandalone(libxmlSAXDriver *self); static int _hasInternalSubset(libxmlSAXDriver *self); static int _hasExternalSubset(libxmlSAXDriver *self); #endif static xmlSAXHandler saxHandler = { (void*)_internalSubset, /* internalSubset */ #if 1 NULL,NULL,NULL, #else (void*)_isStandalone, /* isStandalone */ (void*)_hasInternalSubset, /* hasInternalSubset */ (void*)_hasExternalSubset, /* hasExternalSubset */ #endif #if HANDLE_XML_ENTITIES (void*)_resolveEntity, /* resolveEntity */ (void*)_getEntity, /* getEntity */ #else NULL, NULL, #endif #if HANDLE_XML_DELCS (void*)_entityDecl, /* entityDecl */ (void*)_notationDecl, /* notationDecl */ (void*)_attrDecl, /* attributeDecl */ (void*)_elementDecl, /* elementDecl */ (void*)_unparsedEntityDecl, /* unparsedEntityDecl */ #else NULL, NULL, NULL, NULL, NULL, #endif (void*)_setLocator, /* setDocumentLocator */ (void*)_startDocument, /* startDocument */ (void*)_endDocument, /* endDocument */ (void*)_startElement, /* startElement */ (void*)_endElement, /* endElement */ (void*)_reference, /* reference */ (void*)_characters, /* characters */ (void*)_ignorableWhiteSpace, /* ignorableWhitespace */ (void*)__pi, /* processingInstruction */ (void*)_comment, /* comment */ (void*)_warning, /* warning */ (void*)_error, /* error */ (void*)_fatalError, /* fatalError */ NULL, /* getParameterEntity */ (void*)_cdataBlock, /* cdataBlock */ (void*)_externalSubset /* externalSubset */ }; - (id)init { self->sax = &saxHandler; self->nsStack = [[NSMutableArray alloc] init]; /* feature defaults */ self->fNamespaces = YES; self->fNamespacePrefixes = NO; return self; } - (void)dealloc { [self->attrs release]; [self->nsStack release]; [self->declHandler release]; [self->lexicalHandler release]; [self->contentHandler release]; [self->dtdHandler release]; [self->errorHandler release]; [self->entityResolver release]; [self->locator clear]; [self->locator release]; if (self->entity) free(self->entity); [super dealloc]; } /* properties */ - (void)setProperty:(NSString *)_name to:(id)_value { if ([_name isEqualToString:SaxLexicalHandlerProperty]) { ASSIGN(self->lexicalHandler, _value); return; } if ([_name isEqualToString:SaxDeclHandlerProperty]) { ASSIGN(self->declHandler, _value); return; } [SaxNotRecognizedException raise:@"PropertyException" format:@"don't know property %@", _name]; } - (id)property:(NSString *)_name { if ([_name isEqualToString:SaxLexicalHandlerProperty]) return self->lexicalHandler; if ([_name isEqualToString:SaxDeclHandlerProperty]) return self->declHandler; [SaxNotRecognizedException raise:@"PropertyException" format:@"don't know property %@", _name]; return nil; } /* features */ - (void)setFeature:(NSString *)_name to:(BOOL)_value { if ([_name isEqualToString:@"http://xml.org/sax/features/namespaces"]) { self->fNamespaces = _value; return; } if ([_name isEqualToString: @"http://xml.org/sax/features/namespace-prefixes"]) { self->fNamespacePrefixes = _value; return; } [SaxNotRecognizedException raise:@"FeatureException" format:@"don't know feature %@", _name]; } - (BOOL)feature:(NSString *)_name { if ([_name isEqualToString:@"http://xml.org/sax/features/namespaces"]) return self->fNamespaces; if ([_name isEqualToString: @"http://xml.org/sax/features/namespace-prefixes"]) return self->fNamespacePrefixes; if ([_name isEqualToString: @"http://www.skyrix.com/sax/features/predefined-namespaces"]) return YES; [SaxNotRecognizedException raise:@"FeatureException" format:@"don't know feature %@", _name]; return NO; } /* handlers */ - (void)setDTDHandler:(id)_handler { ASSIGN(self->dtdHandler, _handler); } - (id)dtdHandler { return self->dtdHandler; } - (void)setErrorHandler:(id)_handler { ASSIGN(self->errorHandler, _handler); } - (id)errorHandler { return self->errorHandler; } - (void)setEntityResolver:(id)_handler { ASSIGN(self->entityResolver, _handler); } - (id)entityResolver { return self->entityResolver; } - (void)setContentHandler:(id)_handler { ASSIGN(self->contentHandler, _handler); } - (id)contentHandler { return self->contentHandler; } /* parsing */ - (NSStringEncoding)encodingForXMLEncodingString:(NSString *)_enc { // TODO: use the string-charset functions in NGExtensions _enc = [_enc lowercaseString]; if ([_enc isEqualToString:@"utf-8"]) return NSUTF8StringEncoding; if ([_enc isEqualToString:@"iso-8859-1"]) return NSISOLatin1StringEncoding; #ifndef NeXT_Foundation_LIBRARY if ([_enc isEqualToString:@"iso-8859-9"]) return NSISOLatin9StringEncoding; #endif if ([_enc isEqualToString:@"iso-8859-2"]) return NSISOLatin2StringEncoding; if ([_enc isEqualToString:@"ascii"]) return NSASCIIStringEncoding; NSLog(@"%s: UNKNOWN XML ENCODING '%@'", __PRETTY_FUNCTION__, _enc); return 0; } - (NSData *)dataForXMLString:(NSString *)_string { NSData *data; NSRange r; data = nil; r = [_string rangeOfString:@"?>"]; if ([_string hasPrefix:@" 0) { xmlDecl = [_string substringFromIndex:(r.location + 10)]; r = [xmlDecl rangeOfString:@"'"]; xmlDecl = (r.length > 0) ? [xmlDecl substringToIndex:r.location] : (NSString *)nil; } else { r = [xmlDecl rangeOfString:@"encoding=\""]; if (r.length > 0) { xmlDecl = [_string substringFromIndex:(r.location + r.length)]; r = [xmlDecl rangeOfString:@"\""]; xmlDecl = r.length > 0 ? [xmlDecl substringToIndex:r.location] : (NSString *)nil; } else xmlDecl = nil; } if ([xmlDecl length] > 0) { NSStringEncoding enc; if ((enc = [self encodingForXMLEncodingString:xmlDecl]) != 0) { data = [_string dataUsingEncoding:enc]; if (data == nil) { NSLog(@"WARNING(%s): couldn't get data for string '%@', " @"encoding %i !", __PRETTY_FUNCTION__, _string, enc); return nil; } } } } if (data == nil) data = [_string dataUsingEncoding:NSUTF8StringEncoding]; return data; } - (void)parseFromSource:(id)_source systemId:(NSString *)_sysId { NSAutoreleasePool *pool; if (_source == nil) { /* no source ??? */ return; } if ([_source isKindOfClass:[NSString class]]) { /* convert strings to UTF8 data */ if (_sysId == nil) _sysId = @""; _source = [self dataForXMLString:_source]; } else if ([_source isKindOfClass:[NSURL class]]) { if (_sysId == nil) _sysId = [_source absoluteString]; _source = [_source resourceDataUsingCache:NO]; } else if ([_source isKindOfClass:[NSData class]]) { if (_sysId == nil) _sysId = @""; } else { SaxParseException *e; NSDictionary *ui; ui = [[NSDictionary alloc] initWithObjectsAndKeys: _source ? _source : (id)@"", @"source", self, @"parser", nil]; e = (id)[SaxParseException exceptionWithName:@"SaxIOException" reason:@"cannot handle data-source" userInfo:ui]; [ui release]; ui = nil; [self->errorHandler fatalError:e]; return; } pool = [[NSAutoreleasePool alloc] init]; /* start parsing */ { unsigned char *src, *start; unsigned len; void *oldsax; if ((len = [_source length]) == 0) { /* no content ... */ return; } /* zero-terminate the data !!! */ src = malloc(len + 2); [_source getBytes:src length:len]; src[len] = '\0'; start = src; if (len > 5) { unsigned char *tmp; if ((tmp = (unsigned char *)strstr((char *)src, "ctxt = xmlCreateMemoryParserCtxt((void *)start, len); if (self->ctxt == nil) { SaxParseException *e; NSDictionary *ui; NSLog(@"%s: couldn't create memory parser ctx (src=0x%p, len=%d) !", __PRETTY_FUNCTION__, src, len); TEARDOWN_ACTDRIVER; ui = nil; e = (id)[SaxParseException exceptionWithName:@"SaxIOException" reason:@"couldn't create memory parser context" userInfo:ui]; [self->errorHandler fatalError:e]; return; } if (((xmlParserCtxtPtr)self->ctxt)->input != NULL && [_sysId length] > 0) { ((xmlParserInputPtr)((xmlParserCtxtPtr)self->ctxt)->input)->filename = [_sysId cString]; } oldsax = ((xmlParserCtxtPtr)self->ctxt)->sax; ((xmlParserCtxtPtr)self->ctxt)->sax = self->sax; ((xmlParserCtxtPtr)self->ctxt)->userData = self; xmlParseDocument(ctxt); if (!(((xmlParserCtxtPtr)self->ctxt)->wellFormed)) NSLog(@"%@: not well formed 1", _sysId); if (((xmlParserCtxtPtr)self->ctxt)->input != NULL && [_sysId length] > 0) { ((xmlParserInputPtr)((xmlParserCtxtPtr)self->ctxt)->input)->filename = NULL; } ((xmlParserCtxtPtr)self->ctxt)->sax = oldsax; ((xmlParserCtxtPtr)self->ctxt)->userData = NULL; xmlFreeParserCtxt(ctxt); TEARDOWN_ACTDRIVER; if (src != NULL) { free(src); src = NULL; } } [pool release]; } - (void)parseFromSource:(id)_source { [self parseFromSource:_source systemId:nil]; } static int mfread(void *f, char *buf, int len) { int l; l = fread(buf, 1, len, f); //printf("read %i bytes\n", l); return l; } static int mfclose(void *f) { return fclose(f); } - (void)parseFromSystemId:(NSString *)_sysId { /* _sysId is a URI */ NSAutoreleasePool *pool; if (![_sysId hasPrefix:@"file:"]) { SaxParseException *e; NSDictionary *ui; NSURL *url; if ((url = [NSURL URLWithString:_sysId])) { [self parseFromSource:url systemId:_sysId]; return; } ui = [[NSDictionary alloc] initWithObjectsAndKeys: _sysId ? _sysId : (NSString *)@"", @"systemID", self, @"parser", nil]; e = (id)[SaxParseException exceptionWithName:@"SaxIOException" reason:@"cannot handle system-id" userInfo:ui]; [ui release]; ui = nil; [self->errorHandler fatalError:e]; return; } pool = [[NSAutoreleasePool alloc] init]; /* cut off file:// */ if ([_sysId hasPrefix:@"file://"]) _sysId = [_sysId substringFromIndex:7]; else _sysId = [_sysId substringFromIndex:5]; /* start parsing .. */ #if 0 ret = xmlSAXUserParseFile(self->sax, (void *)self, [_sysId cString]); #else { FILE *f; f = fopen([_sysId cString], "r"); if (f == NULL) { SaxParseException *e; NSDictionary *ui; #if DEBUG NSLog(@"%s: missing file '%@'", __PRETTY_FUNCTION__, _sysId); #endif ui = [[NSDictionary alloc] initWithObjectsAndKeys: _sysId ? _sysId : (NSString *)@"", @"path", self, @"parser", nil]; e = (id)[SaxParseException exceptionWithName:@"SaxIOException" reason:@"can't find file" userInfo:ui]; [ui release]; ui = nil; [self->errorHandler fatalError:e]; [pool release]; return; } self->ctxt = xmlCreateIOParserCtxt(self->sax, self /* userdata */, mfread, /* ioread */ mfclose, /* ioclose */ f, /* ioctx */ XML_CHAR_ENCODING_UTF8 /* encoding */); if (((xmlParserCtxtPtr)self->ctxt)->input != NULL && [_sysId length] > 0) { ((xmlParserInputPtr)((xmlParserCtxtPtr)self->ctxt)->input)->filename = [_sysId cString]; } SETUP_ACTDRIVER; xmlParseDocument(self->ctxt); TEARDOWN_ACTDRIVER; if (((xmlParserCtxtPtr)self->ctxt)->input != NULL && [_sysId length] > 0) { ((xmlParserInputPtr)((xmlParserCtxtPtr)self->ctxt)->input)->filename = NULL; } if (!(((xmlParserCtxtPtr)self->ctxt)->wellFormed)) NSLog(@"%@: not well formed 2", _sysId); ((xmlParserCtxtPtr)self->ctxt)->sax = NULL; xmlFreeParserCtxt(self->ctxt); } #endif [pool release]; } /* entities */ - (NSString *)replacementStringForEntityNamed:(NSString *)_entityName { // TODO: check, how this is used, could explain some problems //NSLog(@"get entity: %@", _entityName); return [[@"&" stringByAppendingString:_entityName] stringByAppendingString:@";"]; } /* namespace support */ - (NSString *)nsUriForPrefix:(NSString *)_prefix { NSEnumerator *e; NSDictionary *ns; e = [self->nsStack reverseObjectEnumerator]; while ((ns = [e nextObject])) { NSString *uri; if ((uri = [ns objectForKey:_prefix])) { //NSLog(@"prefix %@ -> uri %@", _prefix, uri); return uri; } } //NSLog(@"prefix %@ -> uri %@", _prefix, nil); return nil; } - (NSString *)defaultNamespace { return [self nsUriForPrefix:@":"]; } - (void)declarePrefix:(NSString *)_prefix namespaceURI:(NSString *)_uri { NSMutableDictionary *ns = nil; NSDictionary *newns; unsigned count; NSCAssert(self->nsStack, @"missing namespace stack"); if ((count = [self->nsStack count]) == 0) ns = [[NSMutableDictionary alloc] initWithCapacity:2]; else ns = [[self->nsStack lastObject] mutableCopy]; if ([_prefix length] == 0) _prefix = @":"; [ns setObject:_uri forKey:_prefix]; newns = [ns copy]; [ns release]; if (count == 0) [self->nsStack addObject:newns]; else [self->nsStack replaceObjectAtIndex:(count - 1) withObject:newns]; [newns release]; } /* ---------- libxml sax connection ---------- */ static void _startElement(libxmlSAXDriver *self, const xmlChar *name, const xmlChar **atts) { NSString *ename, *rawName, *euri; NSDictionary *nsDict = nil; NSRange r; /* first scan for namespace declaration */ if (atts) { NSMutableDictionary *ns = nil; int i; for (i = 0; atts[i]; i += 2) { const xmlChar *an = atts[i]; /* check for attr-names beginning with 'xmlns' */ if (an[0] != 'x') continue; if (an[1] != 'm') continue; if (an[2] != 'l') continue; if (an[3] != 'n') continue; if (an[4] != 's') continue; /* ok, found ns decl */ if (ns == nil) ns = [[NSMutableDictionary alloc] init]; if (an[5] == ':') { /* eg */ NSString *prefix, *uri; if (an[6] == '\0') { /* invalid, namespace name may not be empty ! */ NSLog(@"WARNING(%s): empty namespace prefix !", __PRETTY_FUNCTION__); } prefix = xmlCharsToString(&(an[6])); uri = xmlCharsToString(atts[i + 1]); //NSLog(@"prefix %@ uri %@", prefix, uri); NSCAssert(ns, @"missing namespace dictionary"); [ns setObject:uri forKey:prefix]; if (self->fNamespaces) [self->contentHandler startPrefixMapping:prefix uri:uri]; [prefix release]; prefix = nil; [uri release]; uri = nil; } else { /* eg */ NSString *uri; uri = xmlCharsToString(atts[i + 1]); [ns setObject:uri forKey:@":"]; //NSLog(@"prefix default uri %@", uri); [uri release]; uri = nil; } } nsDict = [ns copy]; [nsDict autorelease]; [ns release]; } /* manage namespace stack */ if (nsDict == nil) nsDict = [NSDictionary dictionary]; NSCAssert(self->nsStack, @"missing namespace stack"); [self->nsStack addObject:nsDict]; /* process element name */ rawName = xmlCharsToString(name); r = [rawName rangeOfString:@":"]; if (r.length > 0) { /* eg: */ NSString *prefix; prefix = [rawName substringToIndex:r.location]; ename = [rawName substringFromIndex:(r.location + r.length)]; euri = [self nsUriForPrefix:prefix]; } else { ename = rawName; euri = [self defaultNamespace]; } /* create sax attrs */ if (self->attrs == nil) self->attrs = [[SaxAttributes alloc] init]; else [self->attrs clear]; if (atts) { int i; for (i = 0; atts[i]; i += 2) { NSString *name, *rawName, *uri; NSString *type, *value; NSRange r; if (!self->fNamespacePrefixes) { if (atts[i][0] == 'x') { const unsigned char *an = atts[i]; if (strstr((char *)an, "xmlns") == (char *)an) continue; } } rawName = xmlCharsToString(atts[i]); r = [rawName rangeOfString:@":"]; if (r.length > 0) { /* explicit attribute namespace, eg '' */ NSString *prefix; prefix = [rawName substringToIndex:r.location]; name = [rawName substringFromIndex:(r.location + r.length)]; uri = [self nsUriForPrefix:prefix]; } else { /* plain attribute, eg '' */ name = rawName; uri = euri; /* attr inherits namespace from element-name */ } type = @"CDATA"; value = xmlCharsToDecodedString(atts[i + 1]); [self->attrs addAttribute:name uri:uri rawName:rawName type:type value:value]; [value release]; value = nil; [rawName release]; rawName = nil; } } self->depth++; /* send notification */ [self->contentHandler startElement:ename namespace:euri rawName:rawName attributes:self->attrs]; [rawName release]; rawName = nil; [self->attrs clear]; } static void _endElement(libxmlSAXDriver *self, const xmlChar *name) { NSString *ename, *rawName, *uri; NSRange r; rawName = xmlCharsToString(name); r = [rawName rangeOfString:@":"]; if (r.length > 0) { /* eg: */ NSString *prefix; prefix = [rawName substringToIndex:r.location]; ename = [rawName substringFromIndex:(r.location + r.length)]; uri = [self nsUriForPrefix:prefix]; } else { ename = rawName; uri = [self defaultNamespace]; } [self->contentHandler endElement:ename namespace:uri rawName:rawName]; self->depth--; [rawName release]; rawName = nil; /* process namespace stack */ if (self->fNamespaces) { NSDictionary *ns; NSEnumerator *keys; NSString *key; ns = [self->nsStack lastObject]; keys = [ns keyEnumerator]; while ((key = [keys nextObject])) { if ([key isEqualToString:@":"]) continue; [self->contentHandler endPrefixMapping:key]; } } [self->nsStack removeLastObject]; } static void _startDocument(libxmlSAXDriver *self) { static NSDictionary *defNS = nil; id keys[2], values[2]; //NSLog(@"start doc 0x%p", self); if (defNS == nil) { keys[0] = @"xml"; values[0] = @"http://www.w3.org/XML/1998/namespace"; keys[1] = @":"; values[1] = @""; defNS = [[NSDictionary alloc] initWithObjects:values forKeys:keys count:2]; } if ([self->nsStack count] == 0) [self->nsStack addObject:defNS]; else [self->nsStack insertObject:defNS atIndex:0]; [self->contentHandler startDocument]; } static void _endDocument(libxmlSAXDriver *self) { [self->contentHandler endDocument]; if ([self->nsStack count] > 0) [self->nsStack removeObjectAtIndex:0]; else { NSLog(@"libxmlSAXDriver: inconsistent state, " @"nothing on NS stack in endDocument !"); } } static void _characters(libxmlSAXDriver *self, const xmlChar *chars, NSUInteger len) { /* need to transform UTF8 to UTF16 */ unichar *data, *ts; if (len == 0) { unichar c = 0; data = &c; [self->contentHandler characters:data length:0]; return; } if (chars == NULL) { [self->contentHandler characters:NULL length:0]; return; } data = ts = calloc(len + 1, sizeof(unichar)); /* GC ?! */ if (_UTF8ToUTF16((void *)&chars, (void *)(chars + len), (void *)&ts, ts + (len * sizeof(unichar)))) { free(data); NSLog(@"ERROR(%s:%i): couldn't convert UTF8 to UTF16 !", __PRETTY_FUNCTION__, __LINE__); } else { [self->contentHandler characters:data length:((NSUInteger)(ts - data))]; free(data); } } static void _ignorableWhiteSpace(libxmlSAXDriver *self, const xmlChar *chars, NSUInteger len) { /* need to transform UTF8 to UTF16 */ unichar *data, *ts; if (len == 0) { unichar c = 0; data = &c; [self->contentHandler ignorableWhitespace:data length:len]; return; } if (chars == NULL) { [self->contentHandler ignorableWhitespace:NULL length:0]; return; } data = ts = calloc(len + 1, sizeof(unichar)); /* GC ?! */ if (_UTF8ToUTF16((void *)&chars, (void *)(chars + len), (void *)&ts, ts + (len * sizeof(unichar)))) { free(data); NSLog(@"ERROR(%s:%i): couldn't convert UTF8 to UTF16 !", __PRETTY_FUNCTION__, __LINE__); } else { [self->contentHandler ignorableWhitespace:data length:(ts - data)]; free(data); } } static void __pi(libxmlSAXDriver *self, const xmlChar *pi, const xmlChar *data) { NSString *epi, *edata; epi = xmlCharsToString(pi); edata = xmlCharsToString(data); [self->contentHandler processingInstruction:epi data:edata]; [epi release]; epi = nil; [edata release]; edata = nil; } static void _comment(libxmlSAXDriver *self, const xmlChar *value) { if (self->lexicalHandler) { /* need to transform UTF8 to UTF16 */ unichar *data; register int i, len; len = strlen((const char *)value); data = calloc(len +1 ,sizeof(unichar)); /* GC ?! */ for (i = 0; i < len; i++) data[i] = value[i]; [self->lexicalHandler comment:data length:len]; if (data) { free(data); data = NULL; } } } static void _setLocator(void *udata, xmlSAXLocatorPtr _locator) { if (activeDriver == nil) { NSLog(@"ERROR(%s): no driver is active !", __PRETTY_FUNCTION__); return; } [activeDriver->locator release]; activeDriver->locator = [[libxmlSAXLocator alloc] initWithSaxLocator:_locator parser:activeDriver]; activeDriver->locator->ctx = activeDriver->ctxt; [activeDriver->contentHandler setDocumentLocator:activeDriver->locator]; } static xmlParserInputPtr _resolveEntity(libxmlSAXDriver *self, const xmlChar *pub, const xmlChar *sys) { NSString *pubId, *sysId; id src; pubId = xmlCharsToString(pub); sysId = xmlCharsToString(sys); src = [self->entityResolver resolveEntityWithPublicId:pubId systemId:sysId]; if (src == nil) { //return xmlLoadExternalEntity(sys, pub, self); return NULL; } NSLog(@"ignored entity src %@", src); [pubId release]; pubId = nil; [sysId release]; sysId = nil; return NULL; } static xmlEntityPtr _getEntity(libxmlSAXDriver *self, const xmlChar *name) { xmlEntityPtr p; NSString *ename, *s; if ((p = xmlGetPredefinedEntity(name))) return p; if (self->entity == NULL) /* setup shared entity structure */ self->entity = calloc(1, sizeof(xmlEntity)); ename = xmlCharsToString(name); s = [self replacementStringForEntityNamed:ename]; /* need to convert to unicode ! */ /* fill entity structure */ p = self->entity; p->name = (unsigned char *)[ename cString]; p->etype = XML_INTERNAL_GENERAL_ENTITY; p->orig = (void *)[ename cString]; p->content = (void *)[s cString]; p->length = [s cStringLength]; [ename release]; ename = nil; return p; } static void _cdataBlock(libxmlSAXDriver *self, const xmlChar *value, NSUInteger len) { [self->lexicalHandler startCDATA]; _characters(self, value, len); [self->lexicalHandler endCDATA]; } static SaxParseException * mkException(libxmlSAXDriver *self, NSString *key, const char *msg, va_list va) { NSString *s, *reason; NSDictionary *ui; SaxParseException *e; NSRange r; int count = 0, i; id keys[7], values[7]; id tmp; s = [NSString stringWithCString:msg]; s = [[[NSString alloc] initWithFormat:s arguments:va] autorelease]; r = [s rangeOfString:@"\n"]; reason = r.length > 0 ? [s substringToIndex:r.location] : s; if ([reason length] == 0) reason = @"unknown reason"; keys[0] = @"parser"; values[0] = self; count++; keys[1] = @"depth"; values[1] = [NSNumber numberWithInt:self->depth]; count++; if ([s length] > 0) { keys[count] = @"errorMessage"; values[count] = s; count++; } if ((i = [self->locator lineNumber]) >= 0) { keys[count] = @"line"; values[count] = [NSNumber numberWithInt:i]; count++; } if ((i = [self->locator columnNumber]) >= 0) { keys[count] = @"column"; values[count] = [NSNumber numberWithInt:i]; count++; } if ((tmp = [self->locator publicId])) { keys[count] = @"publicId"; values[count] = tmp; count++; } if ((tmp = [self->locator systemId])) { keys[count] = @"systemId"; values[count] = tmp; count++; } ui = [NSDictionary dictionaryWithObjects:values forKeys:keys count:count]; e = (id)[SaxParseException exceptionWithName:key reason:reason userInfo:ui]; return e; } static void _warning(libxmlSAXDriver *self, const char *msg, ...) { va_list args; SaxParseException *e; va_start(args, msg); e = mkException(self, @"SAXWarning", msg, args); va_end(args); [self->errorHandler warning:e]; } static void _error(libxmlSAXDriver *self, const char *msg, ...) { va_list args; SaxParseException *e; va_start(args, msg); e = mkException(self, @"SAXError", msg, args); va_end(args); [self->errorHandler error:e]; } static void _fatalError(libxmlSAXDriver *self, const char *msg, ...) { va_list args; SaxParseException *e; va_start(args, msg); e = mkException(self, @"SAXFatalError", msg, args); va_end(args); [self->errorHandler fatalError:e]; } static void _entityDecl(libxmlSAXDriver *self, const xmlChar *name, int type, const xmlChar *publicId, const xmlChar *systemId, xmlChar *content) { NSString *ename, *pubId, *sysId; NSString *value; ename = xmlCharsToString(name); pubId = xmlCharsToString(publicId); sysId = xmlCharsToString(systemId); value = xmlCharsToString(content); switch (type) { case XML_INTERNAL_GENERAL_ENTITY: case XML_INTERNAL_PARAMETER_ENTITY: case XML_INTERNAL_PREDEFINED_ENTITY: [self->declHandler internalEntityDeclaration:ename value:value]; break; case XML_EXTERNAL_GENERAL_PARSED_ENTITY: case XML_EXTERNAL_PARAMETER_ENTITY: [self->declHandler externalEntityDeclaration:ename publicId:pubId systemId:sysId]; break; case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: /* is content really =notationName ??? */ NSLog(@"unparsed ext entity .."); [self->dtdHandler unparsedEntityDeclaration:ename publicId:pubId systemId:sysId notationName:value]; break; default: [NSException raise:@"InvalidEntityType" format:@"don't know entity type with code %i", type]; } [ename release]; [pubId release]; [sysId release]; [value release]; } static void _unparsedEntityDecl(libxmlSAXDriver *self,const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId, const xmlChar *notationName) { if (self->dtdHandler) { NSString *ename, *nname, *pubId, *sysId; ename = xmlCharsToString(name); nname = xmlCharsToString(notationName); pubId = xmlCharsToString(publicId); sysId = xmlCharsToString(systemId); [self->dtdHandler unparsedEntityDeclaration:ename publicId:pubId systemId:sysId notationName:nname]; [ename release]; [nname release]; [pubId release]; [sysId release]; } } static void _notationDecl(libxmlSAXDriver *self, const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId) { if (self->dtdHandler) { NSString *nname, *pubId, *sysId; nname = xmlCharsToString(name); pubId = xmlCharsToString(publicId); sysId = xmlCharsToString(systemId); [self->dtdHandler notationDeclaration:nname publicId:pubId systemId:sysId]; [nname release]; [pubId release]; [sysId release]; } } static NSString *_occurString(xmlElementContentOccur _occurType) __attribute__((unused)); static NSString *_occurString(xmlElementContentOccur _occurType) { switch (_occurType) { case XML_ELEMENT_CONTENT_ONCE: return @""; case XML_ELEMENT_CONTENT_OPT: return @"?"; case XML_ELEMENT_CONTENT_MULT: return @"*"; case XML_ELEMENT_CONTENT_PLUS: return @"+"; } return @""; } static void _addElemModel(xmlElementContentPtr p, NSMutableString *s, int pt) { if (p == NULL) return; switch (p->type) { case XML_ELEMENT_CONTENT_PCDATA: if (pt == -1) [s appendString:@"("]; [s appendString:@"#PCDATA"]; if (pt == -1) [s appendString:@")"]; break; case XML_ELEMENT_CONTENT_ELEMENT: { NSString *ename; ename = xmlCharsToString(p->name); if (pt == -1) [s appendString:@"("]; [s appendString:ename]; if (pt == -1) [s appendString:@")"]; [ename release]; ename = nil; break; } case XML_ELEMENT_CONTENT_SEQ: if (pt != XML_ELEMENT_CONTENT_SEQ) [s appendString:@"("]; _addElemModel(p->c1, s, XML_ELEMENT_CONTENT_SEQ); [s appendString:@","]; _addElemModel(p->c2, s, XML_ELEMENT_CONTENT_SEQ); if (pt != XML_ELEMENT_CONTENT_SEQ) [s appendString:@")"]; break; case XML_ELEMENT_CONTENT_OR: if (pt != XML_ELEMENT_CONTENT_OR) [s appendString:@"("]; _addElemModel(p->c1, s, XML_ELEMENT_CONTENT_OR); [s appendString:@"|"]; _addElemModel(p->c2, s, XML_ELEMENT_CONTENT_OR); if (pt != XML_ELEMENT_CONTENT_OR) [s appendString:@")"]; break; } switch (p->ocur) { case XML_ELEMENT_CONTENT_ONCE: break; case XML_ELEMENT_CONTENT_OPT: [s appendString:@"?"]; break; case XML_ELEMENT_CONTENT_MULT: [s appendString:@"*"]; break; case XML_ELEMENT_CONTENT_PLUS: [s appendString:@"+"]; break; } } static void _elementDecl(libxmlSAXDriver *self, const xmlChar *name, int type, xmlElementContentPtr content) { if (self->declHandler) { NSString *ename, *model; ename = xmlCharsToString(name); if (content) { NSMutableString *emodel; emodel = [[NSMutableString alloc] init]; _addElemModel(content, emodel, -1); model = [[emodel copy] autorelease]; [emodel release]; } else model = nil; [self->declHandler elementDeclaration:ename contentModel:model]; [ename release]; ename = nil; } } static void _attrDecl(libxmlSAXDriver *self, const xmlChar *elem, const xmlChar *name, int type, int def, const xmlChar *defaultValue, xmlEnumerationPtr tree) { if (self->declHandler) { NSString *ename, *aname, *defValue, *atype, *defType; ename = xmlCharsToString(elem); aname = xmlCharsToString(name); defValue = xmlCharsToString(defaultValue); atype = nil; defType = nil; switch (type) { case XML_ATTRIBUTE_CDATA: atype = @"CDATA"; break; case XML_ATTRIBUTE_ID: atype = @"ID"; break; case XML_ATTRIBUTE_IDREF: atype = @"IDREF"; break; case XML_ATTRIBUTE_IDREFS: atype = @"IDREFS"; break; case XML_ATTRIBUTE_ENTITY: atype = @"ENTITY"; break; case XML_ATTRIBUTE_ENTITIES: atype = @"ENTITIES"; break; case XML_ATTRIBUTE_NMTOKEN: atype = @"NMTOKEN"; break; case XML_ATTRIBUTE_NMTOKENS: atype = @"NMTOKENS"; break; case XML_ATTRIBUTE_ENUMERATION: atype = @"ENUMERATION"; break; case XML_ATTRIBUTE_NOTATION: atype = @"NOTATION"; break; default: [NSException raise:@"InvalidAttributeType" format:@"don't know attr type with code %i", type]; } switch (def) { case XML_ATTRIBUTE_NONE: defType = nil; break; case XML_ATTRIBUTE_REQUIRED: defType = @"#REQUIRED"; break; case XML_ATTRIBUTE_IMPLIED: defType = @"#IMPLIED"; break; case XML_ATTRIBUTE_FIXED: defType = @"#FIXED"; break; default: [NSException raise:@"InvalidAttributeDefaultType" format:@"don't know attr default type with code %i", def]; } [self->declHandler attributeDeclaration:aname elementName:ename type:atype defaultType:defType defaultValue:defValue]; [ename release]; [aname release]; [defValue release]; } } #if 0 static int isStandalone(libxmlSAXDriver *self) { } static int hasInternalSubset(libxmlSAXDriver *self) { } static int hasExternalSubset(libxmlSAXDriver *self) { } #endif static void _externalSubset(libxmlSAXDriver *ctx, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID) { } static void _internalSubset(libxmlSAXDriver *ctx, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID) { } static void _reference(libxmlSAXDriver *ctx, const xmlChar *name) { #if 0 NSString *refName; refName = xmlCharsToString(name); NSLog(@"reference: '%@'", refName); [refName release]; #endif } @end /* libxmlSAXDriver */ #include "unicode.h" SOPE/sope-xml/libxmlSAXDriver/libxmlSAXDriver-Info.plist0000644000000000000000000000144215004363604022074 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable libxmlSAXDriver CFBundleGetInfoString CFBundleIconFile CFBundleIdentifier org.OpenGroupware.sope-xml.libxmlSAXDriver CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleShortVersionString CFBundleSignature ???? CFBundleVersion 4.7.26 SOPE/sope-xml/libxmlSAXDriver/COPYRIGHT0000644000000000000000000000010615004363604016376 0ustar rootrootCopyright (C) 2000-2005 SKYRIX Software AG Contact: info@skyrix.com SOPE/sope-xml/libxmlSAXDriver/libxmlHTMLSAXDriver.m0000644000000000000000000005513315004363604020777 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "libxmlHTMLSAXDriver.h" #import "libxmlSAXLocator.h" #include "TableCallbacks.h" #include #include #include "common.h" #include #include #include @interface NSObject(contentHandlerExtensions) - (xmlCharEncoding)contentEncoding; @end @interface libxmlHTMLSAXDriver(PrivateMethods) - (void)tearDownParser; - (BOOL)walkDocumentTree:(xmlDocPtr)_doc; - (BOOL)processNode:(xmlNodePtr)_node; - (BOOL)processChildren:(xmlNodePtr)children; @end static int _UTF8ToUTF16(unsigned char **sourceStart, unsigned char *sourceEnd, unichar **targetStart, const unichar *targetEnd); static BOOL logUnsupportedFeatures = NO; static BOOL reportInvalidTags = NO; static BOOL reportUnclosedEntities = NO; static NSMapTable *uniqueStrings = NULL; // THREAD static Class NSStringClass = Nil; /* error string detection */ /* TODO: obviously this may change between libxml versions or even localisations ... why doesn't libxml support error codes ? (or does it ?) */ static const char *tagInvalidMsg = "tag %s invalid"; static const char *unclosedEntityInvalidMsg = "htmlParseEntityRef: expecting ';'"; #if 0 static const char *unexpectedNobrCloseMsg = "Unexpected end tag : %s"; #endif static inline NSString *xmlCharsToString(const xmlChar *_s) { NSString *s; char *newkey; if (_s == NULL) return nil; if (uniqueStrings == NULL) { uniqueStrings = NSCreateMapTable(libxmlNonOwnedCStringMapKeyCallBacks, NSObjectMapValueCallBacks, 128); } else if ((s = NSMapGet(uniqueStrings, _s))) { /* found a string in cache ... */ return [s retain]; } newkey = malloc(strlen((char *)_s) + 2); strcpy(newkey, (char *)_s); if (NSStringClass == Nil) NSStringClass = [NSString class]; s = [[NSStringClass alloc] initWithUTF8String:(const char *)_s]; NSMapInsert(uniqueStrings, newkey, s); return s; } static NSString *SaxDeclHandlerProperty = @"http://xml.org/sax/properties/declaration-handler"; static NSString *SaxLexicalHandlerProperty = @"http://xml.org/sax/properties/lexical-handler"; static NSString *XMLNS_XHTML = @"http://www.w3.org/1999/xhtml"; @implementation libxmlHTMLSAXDriver static libxmlHTMLSAXDriver *activeDriver = nil; static void warning(void *udata, const char *msg, ...); static void error(void *udata, const char *msg, ...); static void fatalError(void *udata, const char *msg, ...); static void setLocator(void *udata, xmlSAXLocatorPtr _locator); + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; reportInvalidTags = [ud boolForKey:@"libxmlHTMLSAXDriverReportInvalidTags"]; reportUnclosedEntities = [ud boolForKey:@"libxmlHTMLSAXDriverReportUnclosedEntityRefs"]; } - (id)init { if ((self = [super init])) { self->namespaceURI = [XMLNS_XHTML copy]; self->encodeEntities = NO; } return self; } - (void)dealloc { [self tearDownParser]; [self->attributes release]; [self->namespaceURI release]; [self->lexicalHandler release]; [self->declHandler release]; [self->contentHandler release]; [self->dtdHandler release]; [self->errorHandler release]; [self->entityResolver release]; [super dealloc]; } /* features & properties */ - (void)setFeature:(NSString *)_name to:(BOOL)_value { if (logUnsupportedFeatures) NSLog(@"%s: don't know feature %@", __PRETTY_FUNCTION__, _name); } - (BOOL)feature:(NSString *)_name { if (logUnsupportedFeatures) NSLog(@"%s: don't know feature %@", __PRETTY_FUNCTION__, _name); return NO; } - (void)setProperty:(NSString *)_name to:(id)_value { if ([_name isEqualToString:SaxLexicalHandlerProperty]) { ASSIGN(self->lexicalHandler, _value); return; } if ([_name isEqualToString:SaxDeclHandlerProperty]) { ASSIGN(self->declHandler, _value); return; } [SaxNotRecognizedException raise:@"PropertyException" format:@"don't know property %@", _name]; } - (id)property:(NSString *)_name { if ([_name isEqualToString:SaxLexicalHandlerProperty]) return self->lexicalHandler; if ([_name isEqualToString:SaxDeclHandlerProperty]) return self->declHandler; [SaxNotRecognizedException raise:@"PropertyException" format:@"don't know property %@", _name]; return nil; } /* handlers */ - (void)setDTDHandler:(id)_handler { ASSIGN(self->dtdHandler, _handler); } - (id)dtdHandler { return self->dtdHandler; } - (void)setErrorHandler:(id)_handler { ASSIGN(self->errorHandler, _handler); } - (id)errorHandler { return self->errorHandler; } - (void)setEntityResolver:(id)_handler { ASSIGN(self->entityResolver, _handler); } - (id)entityResolver { return self->entityResolver; } - (void)setContentHandler:(id )_handler { ASSIGN(self->contentHandler, _handler); } - (id )contentHandler { return self->contentHandler; } /* libxml */ - (void)setupParserWithDocumentPath:(NSString *)_path { xmlSAXHandler sax; xmlCharEncoding charEncoding; if (self->ctxt != NULL) { NSLog(@"WARNING(%s): HTML parser context already setup !", __PRETTY_FUNCTION__); [self tearDownParser]; } memcpy(&sax, &htmlDefaultSAXHandler, sizeof(xmlSAXHandler)); sax.error = error; sax.warning = warning; sax.fatalError = fatalError; sax.setDocumentLocator = setLocator; if (activeDriver != nil) { NSLog(@"WARNING(%s): %@ there is an active driver set (%@), override !", __PRETTY_FUNCTION__, self, activeDriver); } activeDriver = self; // hh: thats really a very ugly hack. The content-handler is for handling // content, not for dealing with the input data. // TBD: the charset should be derived from the input (and this method should // probably take a charset) if ([self->contentHandler respondsToSelector:@selector(contentEncoding)]) charEncoding = [self->contentHandler contentEncoding]; else charEncoding = XML_CHAR_ENCODING_8859_1; // TBD: do not use cString (nor UTF8String) but NSFileManager to convert // a string into a path self->ctxt = htmlCreatePushParserCtxt(&sax /* sax */, NULL /*self*/ /* userdata */, NULL /* chunk */, 0 /* chunklen */, [_path cString] /* filename */, charEncoding /* encoding */); self->doc = NULL; } - (void)tearDownParser { if (activeDriver == self) activeDriver = nil; if (self->doc) { xmlFreeDoc(self->doc); self->doc = NULL; } if (self->ctxt) { htmlFreeParserCtxt(self->ctxt); self->ctxt = NULL; } } /* IO */ - (int)pushBytes:(const char *)_bytes count:(unsigned)_len { int r; r = 0; if (_len == 0) return r; NSAssert(self->ctxt, @"missing HTML parser context"); r = htmlParseChunk(self->ctxt, _bytes, _len, 0); return r; } - (int)pushEOF { char dummyByte; int r; r = htmlParseChunk(self->ctxt, &dummyByte, 0, 1 /* terminate */); self->doc = ((xmlParserCtxtPtr)ctxt)->myDoc; return r; } /* parsing */ - (void)_handleEmptyDataInSystemId:(NSString *)_sysId { /* An empty HTML file _is_ valid?! I guess it equals to , wrong? => hh */ [self->contentHandler startDocument]; [self->contentHandler startPrefixMapping:@"" uri:self->namespaceURI]; [self->contentHandler startElement:@"html" namespace:XMLNS_XHTML rawName:@"html" attributes:nil]; [self->contentHandler startElement:@"body" namespace:XMLNS_XHTML rawName:@"body" attributes:nil]; [self->contentHandler endElement:@"body" namespace:XMLNS_XHTML rawName:@"body"]; [self->contentHandler endElement:@"html" namespace:XMLNS_XHTML rawName:@"html"]; [self->contentHandler endPrefixMapping:@""]; [self->contentHandler endDocument]; } - (void)_parseFromData:(NSData *)_data systemId:(NSString *)_sysId { NSAutoreleasePool *pool; SaxParseException *e; int errCode; if ([_data length] == 0) { [self _handleEmptyDataInSystemId:_sysId]; return; } pool = [[NSAutoreleasePool alloc] init]; /* parse into structure */ [self setupParserWithDocumentPath:_sysId]; errCode = [self pushBytes:[_data bytes] count:[_data length]]; if (XML_ERR_INTERNAL_ERROR == errCode) { e = (id)[SaxParseException exceptionWithName:@"SaxIOException" reason:[NSString stringWithFormat: @"Error XML parsing : %i", errCode] userInfo:[NSDictionary dictionaryWithObject: [NSNumber numberWithInt: errCode] forKey:@"code"]]; if (self->errorHandler) [self->errorHandler fatalError: e]; } [self pushEOF]; if (self->doc == NULL) { NSLog(@"Could not parse HTML file: %@", _sysId); [self tearDownParser]; } else { [self walkDocumentTree:self->doc]; [self tearDownParser]; } [pool release]; } - (void)parseFromSource:(id)_source systemId:(NSString *)_sysId { NSAutoreleasePool *pool; pool = [[NSAutoreleasePool alloc] init]; if ([_source isKindOfClass:[NSData class]]) { [self _parseFromData:_source systemId:_sysId]; return; } if ([_source isKindOfClass:[NSString class]]) { [self _parseFromData:[_source dataUsingEncoding:NSISOLatin1StringEncoding] systemId:_sysId]; return; } if ([_source isKindOfClass:[NSURL class]]) { NSData *data; data = [_source isFileURL] ? (NSData *)[NSData dataWithContentsOfMappedFile:[_source path]] : [_source resourceDataUsingCache:YES]; [self _parseFromData:data systemId:[_source absoluteString]]; return; } { SaxParseException *e; NSDictionary *ui; ui = [[NSDictionary alloc] initWithObjectsAndKeys: _source ? _source : (id)@"", @"source", self, @"parser", nil]; e = (id)[SaxParseException exceptionWithName:@"SaxIOException" reason:@"can not handle data-source" userInfo:ui]; [ui release]; ui = nil; [self->errorHandler fatalError:e]; } [self tearDownParser]; [pool release]; } - (void)parseFromSource:(id)_source { if ([_source isKindOfClass:[NSString class]]) [self parseFromSource:_source systemId:@""]; else if ([_source isKindOfClass:[NSData class]]) [self parseFromSource:_source systemId:@""]; else if ([_source isKindOfClass:[NSURL class]]) [self parseFromSource:_source systemId:[_source absoluteString]]; else [self parseFromSource:_source systemId:@""]; } - (void)parseFromSystemId:(NSString *)_sysId { NSAutoreleasePool *pool; NSData *data; if (![_sysId hasPrefix:@"file://"]) { /* exception */ return; } pool = [[NSAutoreleasePool alloc] init]; /* cut off file:// */ _sysId = [_sysId substringFromIndex:7]; /* load data */ data = [NSData dataWithContentsOfFile:_sysId]; [self _parseFromData:data systemId:_sysId]; [pool release]; } /* process attribute nodes */ - (void)processAttributes:(xmlAttrPtr)_attributes { xmlAttrPtr attribute; /* setup or clear attribute cache */ if (self->attributes == nil) attributes = [[SaxAttributes alloc] init]; else [attributes clear]; if (_attributes == NULL) /* nothing to process */ return; /* add attributes */ for (attribute = _attributes; attribute; attribute = attribute->next) { NSString *name, *xhtmlName; NSString *value; #if 0 printf("attr name '%s' has NS '%s'\n", attribute->name, attribute->ns ? "yes" : "no"); #endif name = xmlCharsToString(attribute->name); xhtmlName = [name lowercaseString]; value = @""; if (attribute->children) { xmlChar *t; if ((t = xmlNodeListGetString(doc, attribute->children, 0))) { value = xmlCharsToString(t); free(t); /* should be xmlFree ?? */ } } [attributes addAttribute:xhtmlName uri:self->namespaceURI rawName:name type:@"CDATA" value:value]; [name release]; name = nil; [value release]; value = nil; } return; } /* walking the tree, generating SAX events */ - (BOOL)processEntityRefNode:(xmlNodePtr)node { NSLog(@"Ignoring entity ref: '%s'\n", node->name); return YES; } - (BOOL)processDocumentNode:(xmlNodePtr)node { BOOL result; [self->contentHandler startDocument]; [self->contentHandler startPrefixMapping:@"" uri:self->namespaceURI]; result = [self processChildren:node->children]; [self->contentHandler endPrefixMapping:@""]; [self->contentHandler endDocument]; return result; } - (BOOL)processTextNode:(xmlNodePtr)_node { static unichar c = '\0'; xmlChar *chars; NSUInteger len; if (self->contentHandler == nil) return YES; if (_node->content == NULL) { [self->contentHandler characters:&c length:0]; return YES; } if (self->encodeEntities) { /* should use the HTML encoding routine (htmlEncodeEntities) ??? */ chars = xmlEncodeEntitiesReentrant(self->doc, _node->content); } else chars = _node->content; if (chars == NULL) { [self->contentHandler characters:&c length:0]; return YES; } if ((len = strlen((char *)chars)) == 0) { unichar c = '\0'; [self->contentHandler characters:&c length:0]; return YES; } { void *data, *ts; data = ts = calloc(len + 2, sizeof(unichar)); /* GC ?! */ if (_UTF8ToUTF16((void *)&chars, (void *)(chars + len), (void *)&ts, ts + (len * sizeof(unichar)))) { NSLog(@"ERROR(%s:%i): couldn't convert UTF8 to UTF16 !", __PRETTY_FUNCTION__, __LINE__); if (data) free(data); return NO; } len = (ts - data) / 2; [self->contentHandler characters:data length:len]; if (data) free(data); } return YES; } - (BOOL)processCommentNode:(xmlNodePtr)_node { unichar c = '\0'; if (self->lexicalHandler == nil) return YES; if (_node->content) { xmlChar *chars; /* uses the HTML encoding routine !!!!!!!!!! */ chars = xmlEncodeEntitiesReentrant(self->doc, _node->content); if (chars == NULL) { [self->lexicalHandler comment:&c length:0]; } else { unsigned len; if ((len = strlen((char *)chars)) > 0) { void *data, *ts; data = ts = calloc(len + 1, sizeof(unichar)); /* GC ?! */ if (_UTF8ToUTF16((void *)&chars, (void *)(chars + len), (void *)&ts, ts + (len * sizeof(unichar)))) { free(data); NSLog(@"ERROR(%s:%i): couldn't convert UTF8 to UTF16 !", __PRETTY_FUNCTION__, __LINE__); return NO; } len = (ts - data) / 2; [self->lexicalHandler comment:data length:len]; free(data); } else { unichar c = '\0'; [self->lexicalHandler comment:&c length:0]; } } } else [self->lexicalHandler comment:&c length:0]; return YES; } - (BOOL)processDTDNode:(xmlNodePtr)node { /* do nothing with DTD nodes .. */ return YES; } - (BOOL)processEntityNode:(xmlNodePtr)node { /* do nothing with entity nodes .. */ NSLog(@"%s:%i: ignoring entity node ..", __PRETTY_FUNCTION__, __LINE__); return YES; } - (BOOL)processPINode:(xmlNodePtr)node { /* do nothing with PI nodes .. */ return YES; } - (BOOL)processElementNode:(xmlNodePtr)node { NSString *tagName, *xhtmlName; BOOL result; self->depth++; tagName = xmlCharsToString(node->name); xhtmlName = [tagName lowercaseString]; [self processAttributes:node->properties]; [self->contentHandler startElement:xhtmlName namespace:self->namespaceURI rawName:tagName attributes:self->attributes]; [self->attributes clear]; result = [self processChildren:node->children]; [self->contentHandler endElement:xhtmlName namespace:self->namespaceURI rawName:tagName]; self->depth--; [tagName release]; return result; } - (BOOL)processChildren:(xmlNodePtr)children { xmlNodePtr node; if (children == NULL) return YES; for (node = children; node; node = node->next) { [self processNode:node]; } return YES; } - (BOOL)processNode:(xmlNodePtr)_node { switch(_node->type) { case XML_ELEMENT_NODE: return [self processElementNode:_node]; case XML_ATTRIBUTE_NODE: NSLog(@"invalid place for attribute-node !"); return NO; case HTML_TEXT_NODE: return [self processTextNode:_node]; case XML_CDATA_SECTION_NODE: return [self processTextNode:_node]; case HTML_ENTITY_REF_NODE: return [self processEntityRefNode:_node]; case XML_ENTITY_NODE: return [self processEntityNode:_node]; case XML_PI_NODE: return [self processPINode:_node]; case HTML_COMMENT_NODE: return [self processCommentNode:_node]; case XML_HTML_DOCUMENT_NODE: return [self processDocumentNode:_node]; case XML_DTD_NODE: return [self processDTDNode:_node]; default: NSLog(@"WARNING: UNKNOWN node type %i\n", _node->type); break; } return NO; } - (BOOL)walkDocumentTree:(xmlDocPtr)_doc { int type; BOOL result; type = ((xmlDocPtr)self->doc)->type; ((xmlDocPtr)self->doc)->type = XML_HTML_DOCUMENT_NODE; result = [self processNode:(xmlNodePtr)self->doc]; ((xmlDocPtr)self->doc)->type = type; return result; } /* callbacks */ static SaxParseException * mkException(libxmlHTMLSAXDriver *self, NSString *key, const char *msg, va_list va) { NSString *s, *reason; NSDictionary *ui; SaxParseException *e; int count = 0, i; id keys[7], values[7]; id tmp; NSRange r; s = [NSString stringWithCString:msg]; s = [[[NSString alloc] initWithFormat:s arguments:va] autorelease]; r = [s rangeOfString:@"\n"]; reason = (r.length > 0) ? [s substringToIndex:r.location] : s; if ([reason length] == 0) reason = @"unknown reason"; keys[0] = @"parser"; values[0] = self; count++; keys[1] = @"depth"; values[1] = [NSNumber numberWithInt:self->depth]; count++; if ([s length] > 0) { keys[count] = @"errorMessage"; values[count] = s; count++; } // NSLog(@"locator: %@", self->locator); if ((i = [self->locator lineNumber]) >= 0) { keys[count] = @"line"; values[count] = [NSNumber numberWithInt:i]; count++; } if ((i = [self->locator columnNumber]) >= 0) { keys[count] = @"column"; values[count] = [NSNumber numberWithInt:i]; count++; } if ((tmp = [self->locator publicId])) { keys[count] = @"publicId"; values[count] = tmp; count++; } if ((tmp = [self->locator systemId])) { keys[count] = @"systemId"; values[count] = tmp; count++; } ui = [NSDictionary dictionaryWithObjects:values forKeys:keys count:count]; e = (id)[SaxParseException exceptionWithName:key reason:reason userInfo:ui]; return e; } static void warning(void *udata, const char *msg, ...) { va_list args; SaxParseException *e; if (activeDriver == nil) { NSLog(@"ERROR(%s): no driver is active !", __PRETTY_FUNCTION__); return; } va_start(args, msg); e = mkException(activeDriver, @"SAXWarning", msg, args); va_end(args); [activeDriver->errorHandler warning:e]; } static void error(void *udata, const char *msg, ...) { va_list args; SaxParseException *e; if (!reportInvalidTags && msg != NULL) { if (toupper((unsigned char) msg[0]) == 'T') { if (strncasecmp(tagInvalidMsg, msg, strlen(tagInvalidMsg)) == 0) return; } #if 0 else if (toupper((unsigned char) msg[0]) == 'U') { if (strncasecmp(unexpectedNobrCloseMsg, msg, strlen(unexpectedNobrCloseMsg)) == 0) return; printf("MSG: '%s'\n", msg); } #endif } if (!reportUnclosedEntities && msg != NULL && toupper((unsigned char) msg[0]) == 'H') { if (strncasecmp(unclosedEntityInvalidMsg, msg, strlen(unclosedEntityInvalidMsg)) == 0) return; } if (activeDriver == nil) { NSLog(@"ERROR(%s): no driver is active !", __PRETTY_FUNCTION__); return; } /* msg is a format, eg 'tag %s is invalid' */ va_start(args, msg); e = mkException(activeDriver, @"SAXError", msg, args); va_end(args); [activeDriver->errorHandler error:e]; } static void fatalError(void *udata, const char *msg, ...) { va_list args; SaxParseException *e; if (activeDriver == nil) { NSLog(@"ERROR(%s): no driver is active !", __PRETTY_FUNCTION__); return; } va_start(args, msg); e = mkException(activeDriver, @"SAXFatalError", msg, args); va_end(args); [activeDriver->errorHandler fatalError:e]; } static void setLocator(void *udata, xmlSAXLocatorPtr _locator) { if (activeDriver == nil) { NSLog(@"ERROR(%s): no driver is active !", __PRETTY_FUNCTION__); return; } [activeDriver->locator release]; activeDriver->locator = [[libxmlSAXLocator alloc] initWithSaxLocator:_locator parser:activeDriver]; activeDriver->locator->ctx = activeDriver->ctxt; [activeDriver->contentHandler setDocumentLocator:activeDriver->locator]; } @end /* libxmlHTMLSAXDriver */ #include "unicode.h" SOPE/sope-xml/libxmlSAXDriver/TableCallbacks.m0000644000000000000000000000445615004363604020124 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "TableCallbacks.h" #include "common.h" #include //#define NSNonOwnedCStringMapKeyCallBacks NSNonOwnedPointerMapKeyCallBacks /* From Aho, Sethi & Ullman: Principles of compiler design. */ static unsigned __hashCString(void *table, const void *aString) { register const char* p = (char*)aString; register unsigned hash = 0, hash2; register int i, n; n = aString ? strlen(aString) : 0; for(i=0; i < n; i++) { hash <<= 4; hash += *p++; if((hash2 = hash & 0xf0000000)) hash ^= (hash2 >> 24) ^ hash2; } return hash; } static BOOL __compareCString(void *table, const void *anObject1, const void *anObject2) { if (anObject1 == NULL && anObject2 == NULL) return YES; if (anObject1 == NULL || anObject2 == NULL) return NO; return strcmp((char*)anObject1, (char*)anObject2) == 0; } static void __retain(void *table, const void *anObject) {} static void TableCallbacksRelease(void *table, void *anObject) {} static NSString *__describe(void *table, const void *anObject) { return [NSString stringWithFormat:@"%p", anObject]; } const NSMapTableKeyCallBacks libxmlNonOwnedCStringMapKeyCallBacks = { (NSUInteger(*)(NSMapTable *, const void *))__hashCString, (BOOL(*)(NSMapTable *, const void *, const void *))__compareCString, (void (*)(NSMapTable *, const void *anObject))__retain, (void (*)(NSMapTable *, void *anObject))TableCallbacksRelease, (NSString *(*)(NSMapTable *, const void *))__describe, (const void *)NULL }; SOPE/sope-xml/libxmlSAXDriver/GNUmakefile.preamble0000644000000000000000000000215115004363604020745 0ustar rootroot# compilation settings ifeq ($(frameworks),yes) BUNDLE_INSTALL_DIR := $(FRAMEWORK_INSTALL_DIR)/SaxObjC.framework/Resources/SaxDrivers/ endif ADDITIONAL_CPPFLAGS += -funsigned-char ADDITIONAL_INCLUDE_DIRS += -I../.. -I.. ADDITIONAL_INCLUDE_DIRS += $(shell xml2-config --cflags) libxml_LIBS := $(shell xml2-config --libs) ifneq ($(frameworks),yes) libxmlSAXDriver_BUNDLE_LIBS += -lSaxObjC $(libxml_LIBS) else libxmlSAXDriver_BUNDLE_LIBS += -framework SaxObjC $(libxml_LIBS) endif # library/framework search pathes DEP_DIRS = ../SaxObjC ifneq ($(frameworks),yes) ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),\ -L$(GNUSTEP_BUILD_DIR)/$(dir)/$(GNUSTEP_OBJ_DIR_NAME)) else ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir)) endif ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) SYSTEM_LIB_DIR += -L/usr/local/lib64 -L/usr/lib64 else SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib endif # platform specific options ifeq ($(GNUSTEP_TARGET_OS),darwin6) ADDITIONAL_LIB_DIRS += -L/sw/lib endif ifeq ($(FOUNDATION_LIB),nx) libxmlSAXDriver_LDFLAGS += -framework Foundation endif SOPE/sope-xml/libxmlSAXDriver/libxmlDocSAXDriver.m0000644000000000000000000004473215004363604020743 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "libxmlDocSAXDriver.h" #import "libxmlSAXLocator.h" #include #include #include "common.h" #include #include #include @interface libxmlDocSAXDriver(PrivateMethods) - (void)tearDownParser; - (BOOL)walkDocumentTree:(xmlDocPtr)_doc; - (BOOL)processNode:(xmlNodePtr)_node; - (BOOL)processTextNode:(xmlNodePtr)_node; - (BOOL)processChildren:(xmlNodePtr)children; @end static int _UTF8ToUTF16(unsigned char **sourceStart, unsigned char *sourceEnd, unichar **targetStart, const unichar *targetEnd); static inline NSString *xmlCharsToString(const xmlChar *_s) { static Class NSStringClass = Nil; if (NSStringClass == Nil) NSStringClass = [NSString class]; return _s ? [[NSStringClass alloc] initWithUTF8String:(const char*)_s] : nil; } static NSString *SaxDeclHandlerProperty = @"http://xml.org/sax/properties/declaration-handler"; static NSString *SaxLexicalHandlerProperty = @"http://xml.org/sax/properties/lexical-handler"; @implementation libxmlDocSAXDriver static libxmlDocSAXDriver *activeDriver = nil; static void warning(void *udata, const char *msg, ...); static void error(void *udata, const char *msg, ...); static void fatalError(void *udata, const char *msg, ...); static void setLocator(void *udata, xmlSAXLocatorPtr _locator); - (id)init { if ((self = [super init])) { self->encodeEntities = NO; } return self; } - (void)dealloc { [self tearDownParser]; [self->lexicalHandler release]; [self->declHandler release]; [self->contentHandler release]; [self->dtdHandler release]; [self->errorHandler release]; [self->entityResolver release]; [super dealloc]; } /* features & properties */ - (void)setFeature:(NSString *)_name to:(BOOL)_value { [SaxNotRecognizedException raise:@"FeatureException" format:@"don't know feature %@", _name]; } - (BOOL)feature:(NSString *)_name { [SaxNotRecognizedException raise:@"FeatureException" format:@"don't know feature %@", _name]; return NO; } - (void)setProperty:(NSString *)_name to:(id)_value { if ([_name isEqualToString:SaxLexicalHandlerProperty]) { ASSIGN(self->lexicalHandler, _value); return; } if ([_name isEqualToString:SaxDeclHandlerProperty]) { ASSIGN(self->declHandler, _value); return; } [SaxNotRecognizedException raise:@"PropertyException" format:@"don't know property %@", _name]; } - (id)property:(NSString *)_name { if ([_name isEqualToString:SaxLexicalHandlerProperty]) return self->lexicalHandler; if ([_name isEqualToString:SaxDeclHandlerProperty]) return self->declHandler; [SaxNotRecognizedException raise:@"PropertyException" format:@"don't know property %@", _name]; return nil; } /* handlers */ - (void)setDTDHandler:(id)_handler { ASSIGN(self->dtdHandler, _handler); } - (id)dtdHandler { return self->dtdHandler; } - (void)setErrorHandler:(id)_handler { ASSIGN(self->errorHandler, _handler); } - (id)errorHandler { return self->errorHandler; } - (void)setEntityResolver:(id)_handler { ASSIGN(self->entityResolver, _handler); } - (id)entityResolver { return self->entityResolver; } - (void)setContentHandler:(id)_handler { ASSIGN(self->contentHandler, _handler); } - (id)contentHandler { return self->contentHandler; } /* libxml */ - (void)setupParserWithDocumentPath:(NSString *)_path { static xmlSAXHandler sax; NSAssert(self->ctxt == NULL, @"DocSAX parser context already setup !"); memcpy(&sax, &xmlDefaultSAXHandler, sizeof(xmlSAXHandler)); sax.error = error; sax.warning = warning; sax.fatalError = fatalError; sax.setDocumentLocator = setLocator; NSAssert(activeDriver == nil, @"a parser is already running !"); activeDriver = self; self->ctxt = xmlCreatePushParserCtxt(&sax /* sax */, NULL /*self*/ /* userdata */, NULL /* chunk */, 0 /* chunklen */, [_path cString] /* filename */); self->doc = NULL; } - (void)tearDownParser { if (activeDriver == self) activeDriver = nil; if (self->doc) { xmlFreeDoc(self->doc); self->doc = NULL; } if (self->ctxt) { xmlFreeParserCtxt(self->ctxt); self->ctxt = NULL; } } /* IO */ - (void)pushBytes:(const char *)_bytes count:(unsigned)_len { if (_len == 0) return; NSAssert(self->ctxt, @"missing DocSAX parser context"); xmlParseChunk(self->ctxt, _bytes, _len, 0); } - (void)pushEOF { char dummyByte; xmlParseChunk(self->ctxt, &dummyByte, 0, 1 /* terminate */); self->doc = ((xmlParserCtxtPtr)ctxt)->myDoc; } /* parsing */ - (void)_parseFromData:(NSData *)_data systemId:(NSString *)_sysId { NSAutoreleasePool *pool; pool = [[NSAutoreleasePool alloc] init]; /* parse into structure */ [self setupParserWithDocumentPath:_sysId]; [self pushBytes:[_data bytes] count:[_data length]]; [self pushEOF]; if (self->doc == NULL) { NSLog(@"Couldn't parse file: %@", _sysId); [self tearDownParser]; } else { //NSLog(@"parsed file: %@", _sysId); [self walkDocumentTree:self->doc]; [self tearDownParser]; } [pool release]; } - (void)parseFromSource:(id)_source systemId:(NSString *)_sysId { if ([_source isKindOfClass:[NSData class]]) { [self _parseFromData:_source systemId:nil]; return; } if ([_source isKindOfClass:[NSString class]]) { [self _parseFromData:[_source dataUsingEncoding:NSISOLatin1StringEncoding] systemId:nil]; return; } if ([_source isKindOfClass:[NSURL class]]) { NSData *data; data = [_source isFileURL] ? (NSData *)[NSData dataWithContentsOfMappedFile:[_source path]] : [_source resourceDataUsingCache:YES]; [self _parseFromData:data systemId:[_source absoluteString]]; return; } { SaxParseException *e; NSDictionary *ui; ui = [[NSDictionary alloc] initWithObjectsAndKeys: _source ? _source : (id)@"", @"source", self, @"parser", nil]; e = (id)[SaxParseException exceptionWithName:@"SaxIOException" reason:@"cannot handle data-source" userInfo:ui]; [ui release]; ui = nil; [self->errorHandler fatalError:e]; } } - (void)parseFromSource:(id)_source { if ([_source isKindOfClass:[NSString class]]) [self parseFromSource:_source systemId:@""]; else if ([_source isKindOfClass:[NSData class]]) [self parseFromSource:_source systemId:@""]; else if ([_source isKindOfClass:[NSURL class]]) [self parseFromSource:_source systemId:[_source absoluteString]]; else [self parseFromSource:_source systemId:@""]; } - (void)parseFromSystemId:(NSString *)_sysId { NSAutoreleasePool *pool; NSData *data; if (![_sysId hasPrefix:@"file://"]) { /* exception */ return; } pool = [[NSAutoreleasePool alloc] init]; /* cut off file:// */ _sysId = [_sysId substringFromIndex:7]; /* load data */ data = [NSData dataWithContentsOfFile:_sysId]; [self _parseFromData:data systemId:_sysId]; [pool release]; } /* process attribute nodes */ - (SaxAttributes *)processAttributes:(xmlAttrPtr)_attributes { xmlAttrPtr attribute; SaxAttributes *attributes; if (_attributes == NULL) /* nothing to process */ return nil; /* setup or clear attribute cache */ attributes = [[SaxAttributes alloc] init]; /* add attributes */ for (attribute = _attributes; attribute; attribute = attribute->next) { NSString *name; NSString *value; NSString *nsuri; #if 0 printf("attr name '%s' has NS '%s'\n", attribute->name, attribute->ns ? "yes" : "no"); #endif name = xmlCharsToString(attribute->name); value = @""; if (attribute->children) { xmlChar *t; if ((t = xmlNodeListGetString(doc, attribute->children, 0))) { value = xmlCharsToString(t); free(t); /* should be xmlFree ?? */ } } nsuri = (attribute->ns != NULL) ? xmlCharsToString(attribute->ns->href) : (NSString *)nil; [attributes addAttribute:name uri:nsuri rawName:name type:@"CDATA" value:value]; [nsuri release]; nsuri = nil; [name release]; name = nil; [value release]; value = nil; } return attributes; } /* walking the tree, generating SAX events */ - (BOOL)_resolveEntityReferences { return YES; } - (BOOL)processEntityRefNode:(xmlNodePtr)_node { if ([self _resolveEntityReferences]) return [self processTextNode:_node]; else { NSString *refName; NSString *entityValue; refName = xmlCharsToString(_node->name); entityValue = xmlCharsToString(_node->content); #if 0 NSLog(@"%s:%i: Ignoring entity ref: '%@' %s\n", __PRETTY_FUNCTION__, __LINE__, refName, _node->content); #endif [entityValue release]; [refName release]; return YES; } } - (BOOL)processDocumentNode:(xmlNodePtr)node { BOOL result; [self->contentHandler startDocument]; [self->contentHandler startPrefixMapping:@"" uri:@"http://www.w3.org/XML/1998/namespace"]; result = [self processChildren:node->children]; [self->contentHandler endPrefixMapping:@""]; [self->contentHandler endDocument]; return result; } - (BOOL)processTextNode:(xmlNodePtr)_node { static unichar c = '\0'; if (self->contentHandler == nil) return YES; if (_node->content) { xmlChar *chars; if (self->encodeEntities) { /* should use the DocSAX encoding routine (htmlEncodeEntities) ??? */ chars = xmlEncodeEntitiesReentrant(self->doc, _node->content); } else chars = _node->content; if (chars == NULL) { [self->contentHandler characters:&c length:0]; } else { void *data, *ts; unsigned len; len = strlen((char *)chars); data = ts = calloc(len + 1, sizeof(unichar)); /* GC ?! */ if (_UTF8ToUTF16((void *)&chars, (void *)(chars + len), (void *)&ts, ts + (len * sizeof(unichar)))) { free(data); NSLog(@"ERROR(%s:%i): couldn't convert UTF8 to UTF16 !", __PRETTY_FUNCTION__, __LINE__); return NO; } [self->contentHandler characters:data length:(ts - data)]; free(data); } } else [self->contentHandler characters:&c length:0]; return YES; } - (BOOL)processCommentNode:(xmlNodePtr)_node { unichar c = '\0'; if (self->lexicalHandler == nil) return YES; if (_node->content) { xmlChar *chars; /* uses the DocSAX encoding routine !!!!!!!!!! */ chars = xmlEncodeEntitiesReentrant(self->doc, _node->content); if (chars == NULL) { [self->lexicalHandler comment:&c length:0]; } else { void *data, *ts; unsigned len; len = strlen((const char *)chars); data = ts = calloc(len + 1, sizeof(unichar)); /* GC ?! */ if (_UTF8ToUTF16((void *)&chars, (void *)(chars + len), (void *)&ts, ts + (len * sizeof(unichar)))) { free(data); NSLog(@"ERROR(%s:%i): couldn't convert UTF8 to UTF16 !", __PRETTY_FUNCTION__, __LINE__); return NO; } [self->lexicalHandler comment:data length:(ts - data)]; free(data); } } else [self->lexicalHandler comment:&c length:0]; return YES; } - (BOOL)processDTDNode:(xmlNodePtr)node { /* do nothing with DTD nodes .. */ return YES; } - (BOOL)processEntityNode:(xmlNodePtr)node { /* do nothing with entity nodes .. */ NSLog(@"%s:%i: ignoring entity node (name='%s') ...", __PRETTY_FUNCTION__, __LINE__, node->name); return YES; } - (BOOL)processPINode:(xmlNodePtr)node { NSString *piName; NSString *piValue; piName = xmlCharsToString(node->name); piValue = xmlCharsToString(node->content); [self->contentHandler processingInstruction:piName data:piValue]; [piName release]; [piValue release]; return YES; } - (BOOL)processElementNode:(xmlNodePtr)node { id attrs; NSString *tagName; NSString *nsuri; BOOL result; self->depth++; tagName = xmlCharsToString(node->name); nsuri = (node->ns != NULL) ? xmlCharsToString(node->ns->href) : (NSString *)nil; attrs = [self processAttributes:node->properties]; [self->contentHandler startElement:tagName namespace:nsuri rawName:tagName attributes:attrs]; [attrs release]; attrs = nil; result = [self processChildren:node->children]; [self->contentHandler endElement:tagName namespace:nsuri rawName:tagName]; self->depth--; [nsuri release]; nsuri = nil; [tagName release]; tagName = nil; [attrs release]; attrs = nil; return result; } - (BOOL)processChildren:(xmlNodePtr)children { xmlNodePtr node; if (children == NULL) return YES; for (node = children; node; node = node->next) { [self processNode:node]; } return YES; } - (BOOL)processNode:(xmlNodePtr)_node { switch(_node->type) { case XML_ELEMENT_NODE: return [self processElementNode:_node]; case XML_ATTRIBUTE_NODE: NSLog(@"invalid place for attribute-node !"); return NO; case XML_TEXT_NODE: return [self processTextNode:_node]; case XML_CDATA_SECTION_NODE: return [self processTextNode:_node]; case XML_ENTITY_REF_NODE: return [self processEntityRefNode:_node]; case XML_ENTITY_NODE: return [self processEntityNode:_node]; case XML_PI_NODE: return [self processPINode:_node]; case XML_COMMENT_NODE: return [self processCommentNode:_node]; case XML_DOCUMENT_NODE: return [self processDocumentNode:_node]; case XML_DTD_NODE: return [self processDTDNode:_node]; default: NSLog(@"WARNING: UNKNOWN node type %i\n", _node->type); break; } return NO; } - (BOOL)walkDocumentTree:(xmlDocPtr)_doc { int type; BOOL result; type = ((xmlDocPtr)self->doc)->type; ((xmlDocPtr)self->doc)->type = XML_DOCUMENT_NODE; result = [self processNode:(xmlNodePtr)self->doc]; ((xmlDocPtr)self->doc)->type = type; return result; } /* callbacks */ static SaxParseException * mkException(libxmlDocSAXDriver *self, NSString *key, const char *msg, va_list va) { NSString *s, *reason; NSDictionary *ui; SaxParseException *e; int count = 0, i; id keys[7], values[7]; id tmp; NSRange r; s = [NSString stringWithCString:msg]; s = [[[NSString alloc] initWithFormat:s arguments:va] autorelease]; r = [s rangeOfString:@"\n"]; reason = (r.length > 0) ? [s substringToIndex:r.location] : s; if ([reason length] == 0) reason = @"unknown reason"; keys[0] = @"parser"; values[0] = self; count++; keys[1] = @"depth"; values[1] = [NSNumber numberWithInt:self->depth]; count++; if ([s length] > 0) { keys[count] = @"errorMessage"; values[count] = s; count++; } // NSLog(@"locator: %@", self->locator); if ((i = [self->locator lineNumber]) >= 0) { keys[count] = @"line"; values[count] = [NSNumber numberWithInt:i]; count++; } if ((i = [self->locator columnNumber]) >= 0) { keys[count] = @"column"; values[count] = [NSNumber numberWithInt:i]; count++; } if ((tmp = [self->locator publicId])) { keys[count] = @"publicId"; values[count] = tmp; count++; } if ((tmp = [self->locator systemId])) { keys[count] = @"systemId"; values[count] = tmp; count++; } ui = [NSDictionary dictionaryWithObjects:values forKeys:keys count:count]; e = (id)[SaxParseException exceptionWithName:key reason:reason userInfo:ui]; return e; } static void warning(void *udata, const char *msg, ...) { va_list args; SaxParseException *e; NSCAssert(activeDriver, @"no driver is active !"); va_start(args, msg); e = mkException(activeDriver, @"SAXWarning", msg, args); va_end(args); [activeDriver->errorHandler warning:e]; } static void error(void *udata, const char *msg, ...) { va_list args; SaxParseException *e; NSCAssert(activeDriver, @"no driver is active !"); va_start(args, msg); e = mkException(activeDriver, @"SAXError", msg, args); va_end(args); [activeDriver->errorHandler error:e]; } static void fatalError(void *udata, const char *msg, ...) { va_list args; SaxParseException *e; NSCAssert(activeDriver, @"no driver is active !"); va_start(args, msg); e = mkException(activeDriver, @"SAXFatalError", msg, args); va_end(args); [activeDriver->errorHandler fatalError:e]; } static void setLocator(void *udata, xmlSAXLocatorPtr _locator) { NSCAssert(activeDriver, @"no driver is active !"); [activeDriver->locator release]; activeDriver->locator = [[libxmlSAXLocator alloc] initWithSaxLocator:_locator parser:activeDriver]; activeDriver->locator->ctx = activeDriver->ctxt; [activeDriver->contentHandler setDocumentLocator:activeDriver->locator]; } @end /* libxmlDocSAXDriver */ #include "unicode.h" SOPE/sope-xml/libxmlSAXDriver/libxmlSAXLocator.h0000644000000000000000000000266715004363604020461 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __libxmlSAXLocator_H__ #define __libxmlSAXLocator_H__ #import #import #include @interface libxmlSAXLocator : NSObject < SaxLocator > { @public id parser; void *ctx; const xmlChar *(*getPublicId)(void *ctx); const xmlChar *(*getSystemId)(void *ctx); int (*getLineNumber)(void *ctx); int (*getColumnNumber)(void *ctx); } - (id)initWithSaxLocator:(xmlSAXLocatorPtr)_loc parser:(id)_parser; - (void)clear; /* accessors */ - (int)columnNumber; - (int)lineNumber; - (NSString *)publicId; - (NSString *)systemId; @end #endif /* __libxmlSAXLocator_H__ */ SOPE/sope-xml/XmlRpc/0000755000000000000000000000000015004363604013274 5ustar rootrootSOPE/sope-xml/XmlRpc/XmlRpcResponseEncoder.m0000644000000000000000000000363715004363604017707 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcCoder.h" #include "common.h" @interface XmlRpcEncoder(PrivateMethodes) - (void)_encodeObject:(id)_object; - (void)_reset; @end @implementation XmlRpcResponseEncoder - (void)encodeRootObject:(id)_object { static Class ExceptionClass = Nil; if (ExceptionClass == Nil) ExceptionClass = [NSException class]; [self _reset]; [self->string appendString:@"\n"]; [self->string appendString:@"\n"]; if ([_object isKindOfClass:ExceptionClass]) { [self->string appendString:@"\n"]; [self->string appendString:@"\n"]; [self _encodeObject:_object]; [self->string appendString:@"\n"]; [self->string appendString:@"\n"]; } else { [self->string appendString:@"\n"]; [self->string appendString:@"\n"]; [self->string appendString:@"\n"]; [self _encodeObject:_object]; [self->string appendString:@"\n"]; [self->string appendString:@"\n"]; [self->string appendString:@"\n"]; } [self->string appendString:@"\n"]; } @end /* XmlRpcResponseEncoder */ SOPE/sope-xml/XmlRpc/NSURL+XmlRpcCoding.m0000644000000000000000000000232015004363604016677 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcMethodResponse.h" #include "NSObject+XmlRpc.h" #include "XmlRpcCoder.h" #include "common.h" @implementation NSURL(XmlRpcCoding) - (NSString *)xmlRpcType { return @"string"; } - (void)encodeWithXmlRpcCoder:(XmlRpcEncoder *)_coder { [_coder encodeString:[self absoluteString]]; } + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_coder { return [self URLWithString:[_coder decodeString]]; } @end /* NSURL(XmlRpcCoding) */ SOPE/sope-xml/XmlRpc/SxXML-XmlRpc.graffle0000644000000000000000000003516515004363604017014 0ustar rootroot CanvasColor w 1.000000e+00 ColumnAlign 0 ColumnSpacing 5.400000e+01 GraphDocumentVersion 2 GraphicsList Bounds {{15, 13}, {101, 36}} Class ShapedGraphic FitText YES ID 1012 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-BoldOblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\b\fs48 \cf0 XmlRpc} Bounds {{284, 207}, {167, 18}} Class ShapedGraphic ID 1011 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/XmlRpc/XmlRpcMethodResponse.h Magnets {0.5, 0} {-0.5, 0} Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 XmlRpcMethodResponse} Bounds {{284, 180}, {167, 18}} Class ShapedGraphic ID 1010 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/XmlRpc/XmlRpcValue.h Magnets {0.5, 0} {-0.5, 0} Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 XmlRpcValue} Bounds {{284, 261}, {167, 18}} Class ShapedGraphic ID 1009 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/SaxObjC/SaxDefaultHandler.h Magnets {0.5, 0} {-0.5, 0} Shape Rectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 SaxDefaultHandler} Bounds {{477, 261}, {167, 18}} Class ShapedGraphic ID 1008 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/XmlRpc/XmlRpcSaxHandler.h Magnets {0.5, 0} {-0.5, 0} Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 XmlRpcSaxHandler} Bounds {{284, 153}, {167, 18}} Class ShapedGraphic ID 1007 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/XmlRpc/XmlRpcMethodCall.h Magnets {0.5, 0} {-0.5, 0} Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 XmlRpcMethodCall} Bounds {{284, 126}, {167, 18}} Class ShapedGraphic ID 1006 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/XmlRpc/XmlRpcCoder.h Magnets {0.5, 0} {-0.5, 0} Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 XmlRpcEncoder} Bounds {{284, 99}, {167, 18}} Class ShapedGraphic ID 1005 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-xml-42/XmlRpc/XmlRpcCoder.h Magnets {0.5, 0} {-0.5, 0} Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 XmlRpcDecoder} Bounds {{63, 153}, {167, 18}} Class ShapedGraphic ID 1004 Magnets {0.5, 0} {-0.5, 0} Shape Rectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NSObject} Class LineGraphic Head ID 1011 ID 1003 Points {230, 162} {284, 216} Style stroke HeadArrow 0 LineType 2 TailArrow 0 Tail ID 1004 Class LineGraphic Head ID 1010 ID 1002 Points {230, 162} {284, 189} Style stroke HeadArrow 0 LineType 2 TailArrow 0 Tail ID 1004 Class LineGraphic Head ID 1009 ID 1001 Points {230, 162} {284, 270} Style stroke HeadArrow 0 LineType 2 TailArrow 0 Tail ID 1004 Class LineGraphic Head ID 1008 ID 1000 Points {451, 270} {477, 270} Style stroke HeadArrow 0 LineType 2 TailArrow 0 Tail ID 1009 Class LineGraphic Head ID 1007 ID 999 Points {230, 162} {284, 162} Style stroke HeadArrow 0 LineType 2 TailArrow 0 Tail ID 1004 Class LineGraphic Head ID 1006 ID 998 Points {230, 162} {284, 135} Style stroke HeadArrow 0 LineType 2 TailArrow 0 Tail ID 1004 Class LineGraphic Head ID 1005 ID 997 Points {230, 162} {284, 108} Style stroke HeadArrow 0 LineType 2 TailArrow 0 Tail ID 1004 GridInfo HPages 1 ImageCounter 1 IsPalette NO Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo AutoAdjust YES HierarchicalOrientation 0 MagneticFieldCenter {0, 0} MagnetsEnabled YES PageBreakColor w 3.333333e-01 PageBreaks YES PageSetup BAt0eXBlZHN0cmVhbYED6IQBQISEhAtOU1ByaW50SW5mbwGEhAhOU09iamVjdACFkoSE hBNOU011dGFibGVEaWN0aW9uYXJ5AISEDE5TRGljdGlvbmFyeQCUhAFpEpKEhIQITlNT dHJpbmcBlIQBKxBOU0pvYkRpc3Bvc2l0aW9uhpKEmZkPTlNQcmludFNwb29sSm9ihpKE mZkOTlNCb3R0b21NYXJnaW6GkoSEhAhOU051bWJlcgCEhAdOU1ZhbHVlAJSEASqEhAFm nSSGkoSZmQtOU1BhcGVyTmFtZYaShJmZBkxldHRlcoaShJmZD05TUHJpbnRBbGxQYWdl c4aShJ2chIQBY54AhpKEmZkNTlNSaWdodE1hcmdpboaShJ2cn50khpKEmZkITlNDb3Bp ZXOGkoSdnISEAVOfAYaShJmZD05TU2NhbGluZ0ZhY3RvcoaShJ2chIQBZKABhpKEmZkL TlNGaXJzdFBhZ2WGkoSdnKmfAYaShJmZFE5TVmVydGljYWxQYWdpbmF0aW9uhpKEnZyE hAFzoQCGkoSZmRVOU0hvcml6b25hbFBhZ2luYXRpb26GkoSdnLGhAIaShJmZFk5TSG9y aXpvbnRhbGx5Q2VudGVyZWSGkoSdnKSeAYaShJmZDE5TTGVmdE1hcmdpboaShJ2cn50k hpKEmZkNTlNPcmllbnRhdGlvboaShJ2csaEBhpKEmZkZTlNQcmludFJldmVyc2VPcmll bnRhdGlvboaSo5KEmZkKTlNMYXN0UGFnZYaShJ2chJeXgn////+GkoSZmQtOU1RvcE1h cmdpboaShJ2cn50khpKEmZkUTlNWZXJ0aWNhbGx5Q2VudGVyZWSGkrWShJmZC05TUGFw ZXJTaXplhpKEnpyEhAx7X05TU2l6ZT1mZn2igQMYgQJkhoaG RowAlign 0 RowSpacing 9.000000e+00 VPages 1 WindowInfo Frame {{67, 90}, {826, 833}} VisibleRegion {{-44.5, -108}, {811, 756}} Zoom 1 SOPE/sope-xml/XmlRpc/XmlRpcSaxHandler.h0000644000000000000000000000373215004363604016631 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __XmlRpcSaxHandler_H__ #define __XmlRpcSaxHandler_H__ #include /* Mappings: or -> NSNumber -> NSNumber -> NSNumber -> NSData -> NSString -> NSCalendarDate -> NSDictionary -> NSArray */ @class NSMutableArray, NSTimeZone, NSCalendarDate; @class XmlRpcMethodCall, XmlRpcMethodResponse; @interface XmlRpcSaxHandler : SaxDefaultHandler { XmlRpcMethodCall *call; XmlRpcMethodResponse *response; NSMutableArray *params; NSString *methodName; BOOL invalidCall; NSMutableArray *tagStack; NSMutableArray *valueStack; NSString *className; NSMutableArray *memberNameStack; NSMutableArray *memberValueStack; NSTimeZone *timeZone; NSCalendarDate *dateTime; NSMutableString *characters; unsigned valueNestingLevel; SEL nextCharactersProcessor; } /* reusing sax handler */ - (void)reset; /* result accessors */ - (XmlRpcMethodCall *)methodCall; - (XmlRpcMethodResponse *)methodResponse; @end #endif /* __XmlRpcSaxHandler_H__ */ SOPE/sope-xml/XmlRpc/XmlRpcValue.h0000644000000000000000000000232515004363604015651 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __XML_RPC_XmlRpcValue_H__ #define __XML_RPC_XmlRpcValue_H__ #import @interface XmlRpcValue : NSObject { NSString *className; id value; } - (id)initWithValue:(id)_value className:(NSString *)_className; /* accessors */ - (void)setClassName:(NSString *)_className; - (NSString *)className; - (id)value; - (Class)class; - (BOOL)isException; - (BOOL)isDictionary; @end #endif /* __XML_RPC_XmlRpcValue_H__ */ SOPE/sope-xml/XmlRpc/NSObject+XmlRpc.h0000644000000000000000000000236415004363604016322 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NSObject_XMLRPC_H__ #define __NSObject_XMLRPC_H__ #import #import #import @interface NSObject(XmlRpcValues) + (id)objectWithXmlRpcType:(NSString *)_type characters:(unichar *)_chars length:(NSUInteger)_len; @end @interface NSObject(XmlRpcSignatures) - (NSString *)xmlRpcType; @end @interface NSArray(XmlRpcSignatures) - (NSArray *)xmlRpcElementSignature; @end #endif /* __NSObject_XMLRPC_H__ */ SOPE/sope-xml/XmlRpc/GNUmakefile0000644000000000000000000000220515004363604015345 0ustar rootroot# GNUstep makefile include ../../config.make include ../common.make ifneq ($(frameworks),yes) LIBRARY_NAME = libXmlRpc else FRAMEWORK_NAME = XmlRpc XmlRpc_RESOURCE_FILES += Version endif libXmlRpc_PCH_FILE = common.h XmlRpc_PCH_FILE = common.h libXmlRpc_HEADER_FILES = \ XmlRpc.h \ NSObject+XmlRpc.h \ XmlRpcCoder.h \ XmlRpcMethodCall.h \ XmlRpcMethodResponse.h \ libXmlRpc_OBJC_FILES = \ XmlRpcEncoder.m \ XmlRpcDecoder.m \ XmlRpcMethodCall.m \ XmlRpcMethodResponse.m \ XmlRpcSaxHandler.m \ XmlRpcValue.m \ NSMutableString+XmlRpcDecoder.m \ \ NSArray+XmlRpcCoding.m \ NSData+XmlRpcCoding.m \ NSDate+XmlRpcCoding.m \ NSDictionary+XmlRpcCoding.m \ NSException+XmlRpcCoding.m \ NSHost+XmlRpcCoding.m \ NSNotification+XmlRpcCoding.m \ NSNumber+XmlRpcCoding.m \ NSObject+XmlRpc.m \ NSString+XmlRpcCoding.m \ NSURL+XmlRpcCoding.m \ -include GNUmakefile.preamble ifneq ($(FHS_INSTALL_ROOT),) GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include endif ifneq ($(frameworks),yes) include $(GNUSTEP_MAKEFILES)/library.make else include $(GNUSTEP_MAKEFILES)/framework.make endif -include GNUmakefile.postamble SOPE/sope-xml/XmlRpc/NSHost+XmlRpcCoding.m0000644000000000000000000000231115004363604017152 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcMethodResponse.h" #include "NSObject+XmlRpc.h" #include "common.h" #include "XmlRpcCoder.h" @implementation NSHost(XmlRpcCoding) - (NSString *)xmlRpcType { return @"string"; } - (void)encodeWithXmlRpcCoder:(XmlRpcEncoder *)_coder { [_coder encodeString:[self name]]; } + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_coder { return [NSHost hostWithName:[_coder decodeString]]; } @end /* NSHost(XmlRpcCoding) */ SOPE/sope-xml/XmlRpc/ChangeLog0000644000000000000000000002550615004363604015056 0ustar rootroot2007-02-12 Helge Hess * XmlRpcSaxHandler.m, XmlRpcDecoder.m: fixed a few gnustep-base compilation warnings (v4.7.31) 2006-09-20 Helge Hess * GNUmakefile.preamble: filter out -O% flags for files using exception handlers, enable -O2 per default (v4.5.30) 2006-08-24 Helge Hess * NSObject+XmlRpc.m: added support for 'nil' type as submitted by xmlrpclib with the 'allow_none' option set (v4.5.29) 2006-07-03 Helge Hess * fixed gcc 4.1 warnings, use %p for pointer formats (v4.5.28) 2006-02-26 Marcus Mueller * XmlRpcValue.m: fixed stupid bugs in -isException and -isDictionary, which formerly lead to unreadable exception garbage whenever a remote exception occured. NOTE: have we had proper unit tests, this probably wouldn't have splipped through so easily. :-) (v4.5.27) 2005-11-17 Helge Hess * NSMutableString+XmlRpcDecoder.m: properly include string.h to fix a memcpy warning (v4.5.26) 2005-05-03 Helge Hess * NSObject+XmlRpc.m, XmlRpcSaxHandler.m: fixed gcc 4.0 warnings (v4.5.25) 2005-04-26 Helge Hess * XmlRpcDecoder.m: fixed duplicate decoding of base64 values in XML-RPC results (v4.5.24) 2004-12-14 Marcus Mueller * XmlRpc.xcode: minor cleanup 2004-09-22 Marcus Mueller * XmlRpc.xcode: minor fixes 2004-09-21 Marcus Mueller * XmlRpc.xcode: Fixed dependencies to resemble the make process more closely. Our aim should be to stick to the make process as closely as possible, so we shouldn't introduce dependencies in non-toplevel projects. 2004-08-29 Helge Hess * added hack to install the project in FHS locations - the library, its headers, the tools and the resources will be installed in FHS_INSTALL_ROOT if specified (eg make FHS_INSTALL_ROOT=/usr/local) (v4.3.23) 2004-08-29 Marcus Mueller * XmlRpc.xcode: moved unused source into Unused group. Fixed file encodings. 2004-08-27 Helge Hess * XmlRpc.xcode: fixed Xcode project 2004-08-26 Marcus Mueller * XmlRpc.xcode: new Xcode project 2004-08-20 Helge Hess * moved to SOPE 4.3 (v4.3.22) 2004-06-09 Helge Hess * v4.2.21 * GNUmakefile.preamble: added prebinding info * GNUmakefile: moved preamble stuff to GNUmakefile.preamble, also build XmlRpc.framework on non-libFoundation systems 2004-05-09 Helge Hess * XmlRpcDecoder.m: do not print a compile warning if NSXMLParser is used (on MacOSX) (v4.2.20) 2004-05-05 Marcus Mueller * GNUmakefile.preamble: added support for building with GNUSTEP_BUILD_DIR environment variable set for recent gnustep-make package. (v4.2.19) 2003-11-19 Helge Hess * GNUmakefile: removed autodoc target 2003-11-09 Helge Hess * v4.2.18 * XmlRpcDecoder.m: can use NSXMLParser for parsing, if available * XmlRpcMethodResponse: now accepts an NSData object for parsing, this avoids costly conversions between NSString and NSData for parsing ... * XmlRpcRequestDecoder.m, XmlRpcSaxHandler.m: added debug logging facilities 2003-10-30 Helge Hess * XmlRpcDecoder.m: fixed some Xcode warnings (v4.2.17) 2003-08-29 Helge Hess * fixed an MacOSX warning in XmlRpcEncoder (v4.2.16) 2003-08-28 Helge Hess * v4.2.15 * NSObject+XmlRpc.m: catch year-values bigger than 2033 or smaller than 1900 and transform them into something usable by libFoundation (problem exposed by JOGI) * XmlRpcEncoder.m: moved string category to separate file * XmlRpcDecoder.m: smaller cleanups 2003-08-11 Helge Hess * v4.2.14 * NSObject+XmlRpc.m: map XML-RPC "value" type to "NSString". This happens if the XML-RPC client does not send the "string" tag (abc instead of abc) 2003-07-18 Helge Hess * NSNotification+XmlRpcCoding.m: use -name instead of -notificationName to get the name of the notification for encoding (required for gstep-base, Cocoa, also works on lF) (v4.2.13) 2003-04-28 Helge Hess * XmlRpcEncoder.m: fixed a bug in encode-datetime (wrong timezone was used due to a bug in libFoundation), smaller speed optimizations (v4.2.12) 2003-02-04 Helge Hess * v4.2.11 * XmlRpcSaxHandler.m: if an incorrect fault object is returned, try to transform it to a exception * XmlRpcEncoder.m: renamed -appendHTMLString: to -appendXmlRpcString:, added specialized methods for adding int and double members (since performSelector:withObject: doesn't coerce arguments on Cocoa) 2003-01-30 Helge Hess * XmlRpcMethodCall.m: removed dependency on -shallowCopy (dependency to EOControl being linked in ...) (v4.2.10) 2003-01-07 Helge Hess * v4.2.9 * NSDate+XmlRpcCoding.m: fixed a warning on MacOSX * common.h: removed dependency on FoundationExt on MacOSX Thu Jan 2 10:52:41 2003 Helge Hess * v4.2.8 * common.h: defined ASSIGN macro if missing * XmlRpcValue.m, XmlRpcDecoder.m: do not use AUTORELEASE macros Fri Dec 27 10:56:51 2002 Helge Hess * XmlRpcEncoder.m: added a new escaping function which works with unicode strings (v4.2.7) 2002-09-28 Helge Hess * removed some compilation warnings (v4.2.6) 2002-09-03 Helge Hess * made docs AutoDoc compliant 2002-08-08 Helge Hess * XmlRpcDecoder.m: fixed major bugs in the XML-RPC decoding code, when contained in structures, base types like int,bool resulted in a core dump (basetypes were handled like objects) 2002-07-03 Helge Hess * NSException+XmlRpcCoding.m: improved mapping of NSException's to XML-RPC faults * XmlRpcMethodResponse.m: added better -description Tue Jul 2 16:09:45 2002 Bjoern Stierand * fixed a bug with exception encoding/decoding 2002-07-01 Helge Hess * replaced -initWithXmlRpcDecoder: with -decodeObjectWithXmlRpcCoder: due to a problem with releasing newly allocated objects in MacOSX Fri May 17 11:03:12 2002 Helge Hess * XmlRpcValue.m: added some stuff for the fix below * XmlRpcSaxHandler.m: added a fixup to end_fault that turns NSDictionary XmlRpcValues into NSExceptions * XmlRpcResponseDecoder.m: pass string directly to the parser, not an NSData generated using NSASCIIStringEncoding ... Thu May 2 12:58:59 2002 Helge Hess * changed to use -rangeOfString: instead of -indexOfString: Thu Feb 28 15:16:21 2002 Jan41 Reichmann * NSException+XmlRpcCoding.m: fixed encode bug Wed Feb 27 11:51:17 2002 Helge Hess * added -xmlRpcType method to determine the "default" type which will result in encoding the object as XML-RPC Tue Feb 26 10:18:50 2002 Bjoern Stierand * XmlRpcEncoder.m: removed newlines created during en-/decoding Mon Feb 25 17:41:03 2002 Martin Spindler * XmlRpcSaxHandler.m: decode test as string Wed Feb 13 13:52:09 2002 Helge Hess * moved generic stuff to XML/XmlRpc Sat Feb 9 13:00:11 2002 Helge Hess * XmlRpcSaxHandler.m: added warning and error handlers ... * XmlRpcDecoder.m: improved error output Fri Feb 8 17:35:05 2002 Helge Hess * XmlRpcDecoder.m: fixed charset problems Fri Feb 8 12:29:28 2002 Helge Hess * WODirectAction+XmlRpcIntrospection.m: changed to return "string" signature for object types Thu Feb 7 20:19:55 2002 Helge Hess * WODirectAction+XmlRpc.m: autogenerate SandStorm component name Wed Jan 30 18:16:31 2002 Helge Hess * WODirectAction+XmlRpcIntrospection.m: fixed bug with method names * NGXmlRpcInvocation.m: convert types prior to call, if signature is available Tue Jan 29 18:30:56 2002 Helge Hess * added NGXmlRpcInvocation, NGXmlRpcMethodSignature Mon Jan 28 18:46:34 2002 Helge Hess * WODirectAction+XmlRpc.m: improved reflection capabilities * WODirectAction+XmlRpc.m: support a GET action for dynamic reflection * WODirectAction+XmlRpc.m: added method to define component prefix Fri Jan 25 18:36:58 2002 Helge Hess * WODirectAction+XmlRpc.m: use RPC2 as action name ... * added NGXmlRpcClient class Thu Jan 17 17:23:09 2002 Martin Spindler * NSObject+XmlRpc.m: raise exception if coding methods arn't supported Tue Nov 13 09:34:54 2001 Helge Hess * EOKeyGlobalID+XmlRpcCoding.m: removed unnecessary retain/autorelease Tue Nov 13 01:06:50 2001 Jan41 Reichmann * EOKeyGlobalID+XmlRpcCoding.m: fixed decoding bug Wed Oct 24 13:23:54 2001 Martin Spindler * XmlRpcSaxHandler.m: fixed multiple call of -characters:length: Mon Oct 22 20:53:33 2001 Helge Hess * XmlRpcEncoder.m: normalize NSString subclasses Mon Oct 22 18:20:54 2001 Helge Hess * XmlRpcMethodResponse+WO.m: enabled UTF-8 for result encoding Wed Oct 10 19:42:17 2001 Martin Spindler * XmlRpcEncoder.m: use -classForCoder instead of -class Tue Aug 28 15:38:05 2001 Martin Spindler * changed 'timeZone' - tag into 'timeZone' - attribute Tue Aug 28 14:21:54 2001 Martin Spindler * support of 'timeZone' - tag (not xmlprc compatible!) * XmlRpcCoder: added accessors for defaultTimeZone Mon Aug 27 10:47:03 2001 Helge Hess * moved SKYRiX Logic categories back to skyxmlrpcd Wed Aug 22 15:41:39 2001 Helge Hess * XmlRpcDecoder.m: decode dates as calendar-dates Wed Aug 22 14:56:22 2001 Helge Hess * use ObjC base-types for decoding/encoding numbers Wed Aug 22 11:36:02 2001 Helge Hess * NSDate+XmlRpcCoding.m: fixed NSTimeZone decoding * NSArray+XmlRpcCoding.m: fixed NSEnumerator coding, fixed RC bugs Mon Aug 20 21:55:41 2001 Helge Hess * created ChangeLog SOPE/sope-xml/XmlRpc/common.h0000644000000000000000000000227515004363604014743 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __XmlRpc_common_h__ #define __XmlRpc_common_h__ #include #import #ifndef ASSIGN # define ASSIGN(object, value) \ ({id __object = (id)object; \ id __value = (id)value; \ if (__value != __object) { if (__value) [__value retain]; \ if (__object) [__object release]; \ object = __value;}}) #endif #endif /* __XmlRpc_common_h__ */ SOPE/sope-xml/XmlRpc/NSDictionary+XmlRpcCoding.m0000644000000000000000000000227015004363604020346 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcMethodResponse.h" #include "NSObject+XmlRpc.h" #include "common.h" #include "XmlRpcCoder.h" @implementation NSDictionary(XmlRpcCoding) - (NSString *)xmlRpcType { return @"struct"; } - (void)encodeWithXmlRpcCoder:(XmlRpcEncoder *)_coder { [_coder encodeStruct:self]; } + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_coder { return [_coder decodeStruct]; } @end /* NSDictionary(XmlRpcCoding) */ SOPE/sope-xml/XmlRpc/NSObject+XmlRpc.m0000644000000000000000000002237715004363604016335 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "common.h" @interface NSObject(Misc) - (id)initWithString:(NSString *)_s; @end @interface NSString(XmlRpcParsing) - (id)initWithXmlRpcType:(NSString *)_type characters:(unichar *)_chars length:(NSUInteger)_len; @end @interface NSDate(XmlRpcParsing) - (id)initWithXmlRpcType:(NSString *)_type characters:(unichar *)_chars length:(NSUInteger)_len; @end @interface NSNumber(XmlRpcParsing) - (id)initWithXmlRpcType:(NSString *)_type characters:(unichar *)_chars length:(NSUInteger)_len; @end @interface NSData(XmlRpcParsing) - (id)initWithXmlRpcType:(NSString *)_type characters:(unichar *)_chars length:(NSUInteger)_len; @end @interface NSData(UsedNGExtensions) - (NSData *)dataByDecodingBase64; @end @implementation NSObject(XmlRpcParsing) - (id)initWithXmlRpcCoder:(XmlRpcDecoder *)_coder { NSClassDescription *cd; if ((cd = [self classDescription])) { NSEnumerator *e; NSString *k; if ((self = [self init])) { e = [[cd attributeKeys] objectEnumerator]; while ((k = [e nextObject])) [self takeValue:[_coder decodeObjectForKey:k] forKey:k]; e = [[cd toOneRelationshipKeys] objectEnumerator]; while ((k = [e nextObject])) [self takeValue:[_coder decodeObjectForKey:k] forKey:k]; e = [[cd toManyRelationshipKeys] objectEnumerator]; while ((k = [e nextObject])) [self takeValue:[_coder decodeArrayForKey:k] forKey:k]; } } else if ([self respondsToSelector:@selector(initWithString:)]) { self = [(id)self initWithString:[_coder decodeString]]; } else { [NSException raise:@"XmlRpcCodingException" format: @"in initWithXmlRpcCoder: cannot decode class '%@'", NSStringFromClass([self class])]; [self release]; return nil; } return self; } + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_decoder { return [[[self alloc] initWithXmlRpcCoder:_decoder] autorelease]; } - (NSString *)xmlRpcType { return @"struct"; } - (void)encodeWithXmlRpcCoder:(XmlRpcEncoder *)_coder { NSClassDescription *cd; if ((cd = [self classDescription])) { NSEnumerator *e; NSString *k; e = [[cd attributeKeys] objectEnumerator]; while ((k = [e nextObject])) [_coder encodeObject:[self valueForKey:k] forKey:k]; e = [[cd toOneRelationshipKeys] objectEnumerator]; while ((k = [e nextObject])) [_coder encodeObject:[self valueForKey:k] forKey:k]; e = [[cd toManyRelationshipKeys] objectEnumerator]; while ((k = [e nextObject])) [_coder encodeArray:[self valueForKey:k] forKey:k]; } else if ([self respondsToSelector:@selector(initWithString:)]) { [_coder encodeString:[self description]]; } else { [NSException raise:@"XmlRpcCodingException" format: @"in encodeWithXmlRpcCoder: " @"cannot encode class '%@', object=%@B", NSStringFromClass([self class]), self]; } } + (id)objectWithXmlRpcType:(NSString *)_type characters:(unichar *)_chars length:(NSUInteger)_len { static NSDictionary *typeToClass = nil; Class ObjClass = Nil; id obj; if ([@"nil" isEqualToString:_type]) /* Python with allow_none */ return nil; if (typeToClass == nil) { typeToClass = [[NSDictionary alloc] initWithObjectsAndKeys: [NSNumber class], @"i4", [NSNumber class], @"int", [NSNumber class], @"double", [NSNumber class], @"boolean", [NSString class], @"string", [NSString class], @"value", [NSData class], @"base64", [NSCalendarDate class], @"dateTime.iso8601", nil]; } /* determine basetype class */ if ((ObjClass = [typeToClass objectForKey:_type]) == Nil) { NSLog(@"WARNING(%s): unknown XML-RPC type '%@', using String ...", __PRETTY_FUNCTION__, _type); ObjClass = [NSString class]; } /* construct object */ obj = [[ObjClass alloc] initWithXmlRpcType:_type characters:_chars length:_len]; return [obj autorelease]; } - (id)initWithXmlRpcType:(NSString *)_type characters:(unichar *)_chars length:(NSUInteger)_len { if ([self respondsToSelector:@selector(initWithString:)]) { NSString *s; s = [[NSString alloc] initWithCharacters:_chars length:_len]; self = [self initWithString:s]; [s release]; return self; } /* don't know how to init with given type ... */ [self release]; return nil; } @end /* NSObject(XmlRpc) */ @implementation NSData(XmlRpcParsing) /* NSData represents the xml-rpc base type 'base64' */ - (id)initWithXmlRpcType:(NSString *)_type characters:(unichar *)_chars length:(NSUInteger)_len { NSString *v; [self release]; self = nil; v = [NSString stringWithCharacters:_chars length:_len]; self = [v dataUsingEncoding:NSUTF8StringEncoding]; if ([_type isEqualToString:@"base64"]) self = [self dataByDecodingBase64]; return [self copy]; } @end /* NSData(XmlRpcParsing) */ @implementation NSDate(XmlRpcParsing) /* NSDate represents the xml-rpc type dateTime.iso8601: */ - (id)initWithXmlRpcType:(NSString *)_type characters:(unichar *)_chars length:(NSUInteger)_len { /* eg 19980717T14:08:55 */ if (_len < 17) { [self release]; return nil; } { unsigned char buf[8]; int year, month, day, hour, min, sec; buf[0] = _chars[0]; buf[1] = _chars[1]; buf[2] = _chars[2]; buf[3] = _chars[3]; buf[4] = '\0'; year = atoi((char *)buf); buf[0] = _chars[4]; buf[1] = _chars[5]; buf[2] = '\0'; month = atoi((char *)buf); buf[0] = _chars[6]; buf[1] = _chars[7]; buf[2] = '\0'; day = atoi((char *)buf); buf[0] = _chars[9]; buf[1] = _chars[10]; buf[2] = '\0'; hour = atoi((char *)buf); buf[0] = _chars[12]; buf[1] = _chars[13]; buf[2] = '\0'; min = atoi((char *)buf); buf[0] = _chars[15]; buf[1] = _chars[16]; buf[2] = '\0'; sec = atoi((char *)buf); if (year > 2033) { NSString *s; s = [[NSString alloc] initWithCharacters:_chars length:_len]; NSLog(@"WARNING: got a date value '%@' with year >2033, " @"which cannot be represented, silently using 2033 ...", s); [s release]; year = 2033; } else if (year < 1900) { NSString *s; s = [[NSString alloc] initWithCharacters:_chars length:_len]; NSLog(@"WARNING: got a date value '%@' with year < 1900, " @"which cannot be represented, silently using 1900 ...", s); [s release]; year = 1900; } if (![self isKindOfClass:[NSCalendarDate class]]) { [self release]; self = [NSCalendarDate alloc]; } return [(NSCalendarDate *)self initWithYear:year month:month day:day hour:hour minute:min second:sec timeZone:[NSTimeZone timeZoneWithName:@"GMT"]]; } } @end /* NSDate(XmlRpcParsing) */ @implementation NSNumber(XmlRpcParsing) /* NSNumber represents the xml-rpc base types: 'int', 'double', 'boolean': */ - (id)initWithXmlRpcType:(NSString *)_type characters:(unichar *)_chars length:(NSUInteger)_len { if ([_type isEqualToString:@"boolean"]) { BOOL v; v = (_len > 0) ? ((_chars[0] == '1') ? YES : NO) : NO; return [self initWithBool:v]; } else { NSString *v; BOOL isInt = NO; v = [NSString stringWithCharacters:_chars length:_len]; if ([_type isEqualToString:@"i4"] || [_type isEqualToString:@"int"]) isInt = YES; else if ([_type isEqualToString:@"double"]) isInt = NO; else isInt = ([v rangeOfString:@"."].length == 0) ? YES : NO; return isInt ? [self initWithInt:[v intValue]] : [self initWithDouble:[v doubleValue]]; } } @end /* NSNumber(XmlRpcParsing */ @implementation NSString(XmlRpcParsing) - (id)initWithXmlRpcType:(NSString *)_type characters:(unichar *)_chars length:(NSUInteger)_len { /* this is *never* called, since NSString+alloc returns a NSTemporaryString*/ return [self initWithCharacters:_chars length:_len]; } @end /* NSString(XmlRpcParsing) */ SOPE/sope-xml/XmlRpc/XmlRpcValue.m0000644000000000000000000000440015004363604015652 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcValue.h" #include "common.h" @implementation XmlRpcValue /*" The XmlRpcValue class is used internally by the XML-RPC decoder to represent any valid XML-RPC value. You should never need to use this class. "*/ - (id)initWithValue:(id)_value className:(NSString *)_className { if ((self = [super init])) { NSString *cName; ASSIGN(self->value, _value); cName = (_className != nil) ? _className : NSStringFromClass([_value class]); ASSIGN(self->className, cName); } return self; } - (void)dealloc { [self->className release]; [self->value release]; [super dealloc]; } - (id)value { return self->value; } - (void)setClassName:(NSString *)_className { if (_className != self->className) { [self->className autorelease]; self->className = [_className copy]; } } - (NSString *)className { return self->className; } - (Class)class { return NSClassFromString([self className]); } - (BOOL)isException { return [(id)[self value] isKindOfClass:[NSException class]]; } - (BOOL)isDictionary { return [(id)[self value] isKindOfClass:[NSDictionary class]]; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"XmlRpcValue: %@->%@", self->className, self->value]; } /* NSCopying */ - (id)copyWithZone:(NSZone *)zone { return [[[self class] alloc] initWithValue:self->value className:self->className]; } @end /* XmlRpcValue */ SOPE/sope-xml/XmlRpc/XmlRpcRequestDecoder.m0000644000000000000000000000630615004363604017523 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include "common.h" @implementation XmlRpcRequestDecoder static id saxRequestHandler = nil; static id requestParser = nil; static BOOL doDebug = NO; - (void)_ensureSaxAndParser { if (saxRequestHandler == nil) { static Class clazz = Nil; if (clazz == Nil) clazz = NSClassFromString(@"XmlRpcSaxRequestHandler"); if ((saxRequestHandler = [[clazz alloc] init]) == nil) { NSLog(@"%s: did not find sax handler ...", __PRETTY_FUNCTION__); return; } } if (requestParser != nil) return; requestParser = [[SaxXMLReaderFactory standardXMLReaderFactory] createXMLReader]; if (requestParser == nil) { NSLog(@"%s: did not find an XML parser ...", __PRETTY_FUNCTION__); return; } [requestParser setContentHandler:saxRequestHandler]; [requestParser setDTDHandler:saxRequestHandler]; [requestParser setErrorHandler:saxRequestHandler]; [requestParser retain]; } - (XmlRpcMethodCall *)decodeRootObject { XmlRpcMethodCall *methodCall; NSEnumerator *paramEnum; NSMutableArray *params; XmlRpcValue *param; if (doDebug) NSLog(@"%s: begin", __PRETTY_FUNCTION__); [self _ensureSaxAndParser]; [saxRequestHandler reset]; [requestParser parseFromSource:self->string systemId:nil]; methodCall = [saxRequestHandler methodCall]; // the methodCall's parameters is an array of XmlRpcValues!!! paramEnum = [[methodCall parameters] objectEnumerator]; params = [[NSMutableArray alloc] initWithCapacity: [[methodCall parameters] count]]; while ((param = [paramEnum nextObject])) { Class objClass = Nil; id obj; [self->value autorelease]; self->value = [param retain]; if ((objClass = NSClassFromString([param className])) != Nil) { if ((obj = [objClass decodeObjectWithXmlRpcCoder:self])) { [params addObject:obj]; } else { NSLog(@"%s: Warning: try to add 'nil' object to params (class='%@')", __PRETTY_FUNCTION__, [param className]); } } } [methodCall setParameters:params]; [params release]; if (doDebug) NSLog(@"%s: done: %@", __PRETTY_FUNCTION__, methodCall); return methodCall; } @end /* XmlRpcRequestDecoder */ SOPE/sope-xml/XmlRpc/NSException+XmlRpcCoding.m0000644000000000000000000000520715004363604020202 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcMethodResponse.h" #include "common.h" #include "XmlRpcCoder.h" @implementation NSException(XmlRpcCoding) - (NSString *)xmlRpcType { return @"struct"; } - (NSNumber *)xmlRpcFaultCode { NSDictionary *ui; id code; ui = [self userInfo]; if ((code = [ui objectForKey:@"XmlRpcFaultCode"])) /* code is set */; else if ((code = [ui objectForKey:@"faultCode"])) /* code is set */; else code = [self name]; return [NSNumber numberWithInt:[code intValue]]; } - (void)encodeWithXmlRpcCoder:(XmlRpcEncoder *)_coder { int code; NSString *str, *n, *r; NSDictionary *ui; code = [[self xmlRpcFaultCode] intValue]; n = [self name]; r = [self reason]; if ([n length] == 0) str = r; else if ([r length] == 0) str = n; else str = [NSString stringWithFormat:@"%@: %@", n, r]; if ((ui = [self userInfo])) str = [NSString stringWithFormat:@"%@ %@", str, ui]; [_coder encodeInt:code forKey:@"faultCode"]; [_coder encodeString:str forKey:@"faultString"]; } + (NSString *)exceptionNameForXmlRpcFaultCode:(int)_code { return [NSString stringWithFormat:@"XmlRpcFault<%i>", _code]; } - (NSString *)exceptionNameForXmlRpcFaultCode:(int)_code { return [[self class] exceptionNameForXmlRpcFaultCode:_code]; } + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_coder { int code; NSString *r; NSDictionary *ui; code = [_coder decodeIntForKey:@"faultCode"]; r = [_coder decodeStringForKey:@"faultString"]; ui = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:code], @"faultCode", r, @"faultString", nil]; return [self exceptionWithName: [self exceptionNameForXmlRpcFaultCode:code] reason:r userInfo:ui]; } @end /* NSException(XmlRpcCoding) */ SOPE/sope-xml/XmlRpc/XmlRpcRequestEncoder.m0000644000000000000000000000420015004363604017524 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcCoder.h" #include "XmlRpcMethodCall.h" #include "common.h" @interface XmlRpcEncoder(PrivateMethodes) - (void)_encodeObject:(id)_object; - (void)_reset; @end @implementation XmlRpcRequestEncoder - (void)encodeRootObject:(XmlRpcMethodCall *)_methodCall { NSEnumerator *paramEnum; id param; if (_methodCall == nil) return; if (![_methodCall isKindOfClass:[XmlRpcMethodCall class]]) { NSLog(@"%s: Warning: rootObject MUST be a XmlRpcMethodCall\n " @"(rootObject=%@)", __PRETTY_FUNCTION__, _methodCall); return; } [self _reset]; paramEnum = [[_methodCall parameters] objectEnumerator]; [self->string appendString:@"\n"]; [self->string appendString:@"\n"]; [self->string appendString:@""]; [self->string appendString:[_methodCall methodName]]; [self->string appendString:@"\n"]; [self->string appendString:@"\n"]; while ((param = [paramEnum nextObject])) { [self->string appendString:@"\n"]; [self->string appendString:@"\n"]; [self _encodeObject:param]; [self->string appendString:@"\n"]; [self->string appendString:@"\n"]; } [self->string appendString:@"\n"]; [self->string appendString:@"\n"]; } @end /* XmlRpcRequestEncoder */ SOPE/sope-xml/XmlRpc/COPYING0000644000000000000000000006130315004363604014332 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-xml/XmlRpc/fhs.make0000644000000000000000000000173315004363604014717 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) FHS_INCLUDE_DIR=$(FHS_INSTALL_ROOT)/include/ FHS_BIN_DIR=$(FHS_INSTALL_ROOT)/bin/ ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib64/ else FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib/ endif fhs-header-dirs :: $(MKDIRS) $(FHS_INCLUDE_DIR)$(libXmlRpc_HEADER_FILES_INSTALL_DIR) move-headers-to-fhs :: fhs-header-dirs @echo "moving headers to $(FHS_INCLUDE_DIR) .." mv $(GNUSTEP_HEADERS)$(libXmlRpc_HEADER_FILES_INSTALL_DIR)/*.h \ $(FHS_INCLUDE_DIR)$(libXmlRpc_HEADER_FILES_INSTALL_DIR)/ NONFHS_LIBDIR="$(GNUSTEP_LIBRARIES)/$(GNUSTEP_TARGET_LDIR)/" NONFHS_LIBNAME="$(LIBRARY_NAME)$(LIBRARY_NAME_SUFFIX)$(SHARED_LIBEXT)" move-libs-to-fhs :: @echo "moving libs to $(FHS_LIB_DIR) .." mv $(NONFHS_LIBDIR)/$(NONFHS_LIBNAME)* $(FHS_LIB_DIR)/ move-to-fhs :: move-headers-to-fhs move-libs-to-fhs after-install :: move-to-fhs endif SOPE/sope-xml/XmlRpc/XmlRpcDecoder.m0000644000000000000000000004276315004363604016161 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcCoder.h" #include "XmlRpcValue.h" #include "XmlRpcSaxHandler.h" #include #include "XmlRpcMethodCall.h" #include "XmlRpcMethodResponse.h" #include "common.h" /* self->unarchivedObjects does *not* store objects with xmlrpc base type! */ @interface XmlRpcDecoder(PrivateMethodes) - (id)_decodeObject:(XmlRpcValue *)_value; @end @interface NSData(NGExtensions) - (NSData *)dataByDecodingBase64; @end @implementation XmlRpcDecoder - (BOOL)profileXmlRpcCoding { return [[NSUserDefaults standardUserDefaults] boolForKey:@"ProfileXmlRpcCoding"]; } #if HAVE_NSXMLPARSER && 0 #warning using NSXMLParser! static BOOL useNSXMLParser = YES; #else static BOOL useNSXMLParser = NO; #endif static id saxHandler = nil; static id xmlRpcParser = nil; static Class ArrayClass = Nil; static Class DictionaryClass = Nil; static Class DataClass = Nil; static Class NumberClass = Nil; static Class StringClass = Nil; static Class DateClass = Nil; static BOOL doDebug = NO; + (void)initialize { if (ArrayClass == Nil) ArrayClass = [NSArray class]; if (DictionaryClass == Nil) DictionaryClass = [NSDictionary class]; if (DataClass == Nil) DataClass = [NSData class]; if (NumberClass == Nil) NumberClass = [NSNumber class]; if (StringClass == Nil) StringClass = [NSString class]; if (DateClass == Nil) DateClass = [NSCalendarDate class]; } - (id)init { if ((self = [super init])) { self->unarchivedObjects = [[NSMutableArray alloc] init]; self->awakeObjects = [[NSMutableSet alloc] init]; self->valueStack = [[NSMutableArray alloc] initWithCapacity:4]; self->timeZone = [[NSTimeZone timeZoneWithAbbreviation:@"GMT"] retain]; } return self; } - (NSStringEncoding)encodingForXMLEncodingString:(NSString *)_enc { _enc = [_enc lowercaseString]; if ([_enc isEqualToString:@"utf-8"]) return NSUTF8StringEncoding; else if ([_enc isEqualToString:@"iso-8859-1"]) return NSISOLatin1StringEncoding; #if !(NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY) else if ([_enc isEqualToString:@"iso-8859-9"]) return NSISOLatin9StringEncoding; #endif else if ([_enc isEqualToString:@"ascii"]) return NSASCIIStringEncoding; else NSLog(@"%s: UNKNOWN XML ENCODING '%@'", __PRETTY_FUNCTION__, _enc); return 0; } - (id)initForReadingWithString:(NSString *)_string { if ((self = [self init])) { NSRange r; r = [_string rangeOfString:@"?>"]; if ([_string hasPrefix:@" 0) { NSStringEncoding enc; if ((enc = [self encodingForXMLEncodingString:xmlDecl]) != 0) { self->data = [[_string dataUsingEncoding:enc] retain]; if (self->data == nil) { NSLog(@"WARNING(%s): couldn't get data for string '%@', " @"encoding %i !", __PRETTY_FUNCTION__, _string, enc); [self release]; return nil; } } } } if (self->data == nil) self->data = [[_string dataUsingEncoding:NSUTF8StringEncoding] retain]; } return self; } - (id)initForReadingWithData:(NSData *)_data { if ((self = [self init])) { self->data = [_data retain]; } return self; } - (void)dealloc { [self->data release]; [self->valueStack release]; [self->unarchivedObjects release]; [self->awakeObjects release]; [self->timeZone release]; [super dealloc]; } /* accessors */ - (void)setDefaultTimeZone:(NSTimeZone *)_timeZone { [self->timeZone autorelease]; self->timeZone = [_timeZone retain]; } - (NSTimeZone *)defaultTimeZone { return self->timeZone; } /* *** */ - (void)_ensureSaxAndParser { if (saxHandler == nil) { if ((saxHandler = [[XmlRpcSaxHandler alloc] init]) == nil) { NSLog(@"%s: did not find sax handler ...", __PRETTY_FUNCTION__); return; } } if (useNSXMLParser) return; if (xmlRpcParser != nil) return; xmlRpcParser = [[SaxXMLReaderFactory standardXMLReaderFactory] createXMLReaderForMimeType:@"text/xml"]; if (xmlRpcParser == nil) { NSLog(@"%s: did not find an XML parser ...", __PRETTY_FUNCTION__); return; } [xmlRpcParser setContentHandler:saxHandler]; [xmlRpcParser setDTDHandler:saxHandler]; [xmlRpcParser setErrorHandler:saxHandler]; [xmlRpcParser retain]; } - (id)_decodeValueOfClass:(Class)_class { id obj; obj = [(XmlRpcValue *)[self->valueStack lastObject] value]; if ([obj isKindOfClass:_class]) return obj; NSLog(@"WARNING(%s): obj (%@) is not of proper class ('%@'<-->'%@'", __PRETTY_FUNCTION__, obj, NSStringFromClass(_class), NSStringFromClass([obj class]), nil); return nil; } - (XmlRpcMethodCall *)_decodeMethodCall:(XmlRpcMethodCall *)_baseCall { NSArray *params; NSEnumerator *paramEnum; XmlRpcMethodCall *result = nil; XmlRpcValue *param = nil; NSMutableArray *decParams = nil; // decoded parameters params = [_baseCall parameters]; // XmlRpcValues!! decParams = [[NSMutableArray alloc] initWithCapacity:[params count]]; paramEnum = [params objectEnumerator]; while ((param = [paramEnum nextObject])) { id obj; if ((obj = [self _decodeObject:param]) != nil) [decParams addObject:obj]; } result = [[XmlRpcMethodCall alloc] initWithMethodName:[_baseCall methodName] parameters:decParams]; [decParams release]; return [result autorelease]; } - (XmlRpcMethodResponse *)_decodeMethodResponse:(XmlRpcMethodResponse *)_resp { static Class ExceptionClass = Nil; XmlRpcMethodResponse *response = nil; id result = [_resp result]; if (ExceptionClass == Nil) ExceptionClass = [NSException class]; if (![result isKindOfClass:ExceptionClass]) { result = [self _decodeObject:result]; // => XmlRpcValue } response = [[XmlRpcMethodResponse alloc] initWithResult:result]; return [response autorelease]; } - (NSStringEncoding)logEncoding { return NSUTF8StringEncoding; } - (id)decodeRootObject { id tmp = nil; if (doDebug) { NSLog(@"%s: begin (data: %"PRIuPTR" bytes, nesting: %i)", __PRETTY_FUNCTION__, [self->data length], self->nesting); } if ([self->data length] == 0) return nil; self->nesting++; [self _ensureSaxAndParser]; NSAssert(saxHandler, @"missing sax handler ..."); NSAssert(xmlRpcParser || useNSXMLParser, @"missing parser handler ..."); [saxHandler reset]; if (doDebug) NSLog(@"%s: SAX handler: %@", __PRETTY_FUNCTION__, saxHandler); #if HAVE_NSXMLPARSER if (useNSXMLParser) { NSXMLParser *parser; parser = [[NSXMLParser alloc] initWithData:self->data]; if (doDebug) NSLog(@"%s: using NSXMLParser: %@", __PRETTY_FUNCTION__, parser); [parser setDelegate:saxHandler]; [parser setShouldProcessNamespaces:NO]; [parser setShouldReportNamespacePrefixes:NO]; [parser setShouldResolveExternalEntities:NO]; [parser parse]; [parser release]; } else #endif [xmlRpcParser parseFromSource:self->data systemId:@""]; if ((tmp = [saxHandler methodCall]) != nil) { tmp = [self _decodeMethodCall:tmp]; } else if ((tmp = [saxHandler methodResponse]) != nil) { tmp = [self _decodeMethodResponse:tmp]; } else if (tmp == nil) { NSString *s; s = [[NSString alloc] initWithData:self->data encoding:[self logEncoding]]; NSLog(@"%s: couldn't parse source\n" @" parser: %@\n" @" handler: %@\n" @" data: %@" @" string: '%@'", __PRETTY_FUNCTION__, xmlRpcParser, saxHandler, self->data, s); [s release]; } else { NSLog(@"%s: neither call nor response (handler=%@): %@ ..", __PRETTY_FUNCTION__, saxHandler, tmp); } self->nesting--; // [saxHandler reset]; // hh asks: why is that commented out? if (doDebug) NSLog(@"%s: end: %@", __PRETTY_FUNCTION__, tmp); return tmp; } - (XmlRpcMethodCall *)decodeMethodCall { XmlRpcMethodCall *result; NSTimeInterval st = 0.0; if ([self profileXmlRpcCoding]) st = [[NSDate date] timeIntervalSince1970]; result = [self decodeRootObject]; if ([self profileXmlRpcCoding]) { NSTimeInterval diff; diff = [[NSDate date] timeIntervalSince1970] - st; printf("+++ decodeMethodCall: %0.5fs\n", diff); } return ([result isKindOfClass:[XmlRpcMethodCall class]]) ? result : (XmlRpcMethodCall *)nil; } - (XmlRpcMethodResponse *)decodeMethodResponse { XmlRpcMethodResponse *result; NSTimeInterval st = 0.0; if ([self profileXmlRpcCoding]) st = [[NSDate date] timeIntervalSince1970]; result = [self decodeRootObject]; if ([self profileXmlRpcCoding]) { NSTimeInterval diff; diff = [[NSDate date] timeIntervalSince1970] - st; printf("+++ decodeMethodResponse: %0.5fs\n", diff); } return [result isKindOfClass:[XmlRpcMethodResponse class]] ? result : (XmlRpcMethodResponse *)nil; } - (id)_decodeObject:(XmlRpcValue *)_value { id result; if (_value == nil) return nil; [self->valueStack addObject:_value]; result = [self decodeObject]; [self->valueStack removeLastObject]; return result; } - (id)decodeObject { Class objClass = Nil; id object = nil; self->nesting++; if ((self->nesting == 1) && ([self->valueStack count] == 0)) { object = [self decodeRootObject]; } else { NSString *className; id value = [self->valueStack lastObject]; className = [value className]; if ([className length] == 0) { object = [(XmlRpcValue *)value value]; } else if ((objClass = NSClassFromString(className)) != Nil) { object = [objClass decodeObjectWithXmlRpcCoder:self]; } else { NSLog(@"%s: class (%@) specified by value (%@) wasn't found.", __PRETTY_FUNCTION__, className, value); object = [(XmlRpcValue *)value value]; } if (object) [self->unarchivedObjects addObject:object]; } self->nesting--; return object; } - (NSDictionary *)decodeStruct { NSDictionary *dict; id result = nil; NSMutableDictionary *tmp; NSEnumerator *keyEnum; NSString *key; dict = (NSDictionary *)[(XmlRpcValue *)[self->valueStack lastObject] value]; if (!([dict respondsToSelector:@selector(keyEnumerator)] && [dict respondsToSelector:@selector(objectForKey:)])) return nil; keyEnum = [dict keyEnumerator]; tmp = [[NSMutableDictionary alloc] initWithCapacity:8]; while ((key = [keyEnum nextObject])) { XmlRpcValue *v; id obj; v = [dict objectForKey:key]; if ((obj = [self _decodeObject:v]) != nil) [tmp setObject:obj forKey:key]; } result = [NSDictionary dictionaryWithDictionary:tmp]; [tmp release]; return result; } - (NSArray *)decodeArray { NSArray *array; id result = nil; NSMutableArray *tmp = nil; NSEnumerator *valEnum; XmlRpcValue *val = nil; array = (NSArray *)[(XmlRpcValue *)[self->valueStack lastObject] value]; if (![array respondsToSelector:@selector(objectEnumerator)]) return nil; valEnum = [array objectEnumerator]; tmp = [[NSMutableArray alloc] initWithCapacity:8]; while ((val = [valEnum nextObject])) { id obj; if ((obj = [self _decodeObject:val]) != nil) [tmp addObject:obj]; } result = [NSArray arrayWithArray:tmp]; [tmp release]; return result; } - (NSData *)decodeBase64 { #if 0 /* data is already decoded in the XmlRpcValue */ tmp = [tmp dataByDecodingBase64]; #endif return [self _decodeValueOfClass:DataClass]; } - (BOOL)decodeBoolean { return [[self _decodeValueOfClass:NumberClass] boolValue]; } - (int)decodeInt { return [[self _decodeValueOfClass:NumberClass] intValue]; } - (double)decodeDouble { return [[self _decodeValueOfClass:NumberClass] doubleValue]; } - (NSString *)decodeString { return [self _decodeValueOfClass:StringClass]; } - (NSCalendarDate *)decodeDateTime { NSCalendarDate *date; NSTimeZone *tz; int secFromGMT; if ((date = [self _decodeValueOfClass:DateClass]) == nil) return nil; if ((tz = [date timeZone])) return date; if (![date respondsToSelector:@selector(setTimeZone:)]) { /* a plain date ... */ NSLog(@"cannot set timezone on date: %@", date); return date; } /* apply timezone correction */ secFromGMT = [self->timeZone secondsFromGMT]; [date setTimeZone:self->timeZone]; date = [date dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 seconds:-secFromGMT]; return date; } - (XmlRpcValue *)beginDecodingKey:(NSString *)_key { XmlRpcValue *newValue; NSDictionary *obj; obj = (NSDictionary *)[(XmlRpcValue *)[self->valueStack lastObject] value]; NSAssert(_key != nil, @"_key is not allowed to be nil"); if (![obj isKindOfClass:DictionaryClass]) { NSLog(@"WARNING(%s): obj (%@) is not kind of class NSDictionary !!", __PRETTY_FUNCTION__, obj, nil); return nil; } if ((newValue = [obj objectForKey:_key]) == nil) /* got no value for key ... */ return nil; [self->valueStack addObject:newValue]; return newValue; } - (void)finishedDecodingKey { [self->valueStack removeLastObject]; } - (id)_decodeValueForKey:(NSString *)_key selector:(SEL)_selector { XmlRpcValue *newValue; id result; if ((newValue = [self beginDecodingKey:_key]) == nil) return nil; result = [[self performSelector:_selector] retain]; [self finishedDecodingKey]; return [result autorelease]; } - (NSDictionary *)decodeStructForKey:(NSString *)_key { return [self _decodeValueForKey:_key selector:@selector(decodeStruct)]; } - (NSArray *)decodeArrayForKey:(NSString *)_key { return [self _decodeValueForKey:_key selector:@selector(decodeArray)]; } - (NSData *)decodeBase64ForKey:(NSString *)_key { return [self _decodeValueForKey:_key selector:@selector(decodeBase64)]; } - (BOOL)decodeBooleanForKey:(NSString *)_key { XmlRpcValue *newValue; BOOL result; if ((newValue = [self beginDecodingKey:_key]) == nil) /* any useful alternatives ? */ return NO; result = [self decodeBoolean]; [self finishedDecodingKey]; return result; } - (int)decodeIntForKey:(NSString *)_key { XmlRpcValue *newValue; int result; if ((newValue = [self beginDecodingKey:_key]) == nil) /* NSKeyedArchiver returns 0, we too */ return 0; result = [self decodeInt]; [self finishedDecodingKey]; return result; } - (double)decodeDoubleForKey:(NSString *)_key { XmlRpcValue *newValue; double result; if ((newValue = [self beginDecodingKey:_key]) == nil) /* any useful alternatives ? */ return 0.0; result = [self decodeDouble]; [self finishedDecodingKey]; return result; } - (NSString *)decodeStringForKey:(NSString *)_key { return [self _decodeValueForKey:_key selector:@selector(decodeString)]; } - (NSCalendarDate *)decodeDateTimeForKey:(NSString *)_key { return [self _decodeValueForKey:_key selector:@selector(decodeDateTime)]; } - (id)decodeObjectForKey:(NSString *)_key { return [self _decodeValueForKey:_key selector:@selector(decodeObject)]; } /* operations */ - (void)ensureObjectAwake:(id)_object { if ([self->awakeObjects containsObject:_object]) return; if ([_object respondsToSelector:@selector(awakeFromXmlRpcDecoder:)]) [_object awakeFromXmlRpcDecoder:self]; [self->awakeObjects addObject:_object]; } - (void)awakeObjects { NSEnumerator *e; id obj; e = [self->unarchivedObjects objectEnumerator]; while ((obj = [e nextObject])) [self ensureObjectAwake:obj]; } - (void)finishInitializationOfObjects { NSEnumerator *e; id obj; e = [self->unarchivedObjects objectEnumerator]; while ((obj = [e nextObject])) { if ([obj respondsToSelector: @selector(finishInitializationWithXmlRpcDecoder:)]) [obj finishInitializationWithXmlRpcDecoder:self]; } } @end /* XmlRpcDecoder */ SOPE/sope-xml/XmlRpc/XmlRpcMethodResponse.m0000644000000000000000000000614215004363604017542 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcMethodResponse.h" #include "XmlRpcCoder.h" #include "common.h" @interface XmlRpcMethodResponse(PrivateMethodes) - (NSString *)_encodeXmlRpcMethodResponse; @end @implementation XmlRpcMethodResponse - (id)initWithXmlRpcString:(NSString *)_string { XmlRpcDecoder *coder; XmlRpcMethodResponse *baseResponse; if ([_string length] == 0) { [self release]; return nil; } coder = [[XmlRpcDecoder alloc] initForReadingWithString:_string]; baseResponse = [coder decodeMethodResponse]; [coder release]; if (baseResponse == nil) { [self release]; return nil; } self = [self initWithResult:[baseResponse result]]; return self; } - (id)initWithXmlRpcData:(NSData *)_data { XmlRpcDecoder *coder; XmlRpcMethodResponse *baseResponse; if ([_data length] == 0) { [self release]; return nil; } coder = [[XmlRpcDecoder alloc] initForReadingWithData:_data]; baseResponse = [coder decodeMethodResponse]; [coder release]; if (baseResponse == nil) { [self release]; return nil; } self = [self initWithResult:[baseResponse result]]; return self; } - (id)initWithResult:(id)_result { if ((self = [super init])) { self->result = [_result retain]; } return self; } - (void)dealloc { [self->result release]; [super dealloc]; } /* accessors */ - (void)setResult:(id)_result { [self->result autorelease]; self->result = [_result retain]; } - (id)result { return self->result; } - (NSString *)xmlRpcString { return [self _encodeXmlRpcMethodResponse]; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:64]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if (result) [ms appendFormat:@" %@", self->result]; else [ms appendString:@" no result"]; [ms appendString:@">"]; return ms; } @end /* XmlRpcMethodResponse */ @implementation XmlRpcMethodResponse(PrivateMethodes) - (NSString *)_encodeXmlRpcMethodResponse { XmlRpcEncoder *encoder = nil; NSMutableString *str = nil; str = [NSMutableString stringWithCapacity:512]; encoder = [[XmlRpcEncoder alloc] initForWritingWithMutableString:str]; [encoder encodeMethodResponse:self]; [encoder release]; return str; } @end /* XmlRpcMethodResponse(PrivateMethodes) */ SOPE/sope-xml/XmlRpc/XmlRpcEncoder.m0000644000000000000000000003362215004363604016165 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcCoder.h" #include "XmlRpcMethodCall.h" #include "XmlRpcMethodResponse.h" #include "common.h" @interface NSMutableString(XmlRpcDecoder) - (void)appendXmlRpcString:(NSString *)_value; @end @interface NSData(UsedNGExtensions) - (NSData *)dataByEncodingBase64; @end @implementation XmlRpcEncoder static NSTimeZone *gmt = nil; static BOOL profileOn = NO; static Class NSNumberClass = Nil; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; profileOn = [ud boolForKey:@"ProfileXmlRpcCoding"]; gmt = [[NSTimeZone timeZoneWithAbbreviation:@"GMT"] retain]; NSNumberClass = [NSNumber class]; } - (id)initForWritingWithMutableString:(NSMutableString *)_string { if ((self = [super init])) { self->string = [_string retain]; self->timeZone = [gmt retain]; } return self; } - (void)dealloc { [self->string release]; [self->objectStack release]; [self->objectHasStructStack release]; [self->timeZone release]; [super dealloc]; } - (BOOL)profileXmlRpcCoding { return profileOn; } /* accessors */ - (void)setDefaultTimeZone:(NSTimeZone *)_timeZone { [self->timeZone autorelease]; self->timeZone = [_timeZone retain]; } /*" This returns the timezone which will be associated with XML-RPC datetime objects. Note: XML-RPC datetime values have no! associated timezone, it's recommended that you always use UTC though. "*/ - (NSTimeZone *)defaultTimeZone { return self->timeZone; } /* *** */ - (void)encodeMethodCall:(XmlRpcMethodCall *)_methodCall { NSEnumerator *paramEnum = [[_methodCall parameters] objectEnumerator]; id param; NSTimeInterval st = 0.0; if ([self profileXmlRpcCoding]) st = [[NSDate date] timeIntervalSince1970]; [self->string appendString:@""]; [self->string appendString:@""]; [self->string appendString:@""]; [self->string appendString:[_methodCall methodName]]; [self->string appendString:@""]; [self->string appendString:@""]; while ((param = [paramEnum nextObject])) { [self->string appendString:@""]; [self->string appendString:@""]; [self encodeObject:param]; [self->string appendString:@""]; [self->string appendString:@""]; } [self->string appendString:@""]; [self->string appendString:@""]; if ([self profileXmlRpcCoding]) { NSTimeInterval diff; diff = [[NSDate date] timeIntervalSince1970] - st; printf("+++ encodeMethodCall: %0.5fs\n", diff); } } - (void)encodeMethodResponse:(XmlRpcMethodResponse *)_methodResponse { id result = [_methodResponse result]; static Class ExceptionClass = Nil; NSTimeInterval st = 0.0; if ([self profileXmlRpcCoding]) st = [[NSDate date] timeIntervalSince1970]; if (ExceptionClass == Nil) ExceptionClass = [NSException class]; [self->string appendString:@""]; [self->string appendString:@""]; if ([result isKindOfClass:ExceptionClass]) { [self->string appendString:@""]; [self->string appendString:@""]; [self encodeObject:result]; [self->string appendString:@""]; [self->string appendString:@""]; } else { [self->string appendString:@""]; [self->string appendString:@""]; [self->string appendString:@""]; [self encodeObject:result]; [self->string appendString:@""]; [self->string appendString:@""]; [self->string appendString:@""]; } [self->string appendString:@""]; if ([self profileXmlRpcCoding]) { NSTimeInterval diff; diff = [[NSDate date] timeIntervalSince1970] - st; printf("+++ enocdeMethodResponse: %0.5fs\n", diff); } } - (void)_reset { [self->objectStack release]; self->objectStack = nil; [self->objectHasStructStack release]; self->objectHasStructStack = nil; } - (void)_ensureStacks { if (self->objectStack == nil) self->objectStack = [[NSMutableArray alloc] initWithCapacity:8]; if (self->objectHasStructStack == nil) self->objectHasStructStack = [[NSMutableArray alloc] initWithCapacity:8]; } - (void)_encodeObject:(id)_object { if (_object) { [self _ensureStacks]; [self->objectStack addObject:_object]; [self->objectHasStructStack addObject:@"NO"]; [_object encodeWithXmlRpcCoder:self]; if ([[self->objectHasStructStack lastObject] boolValue]) { [self->string appendString:@""]; } [self->objectHasStructStack removeLastObject]; [self->objectStack removeLastObject]; } } - (NSString *)_className { id obj; if ((obj = [self->objectStack lastObject]) == nil) return nil; if ([obj isKindOfClass:[NSString class]]) return @"NSString"; return NSStringFromClass([obj classForCoder]); } - (void)encodeObject:(id)_obj { [self _encodeObject:_obj]; } - (BOOL)isObjectClassAttributeEnabled { // adding of NSObjectClass removed due to compatibility issues ! return NO; } - (void)_appendTagName:(NSString *)_tagName attributes:(NSDictionary *)_attrs { NSEnumerator *keyEnum = [_attrs keyEnumerator]; NSString *key = nil; [self->string appendString:@"<"]; [self->string appendString:_tagName]; if ([self isObjectClassAttributeEnabled]) { NSString *className = [self _className]; if ([className length] > 0) { [self->string appendString:@" NSObjectClass=\""]; [self->string appendXmlRpcString:className]; [self->string appendString:@"\""]; } } while ((key = [keyEnum nextObject])) { [self->string appendString:@" "]; [self->string appendString:key]; [self->string appendString:@"=\""]; [self->string appendXmlRpcString:[_attrs objectForKey:key]]; [self->string appendString:@"\""]; } [self->string appendString:@">"]; } - (void)_appendTagName:(NSString *)_tagName { [self _appendTagName:_tagName attributes:nil]; } - (void)_encodeNumber:(NSNumber *)_number tagName:(NSString *)_tagName { [self _appendTagName:_tagName]; if ([_tagName isEqualToString:@"boolean"]) [self->string appendString:[_number boolValue] ? @"1" : @"0"]; else if ([_tagName isEqualToString:@"int"]) [self->string appendFormat:@"%i", [_number intValue]]; else [self->string appendXmlRpcString:[_number stringValue]]; [self->string appendString:@"string appendString:_tagName]; [self->string appendString:@">"]; } - (void)encodeStruct:(NSDictionary *)_struct { NSEnumerator *keys = nil; id key = nil; [self _appendTagName:@"struct"]; keys = [_struct keyEnumerator]; while ((key = [keys nextObject])) { [self->string appendString:@""]; [self->string appendString:@""]; [self->string appendXmlRpcString:key]; [self->string appendString:@""]; [self->string appendString:@""]; [self _encodeObject:[_struct objectForKey:key]]; [self->string appendString:@""]; [self->string appendString:@""]; } [self->string appendString:@""]; } - (void)encodeArray:(NSArray *)_array { NSEnumerator *valueEnum = [_array objectEnumerator]; id value; [self _appendTagName:@"array"]; [self->string appendString:@""]; while ((value = [valueEnum nextObject])) { [self->string appendString:@""]; [self _encodeObject:value]; [self->string appendString:@""]; } [self->string appendString:@""]; [self->string appendString:@""]; } - (void)encodeBase64:(NSData *)_data { NSString *base64; base64 = [[NSString alloc] initWithData:[_data dataByEncodingBase64] encoding:NSASCIIStringEncoding]; [self _appendTagName:@"base64"]; [self->string appendString:base64]; [self->string appendString:@""]; [base64 release]; base64 = nil; } - (void)encodeBoolean:(BOOL)_number { [self _encodeNumber:[NSNumberClass numberWithBool:_number] tagName:@"boolean"]; } - (void)encodeInt:(int)_number { [self _encodeNumber:[NSNumberClass numberWithInt:_number] tagName:@"int"]; } - (void)encodeDouble:(double)_number { [self _encodeNumber:[NSNumberClass numberWithDouble:_number] tagName:@"double"]; } - (void)encodeString:(NSString *)_string { [self _appendTagName:@"string"]; [self->string appendXmlRpcString:_string]; [self->string appendString:@""]; } - (void)encodeDateTime:(NSDate *)_date { static NSDictionary *attrs = nil; NSCalendarDate *date; NSString *s; if (attrs == nil) { attrs = [[NSDictionary alloc] initWithObjectsAndKeys:@"GMT",@"timeZone",nil]; } /* convert parameter to GMT */ #if LIB_FOUNDATION_LIBRARY /* TODO: not sure whether lF handles reference-date correctly ... */ date = [[NSCalendarDate alloc] initWithTimeIntervalSince1970: [_date timeIntervalSince1970]]; #else date = [[NSCalendarDate alloc] initWithTimeIntervalSinceReferenceDate: [_date timeIntervalSinceReferenceDate]]; #endif [date setTimeZone:gmt]; /* format in XML-RPC date format */ s = [[NSString alloc] initWithFormat: @"%04"PRIiPTR"%02"PRIiPTR"%02"PRIiPTR"T%02"PRIiPTR":%02"PRIiPTR":%02"PRIiPTR, [date yearOfCommonEra], [date monthOfYear], [date dayOfMonth], [date hourOfDay], [date minuteOfHour], [date secondOfMinute]]; [date release]; date = nil; [self _appendTagName:@"dateTime.iso8601" attributes:attrs]; [self->string appendString:s]; [self->string appendString:@""]; [s release]; } - (void)_appendMember:(id)_obj forKey:(NSString *)_key selector:(SEL)_sel { [self _ensureStacks]; if (![[self->objectHasStructStack lastObject] boolValue]) { [self->objectHasStructStack removeLastObject]; [self->objectHasStructStack addObject:@"YES"]; [self _appendTagName:@"struct"]; } if (_obj != nil) { [self->objectStack addObject:_obj]; [self->string appendString:@""]; [self->string appendString:_key]; [self->string appendString:@""]; /* this does not work for int/double on OSX, since OSX doesn't coerce the argument to the receivers parameter type */ [self performSelector:_sel withObject:_obj]; [self->string appendString:@""]; [self->objectStack removeLastObject]; } } - (void)_appendInt:(int)_i forKey:(NSString *)_key selector:(SEL)_sel { /* special methods required for OSX */ void (*m)(id,SEL,int); [self _ensureStacks]; if (![[self->objectHasStructStack lastObject] boolValue]) { [self->objectHasStructStack removeLastObject]; [self->objectHasStructStack addObject:@"YES"]; [self _appendTagName:@"struct"]; } [self->objectStack addObject:[NSNumberClass numberWithInt:_i]]; [self->string appendString:@""]; [self->string appendString:_key]; [self->string appendString:@""]; m = (void *)[self methodForSelector:_sel]; m(self, _sel, _i); [self->string appendString:@""]; [self->objectStack removeLastObject]; } - (void)_appendDouble:(double)_d forKey:(NSString *)_key selector:(SEL)_sel { /* special methods required for OSX */ void (*m)(id,SEL,double); [self _ensureStacks]; if (![[self->objectHasStructStack lastObject] boolValue]) { [self->objectHasStructStack removeLastObject]; [self->objectHasStructStack addObject:@"YES"]; [self _appendTagName:@"struct"]; } [self->objectStack addObject:[NSNumberClass numberWithDouble:_d]]; [self->string appendString:@""]; [self->string appendString:_key]; [self->string appendString:@""]; m = (void *)[self methodForSelector:_sel]; m(self, _sel, _d); [self->string appendString:@""]; [self->objectStack removeLastObject]; } - (void)encodeStruct:(NSDictionary *)_struct forKey:(NSString *)_key { [self _appendMember:_struct forKey:_key selector:@selector(encodeStruct:)]; } - (void)encodeArray:(NSArray *)_array forKey:(NSString *)_key { [self _appendMember:_array forKey:_key selector:@selector(encodeArray:)]; } - (void)encodeBase64:(NSData *)_data forKey:(NSString *)_key { [self _appendMember:_data forKey:_key selector:@selector(encodeBase64:)]; } - (void)encodeBoolean:(BOOL)_number forKey:(NSString *)_key { [self _appendInt:(int)_number forKey:_key selector:@selector(encodeBoolean:)]; } - (void)encodeInt:(int)_number forKey:(NSString *)_key { [self _appendInt:_number forKey:_key selector:@selector(encodeInt:)]; } - (void)encodeDouble:(double)_number forKey:(NSString *)_key { [self _appendDouble:_number forKey:_key selector:@selector(encodeDouble:)]; } - (void)encodeString:(NSString *)_string forKey:(NSString *)_key { [self _appendMember:_string forKey:_key selector:@selector(encodeString:)]; } - (void)encodeDateTime:(NSDate *)_date forKey:(NSString *)_key { [self _appendMember:_date forKey:_key selector:@selector(encodeDateTime:)]; } - (void)encodeObject:(id)_object forKey:(NSString *)_key { [self _appendMember:_object forKey:_key selector:@selector(encodeObject:)]; } @end /* XmlRpcEncoder */ SOPE/sope-xml/XmlRpc/NSDate+XmlRpcCoding.m0000644000000000000000000000326015004363604017116 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcMethodResponse.h" #include "NSObject+XmlRpc.h" #include "XmlRpcCoder.h" #import #include "common.h" @implementation NSDate(XmlRpcCoding) - (NSString *)xmlRpcType { return @"dateTime.iso8601"; } - (void)encodeWithXmlRpcCoder:(XmlRpcEncoder *)_coder { [_coder encodeDateTime:self]; } + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_coder { return [_coder decodeDateTime]; } @end /* NSDate(XmlRpcCoding) */ @implementation NSTimeZone(XmlRpcCoding) - (NSString *)xmlRpcType { return @"string"; } - (void)encodeWithXmlRpcCoder:(XmlRpcEncoder *)_coder { #if NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY [_coder encodeString:[self name]]; #else [_coder encodeString:[self timeZoneName]]; #endif } + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_coder { return [NSTimeZone timeZoneWithName:[_coder decodeString]]; } @end /* NSTimeZone(XmlRpcCoding) */ SOPE/sope-xml/XmlRpc/NSNumber+XmlRpcCoding.m0000644000000000000000000000616315004363604017476 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcMethodResponse.h" #include "NSObject+XmlRpc.h" #include "XmlRpcCoder.h" #include "common.h" #if LIB_FOUNDATION_LIBRARY # include #endif #define BOOLEAN_TYPE 0 #define INTEGER_TYPE 1 #define DOUBLE_TYPE 2 @implementation NSNumber(XmlRpcCoding) - (unsigned int)_xmlRpcNumberType { static Class BoolClass = Nil; if (BoolClass == Nil) BoolClass = NSClassFromString(@"NSBoolNumber"); if ([self isKindOfClass:BoolClass]) return BOOLEAN_TYPE; switch (*[self objCType]) { case 'i': case 'I': case 'c': case 'C': case 's': case 'S': case 'l': case 'L': return INTEGER_TYPE; case 'f': case 'd': default: return DOUBLE_TYPE; } } - (NSString *)xmlRpcType { switch ([self _xmlRpcNumberType]) { case BOOLEAN_TYPE: return @"boolean"; case DOUBLE_TYPE: return @"double"; default: /* INTEGER_TYPE */ return @"i4"; } } - (void)encodeWithXmlRpcCoder:(XmlRpcEncoder *)_coder { switch ([self _xmlRpcNumberType]) { case BOOLEAN_TYPE: [_coder encodeBoolean:[self boolValue]]; break; case DOUBLE_TYPE: [_coder encodeDouble:[self doubleValue]]; break; default: /* INTEGER_TYPE */ [_coder encodeInt:[self intValue]]; } } + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_coder { return [NSNumber numberWithInt:[_coder decodeInt]]; } @end /* NSNumber(XmlRpcCoding) */ #if LIB_FOUNDATION_LIBRARY @implementation NSBoolNumber(XmlRpcCoding) + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_coder { return [[[NSNumber alloc] initWithBool:[_coder decodeBoolean]] autorelease]; } - (NSString *)xmlRpcType { return @"boolean"; } @end /* NSBoolNumber(XmlRpcCoding) */ // nicht notwendig, nur BOOL muss speziell abgefangen werden ??? : @implementation NSFloatNumber(XmlRpcCoding) + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_coder { return [[[NSNumber alloc] initWithDouble:[_coder decodeDouble]] autorelease]; } - (NSString *)xmlRpcType { return @"double"; } @end /* NSFloatNumber(XmlRpcCoding) */ @implementation NSDoubleNumber(XmlRpcCoding) + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_coder { return [[[NSNumber alloc] initWithDouble:[_coder decodeDouble]] autorelease]; } - (NSString *)xmlRpcType { return @"double"; } @end /* NSDoubleNumber(XmlRpcCoding) */ #endif SOPE/sope-xml/XmlRpc/NSData+XmlRpcCoding.m0000644000000000000000000000221715004363604017113 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcMethodResponse.h" #include "common.h" #include "XmlRpcCoder.h" @implementation NSData(XmlRpcCoding) - (NSString *)xmlRpcType { return @"base64"; } - (void)encodeWithXmlRpcCoder:(XmlRpcEncoder *)_coder { [_coder encodeBase64:self]; } + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_coder { return [_coder decodeBase64]; } @end /* NSData(XmlRpcCoding) */ SOPE/sope-xml/XmlRpc/XmlRpc-Info.plist0000644000000000000000000000133515004363604016451 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable XmlRpc CFBundleGetInfoString CFBundleIdentifier org.OpenGroupware.SOPE.xml.XmlRpc CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType FMWK CFBundleShortVersionString CFBundleSignature ???? CFBundleVersion 4.5 SOPE/sope-xml/XmlRpc/NSString+XmlRpcCoding.m0000644000000000000000000000226015004363604017506 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcMethodResponse.h" #include "NSObject+XmlRpc.h" #include "XmlRpcCoder.h" #include "common.h" @implementation NSString(XmlRpcCoding) + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_coder { return [_coder decodeString]; } - (NSString *)xmlRpcType { return @"string"; } - (void)encodeWithXmlRpcCoder:(XmlRpcEncoder *)_coder { [_coder encodeString:self]; } @end /* NSString(XmlRpcCoding) */ SOPE/sope-xml/XmlRpc/Version0000644000000000000000000000004515004363604014643 0ustar rootroot# version file SUBMINOR_VERSION:=31 SOPE/sope-xml/XmlRpc/XmlRpcMethodCall.h0000644000000000000000000000257715004363604016622 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __XmlRpcMethodCall_H__ #define __XmlRpcMethodCall_H__ #import @class NSString, NSArray, NSData; @interface XmlRpcMethodCall : NSObject { NSString *methodName; NSArray *parameters; } - (id)initWithXmlRpcString:(NSString *)_xmlRpcString; - (id)initWithXmlRpcData:(NSData *)_xmlRpcData; - (id)initWithMethodName:(NSString *)_name parameters:(NSArray *)_params; /* accessors */ - (void)setMethodName:(NSString *)_name; - (NSString *)methodName; - (void)setParameters:(NSArray *)_params; - (NSArray *)parameters; - (NSString *)xmlRpcString; @end #endif /* __XmlRpcMethodCall_H__ */ SOPE/sope-xml/XmlRpc/XmlRpcCoder.h0000644000000000000000000001216015004363604015627 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __XmlRpc_XmlRpcCoder_H__ #define __XmlRpc_XmlRpcCoder_H__ #import @class NSDictionary, NSArray, NSNumber, NSString, NSCalendarDate, NSData; @class NSMutableArray, NSMutableString, NSTimeZone, NSDate; @class XmlRpcValue, XmlRpcMethodCall, XmlRpcMethodResponse; /*" The XmlRpcEncoder is used to encode XML-RPC objects. It's pretty much like NSArchiver, only for XML-RPC. Encoder example: NSMutableString *str; // asume that exists XmlRpcMethodResponse *methodResponse; // asume that exists XmlRpcMethodCall *methodCall; // asume that exists coder = [[XmlRpcEncoder alloc] initForWritingWithMutableString:str]; [coder encodeMethodCall:methodCall]; // or [coder encodeMethodResponse:methodResponse]; "*/ @interface XmlRpcEncoder : NSObject { NSMutableString *string; NSMutableArray *objectStack; NSMutableArray *objectHasStructStack; NSTimeZone *timeZone; } - (id)initForWritingWithMutableString:(NSMutableString *)_string; - (void)encodeMethodCall:(XmlRpcMethodCall *)_methodCall; - (void)encodeMethodResponse:(XmlRpcMethodResponse *)_methodResponse; - (void)encodeStruct:(NSDictionary *)_struct; - (void)encodeArray:(NSArray *)_array; - (void)encodeBase64:(NSData *)_data; - (void)encodeBoolean:(BOOL)_number; - (void)encodeInt:(int)_number; - (void)encodeDouble:(double)_number; - (void)encodeString:(NSString *)_string; - (void)encodeDateTime:(NSDate *)_date; - (void)encodeObject:(id)_object; - (void)encodeStruct:(NSDictionary *)_struct forKey:(NSString *)_key; - (void)encodeArray:(NSArray *)_array forKey:(NSString *)_key; - (void)encodeBase64:(NSData *)_data forKey:(NSString *)_key; - (void)encodeBoolean:(BOOL)_number forKey:(NSString *)_key; - (void)encodeInt:(int)_number forKey:(NSString *)_key; - (void)encodeDouble:(double)_number forKey:(NSString *)_key; - (void)encodeString:(NSString *)_string forKey:(NSString *)_key; - (void)encodeDateTime:(NSDate *)_date forKey:(NSString *)_key; - (void)encodeObject:(id)_object forKey:(NSString *)_key; - (void)setDefaultTimeZone:(NSTimeZone *)_timeZone; - (NSTimeZone *)defaultTimeZone; @end @class NSMutableSet; /*" The XmlRpcDecoder is used to decode XML-RPC objects. It's pretty much like NSUnarchiver, only for XML-RPC. Decoder example: NSString *xmlRpcString; // asume that exists XmlRpcMethodCall *methodCall = nil; XmlRpcMethodResponse *methodResponse = nil; coder = [[XmlRpcDecoder alloc] initForReadingWithString:xmlRpcString]; methodCall = [coder decodeMethodCall]; // or methodResponse = [coder decodeMethodResponse]; "*/ @interface XmlRpcDecoder : NSObject { NSData *data; NSMutableArray *valueStack; unsigned nesting; NSMutableArray *unarchivedObjects; NSMutableSet *awakeObjects; NSTimeZone *timeZone; } - (id)initForReadingWithString:(NSString *)_string; - (id)initForReadingWithData:(NSData *)_data; - (XmlRpcMethodCall *)decodeMethodCall; - (XmlRpcMethodResponse *)decodeMethodResponse; /* decoding */ - (NSDictionary *)decodeStruct; - (NSArray *)decodeArray; - (NSData *)decodeBase64; - (BOOL)decodeBoolean; - (int)decodeInt; - (double)decodeDouble; - (NSString *)decodeString; - (NSCalendarDate *)decodeDateTime; - (id)decodeObject; - (NSDictionary *)decodeStructForKey:(NSString *)_key; - (NSArray *)decodeArrayForKey:(NSString *)_key; - (NSData *)decodeBase64ForKey:(NSString *)_key; - (BOOL)decodeBooleanForKey:(NSString *)_key; - (int)decodeIntForKey:(NSString *)_key; - (double)decodeDoubleForKey:(NSString *)_key; - (NSString *)decodeStringForKey:(NSString *)_key; - (NSCalendarDate *)decodeDateTimeForKey:(NSString *)_key; - (id)decodeObjectForKey:(NSString *)_key; - (void)setDefaultTimeZone:(NSTimeZone *)_timeZone; - (NSTimeZone *)defaultTimeZone; /* operations */ - (void)ensureObjectAwake:(id)_object; - (void)finishInitializationOfObjects; - (void)awakeObjects; @end @interface NSObject(XmlRpcCoder) + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_decoder; - (void)encodeWithXmlRpcCoder:(XmlRpcEncoder *)_coder; @end @interface NSObject(XmlRpcDecoderAwakeMethods) - (void)finishInitializationWithXmlRpcDecoder:(XmlRpcDecoder *)_decoder; - (void)awakeFromXmlRpcDecoder:(XmlRpcDecoder *)_decoder; @end #endif /* __XmlRpc_XmlRpcCoder_H__ */ SOPE/sope-xml/XmlRpc/XmlRpcMethodResponse.h0000644000000000000000000000233315004363604017533 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __XmlRpcMethodResponse_H__ #define __XmlRpcMethodResponse_H__ #import @class NSString, NSData; @interface XmlRpcMethodResponse : NSObject { id result; } - (id)initWithXmlRpcString:(NSString *)_xmlRpcString; - (id)initWithXmlRpcData:(NSData *)_data; - (id)initWithResult:(id)_result; /* accessors */ - (void)setResult:(id)_result; - (id)result; - (NSString *)xmlRpcString; @end #endif /* __XmlRpcMethodResponse_H__ */ SOPE/sope-xml/XmlRpc/NSArray+XmlRpcCoding.m0000644000000000000000000000455615004363604017330 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcMethodResponse.h" #include "XmlRpcCoder.h" #include "NSObject+XmlRpc.h" #include "common.h" @implementation NSEnumerator(XmlRpcCoding) - (NSString *)xmlRpcType { return @"array"; } - (void)encodeWithXmlRpcCoder:(XmlRpcEncoder *)_coder { NSMutableArray *objs; id obj; /* make a copy to keep the enum state */ self = [self copy]; objs = [[NSMutableArray alloc] initWithCapacity:16]; while ((obj = [self nextObject])) [objs addObject:obj]; [_coder encodeArray:objs]; [objs release]; [self release]; } + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_coder { return [[_coder decodeArray] objectEnumerator]; } @end /* NSEnumerator(XmlRpc) */ @implementation NSArray(XmlRpcCoding) - (NSString *)xmlRpcType { return @"array"; } - (NSArray *)xmlRpcElementSignature { unsigned i, count; NSMutableArray *ma; if ((count = [self count]) == 0) return [NSArray array]; ma = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) [ma addObject:[[self objectAtIndex:i] xmlRpcType]]; return ma; } - (void)encodeWithXmlRpcCoder:(XmlRpcEncoder *)_coder { [_coder encodeArray:self]; } + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_coder { return [_coder decodeArray]; } @end /* NSArray(XmlRpc) */ @implementation NSSet(XmlRpcCoding) - (NSString *)xmlRpcType { return @"array"; } - (void)encodeWithXmlRpcCoder:(XmlRpcEncoder *)_coder { [_coder encodeArray:[self allObjects]]; } + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_coder { return [NSSet setWithArray:[_coder decodeArray]]; } @end /* NSSet(XmlRpcCoding) */ SOPE/sope-xml/XmlRpc/XmlRpcSaxHandler.m0000644000000000000000000004245315004363604016641 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcSaxHandler.h" #include "XmlRpcMethodCall.h" #include "XmlRpcMethodResponse.h" #include "NSObject+XmlRpc.h" #include "XmlRpcValue.h" #include "common.h" @implementation XmlRpcSaxHandler /*" The SAX handler used to decode XML-RPC responses and requests. If the parsing finishes successfully, either -methodCall or -methodResponse will return an properly initialized object representing the XML-RPC response. The SAX handler is used by the XmlRpcDecoder class internally, in most cases you shouldn't need to access it directly. "*/ static Class ArrayClass = Nil; static Class DictionaryClass = Nil; static BOOL doDebug = NO; + (void)initialize { if (ArrayClass == Nil) ArrayClass = [NSMutableArray class]; if (DictionaryClass == Nil) DictionaryClass = [NSMutableDictionary class]; } - (void)reset { if (doDebug) NSLog(@"%s: begin ...", __PRETTY_FUNCTION__); [self->response release]; self->response = nil; [self->call release]; self->call = nil; [self->methodName release]; self->methodName = nil; [self->params release]; self->params = nil; // for recursive structures (struct, array) [self->valueStack removeAllObjects]; [self->className release]; self->className = nil; [self->memberNameStack removeAllObjects]; [self->memberValueStack removeAllObjects]; [self->timeZone release]; self->timeZone = nil; [self->dateTime release]; self->dateTime = nil; [self->characters setString:@""]; self->valueNestingLevel = 0; self->nextCharactersProcessor = NULL; self->invalidCall = NO; [self->tagStack removeAllObjects]; } - (void)dealloc { [self reset]; [self->characters release]; [self->tagStack release]; [self->valueStack release]; [self->memberNameStack release]; [self->memberValueStack release]; [super dealloc]; } /* accessors */ - (XmlRpcMethodCall *)methodCall { return self->call; } - (XmlRpcMethodResponse *)methodResponse { return self->response; } - (id)result { return [self->params lastObject]; // => NSException || XmlRpcValue } /* *** */ - (void)_addValueToParas:(id)_value { id topValue = [(XmlRpcValue *)[self->valueStack lastObject] value]; if ([topValue isKindOfClass:ArrayClass]) [topValue addObject:_value]; else if ([topValue isKindOfClass:DictionaryClass]) [self->memberValueStack addObject:_value]; else [self->params addObject:_value]; } /* document */ - (void)startDocument { if (doDebug) NSLog(@"%s: begin ...", __PRETTY_FUNCTION__); [self reset]; if (self->tagStack == nil) self->tagStack = [[NSMutableArray alloc] initWithCapacity:8]; if (self->valueStack == nil) self->valueStack = [[NSMutableArray alloc] initWithCapacity:8]; if (self->characters == nil) self->characters = [[NSMutableString alloc] initWithCapacity:128]; if (doDebug) NSLog(@"%s: done ...", __PRETTY_FUNCTION__); } - (void)endDocument { if (doDebug) NSLog(@"%s: begin ...", __PRETTY_FUNCTION__); if ([self->tagStack count] > 0) { self->invalidCall = YES; NSLog(@"Warning(%s): tagStack is not empty (%@)", __PRETTY_FUNCTION__, self->tagStack); } if (self->call != nil && self->response != nil) { self->invalidCall = YES; NSLog(@"Warning(%s): got methodCall *AND* methodResponse!!! (%@<->%@)", __PRETTY_FUNCTION__, self->call, self->response); } if (self->invalidCall) { if (doDebug) NSLog(@"%s: marked as invalid call!", __PRETTY_FUNCTION__); [self->call release]; self->call = nil; [self->response release]; self->response = nil; } if (doDebug) NSLog(@"%s: done ...", __PRETTY_FUNCTION__); } /* elements */ - (void)start_name:(id)_attrs { self->nextCharactersProcessor = @selector(_name:length:); } - (void)end_name { self->nextCharactersProcessor = NULL; } - (void)_name:(unichar *)_chars length:(NSUInteger)_len { NSString *name; name = [NSString stringWithCharacters:_chars length:_len]; [self->memberNameStack addObject:name]; } - (void)start_params:(id)_attrs { if (self->params) { self->invalidCall = YES; return; } self->params = [[NSMutableArray alloc] initWithCapacity:8]; } - (void)end_params { if (self->params == nil) self->invalidCall =YES; } - (void)start_value:(id)_attrs { self->valueNestingLevel++; self->nextCharactersProcessor = @selector(_baseValue:length:); } - (void)end_value { self->valueNestingLevel--; } - (void)_dateValue:(unichar *)_chars length:(NSUInteger)_len { if (self->dateTime) return; self->dateTime = [[NSObject objectWithXmlRpcType:@"dateTime.iso8601" characters:_chars length:_len] retain]; } - (void)_baseValue:(unichar *)_chars length:(NSUInteger)_len { id value; if (self->valueNestingLevel == 0) { NSLog(@"%s: invalidCall......... self->valueNestingLevel = 0", __PRETTY_FUNCTION__); return; } value = [NSObject objectWithXmlRpcType:[self->tagStack lastObject] characters:_chars length:_len]; if (value == nil) value = [NSNull null]; value = [[XmlRpcValue alloc] initWithValue:value className:self->className]; if (self->params == nil) { NSLog(@"%s: invalidCall......... self->params = nil", __PRETTY_FUNCTION__); return; } [self _addValueToParas:value]; [value release]; } - (void)start_i4:(id)_attrs { self->nextCharactersProcessor = @selector(_baseValue:length:); } - (void)start_int:(id)_attrs { self->nextCharactersProcessor = @selector(_baseValue:length:); } - (void)start_double:(id)_attrs { self->nextCharactersProcessor = @selector(_baseValue:length:); } - (void)start_base64:(id)_attrs { self->nextCharactersProcessor = @selector(_baseValue:length:); } - (void)start_boolean:(id)_attrs { self->nextCharactersProcessor = @selector(_baseValue:length:); } - (void)start_string:(id)_attrs { self->nextCharactersProcessor = @selector(_baseValue:length:); } - (void)start_dateTime:(id)_attrs { NSString *tz; NSUInteger idx; [self->timeZone release]; self->timeZone = nil; [self->dateTime release]; self->dateTime = nil; tz = ((idx = [_attrs indexOfRawName:@"timeZone"]) != NSNotFound) ? (id)[_attrs valueAtIndex:idx] : nil; if (tz) { self->timeZone = [[NSTimeZone timeZoneWithAbbreviation:tz] retain]; } self->nextCharactersProcessor = @selector(_dateValue:length:); } - (void)end_dateTime { if (self->dateTime) { NSCalendarDate *date; XmlRpcValue *value; int secFromGMT; if ([self->dateTime respondsToSelector:@selector(setTimeZone:)]) { secFromGMT = [self->timeZone secondsFromGMT]; [self->dateTime setTimeZone:self->timeZone]; date = [self->dateTime dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 seconds:-secFromGMT]; } else { NSLog(@"WARNING(%s): cannot set timezone on date: %@", __PRETTY_FUNCTION__, self->dateTime); date = self->dateTime; } value = [[XmlRpcValue alloc] initWithValue:date className:@"NSCalendarDate"]; [value autorelease]; [self _addValueToParas:value]; } [self->timeZone release]; self->timeZone = nil; [self->dateTime release]; self->dateTime = nil; self->nextCharactersProcessor = NULL; } - (void)start_array:(id)_attrs { id value = [NSMutableArray arrayWithCapacity:8]; value = [[XmlRpcValue alloc] initWithValue:value className:self->className]; [self _addValueToParas:value]; [self->valueStack addObject:value]; self->nextCharactersProcessor = NULL; [value release]; } - (void)end_array { if ([self->valueStack count] > 0) [self->valueStack removeLastObject]; else { NSLog(@"%s: valueStack should be empty: %@", __PRETTY_FUNCTION__, self->valueStack); } } - (void)start_struct:(id)_attrs { id value = [NSMutableDictionary dictionaryWithCapacity:8]; value = [[XmlRpcValue alloc] initWithValue:value className:self->className]; [self _addValueToParas:value]; [self->valueStack addObject:value]; self->nextCharactersProcessor = NULL; [value release]; } - (void)end_struct { if ([self->valueStack count] > 0) [self->valueStack removeLastObject]; else { NSLog(@"%s: valueStack should be empty: %@", __PRETTY_FUNCTION__, self->valueStack); } } - (void)start_member:(id)_attrs { if (![[(XmlRpcValue *)[self->valueStack lastObject] value] isKindOfClass:DictionaryClass]) { self->invalidCall = YES; } else { if (self->memberNameStack == nil) self->memberNameStack = [[NSMutableArray alloc] initWithCapacity:8]; if (self->memberValueStack == nil) self->memberValueStack = [[NSMutableArray alloc] initWithCapacity:8]; } self->nextCharactersProcessor = NULL; } - (void)end_member { id tmp; // TODO: can't we type the var? tmp = [(XmlRpcValue *)[self->valueStack lastObject] value]; if ([self->memberNameStack count] != [self->memberValueStack count]) { NSLog(@"Warning(%s): memberNameStack.count != memberValueStack.count" @" (%@ <--> %@)", __PRETTY_FUNCTION__, self->memberNameStack, self->memberValueStack, nil); [self->memberValueStack release]; self->memberValueStack = nil; [self->memberNameStack release]; self->memberNameStack = nil; self->invalidCall = YES; } else if ([self->memberNameStack count] == 0) { NSLog(@"Warning(%s): memberNameStack and memberValueStack are empty!", __PRETTY_FUNCTION__, nil); [self->memberValueStack release]; self->memberValueStack = nil; [self->memberNameStack release]; self->memberNameStack = nil; self->invalidCall = YES; } else if (![tmp isKindOfClass:DictionaryClass]) self->invalidCall = YES; else { [(NSMutableDictionary *)tmp setObject:[self->memberValueStack lastObject] forKey:[self->memberNameStack lastObject]]; [self->memberNameStack removeLastObject]; [self->memberValueStack removeLastObject]; } } - (void)start_methodCall:(id)_attrs { /* can't create call here, args unknown !!! */ if (self->call != nil) { if (doDebug) NSLog(@"%s: method-call already setup!", __PRETTY_FUNCTION__); self->invalidCall = YES; return; } if (doDebug) NSLog(@"%s: ...", __PRETTY_FUNCTION__); } - (void)end_methodCall { if (self->call != nil) { if (doDebug) NSLog(@"%s: method-call already setup!", __PRETTY_FUNCTION__); self->invalidCall = YES; return; } self->call = [[XmlRpcMethodCall alloc] initWithMethodName:self->methodName parameters:self->params]; /* reset args */ [self->methodName release]; self->methodName = nil; [self->params release]; self->params = nil; } - (void)start_methodResponse:(id)_attrs { if (self->response != nil) { if (doDebug) NSLog(@"%s: method-response already setup!", __PRETTY_FUNCTION__); self->invalidCall = YES; return; } } - (void)end_methodResponse { if (doDebug) NSLog(@"%s: begin ...", __PRETTY_FUNCTION__); if (self->response != nil) { if (doDebug) NSLog(@"%s: method-response already setup!", __PRETTY_FUNCTION__); self->invalidCall = YES; return; } if ([self->params count] > 1) { if (doDebug) { NSLog(@"%s: has more than one params (%"PRIuPTR")!", __PRETTY_FUNCTION__, [self->params count]); } self->invalidCall = YES; } if (self->invalidCall) { NSException *error; if (doDebug) NSLog(@"%s: response marked as invalid!", __PRETTY_FUNCTION__); error = [NSException exceptionWithName:@"error while parsing response" reason:@"error while parsing response" userInfo:nil]; [self->params release]; self->params = [[NSMutableArray arrayWithObject:error] retain]; } self->response = [[XmlRpcMethodResponse alloc] initWithResult:[self->params lastObject]]; if (doDebug) NSLog(@"%s: response: %@", __PRETTY_FUNCTION__, self->response); /* reset args */ [self->params release]; self->params = nil; if (doDebug) NSLog(@"%s: done.", __PRETTY_FUNCTION__); } - (void)start_methodName:(id)_attrs { if (self->call != nil) { self->invalidCall = YES; return; } self->nextCharactersProcessor = @selector(_methodName:length:); } - (void)end_methodName { self->nextCharactersProcessor = NULL; } - (void)_methodName:(unichar *)_chars length:(NSUInteger)_len { [self->methodName release]; self->methodName = [[NSString alloc] initWithCharacters:_chars length:_len]; } - (void)start_fault:(id)_attrs { if (self->params) { self->invalidCall = YES; return; } else self->params = [[NSMutableArray alloc] initWithCapacity:2]; self->nextCharactersProcessor = NULL; } - (void)end_fault { if (self->params == nil) self->invalidCall = YES; self->nextCharactersProcessor = NULL; /* fixup result class */ if ([self->params count] != 1) { NSLog(@"XML-RPC: incorrect params count (should be 1 for faults) ?: %@", self->params); } else { XmlRpcValue *fault; fault = [self->params objectAtIndex:0]; if (![fault isException]) { if ([fault isDictionary]) { [fault setClassName:@"NSException"]; } else { NSException *e; NSString *name; NSString *reason; NSLog(@"XML-RPC: got incorrect fault object (class=%@) ?: %@", [fault className], fault); name = [NSString stringWithFormat:@"XmlRpcFault<%@>", [fault valueForKey:@"faultCode"]]; if (name == nil) name = @"GenericXmlRpcFault"; reason = [fault valueForKey:@"faultString"]; if (reason == nil) reason = name; e = [NSException exceptionWithName:name reason:reason userInfo:nil]; [self->params replaceObjectAtIndex:0 withObject:e]; } } } } /* generic dispatcher */ - (void)startElement:(NSString *)_localName namespace:(NSString *)_ns rawName:(NSString *)_rawName attributes:(id)_attrs { NSString *tmp = nil; SEL sel; NSUInteger idx; [self->tagStack addObject:_rawName]; tmp = ((idx = [_attrs indexOfRawName:@"NSObjectClass"]) != NSNotFound) ? (id)[_attrs valueAtIndex:idx] : nil; [self->className autorelease]; self->className = [tmp retain]; if (self->invalidCall) return; if ([_rawName isEqualToString:@"dateTime.iso8601"]) _rawName = @"dateTime"; [self->characters setString:@""]; tmp = [NSString stringWithFormat:@"start_%@:",_rawName]; if ((sel = NSSelectorFromString(tmp))) { if ([self respondsToSelector:sel]) [self performSelector:sel withObject:_attrs]; } } - (void)endElement:(NSString *)_localName namespace:(NSString *)_ns rawName:(NSString *)_rawName { NSUInteger stackDepth, lastIdx; NSString *tmp; SEL sel; if (self->nextCharactersProcessor != NULL) { void (*m)(id, SEL, unichar *, NSUInteger); unichar *chars; NSUInteger len; len = [self->characters length]; chars = malloc(sizeof(unichar)*len); [self->characters getCharacters:chars]; if ((m = (void*)[self methodForSelector:self->nextCharactersProcessor])) m(self, self->nextCharactersProcessor, chars, len); free(chars); } self->nextCharactersProcessor = NULL; if ((stackDepth = [self->tagStack count]) == 0) { self->invalidCall = YES; return; } lastIdx = stackDepth - 1; if (![[self->tagStack objectAtIndex:lastIdx] isEqualToString:_rawName]) { self->invalidCall = YES; return; } [self->tagStack removeObjectAtIndex:lastIdx]; stackDepth--; if (self->invalidCall) { return; } if ([_rawName isEqualToString:@"dateTime.iso8601"]) _rawName = @"dateTime"; tmp = [NSString stringWithFormat:@"end_%@", _rawName]; if ((sel = NSSelectorFromString(tmp))) { if ([self respondsToSelector:sel]) [self performSelector:sel]; } } - (void)characters:(unichar *)_chars length:(NSUInteger)_len { if (_len > 0) { [self->characters appendString: [NSString stringWithCharacters:_chars length:_len]]; } } /* errors */ - (void)warning:(SaxParseException *)_exception { NSLog(@"XML-RPC warning: %@", _exception); } - (void)error:(SaxParseException *)_exception { NSLog(@"XML-RPC error: %@", _exception); } @end /* XmlRpcSaxHandler */ SOPE/sope-xml/XmlRpc/NSMutableString+XmlRpcDecoder.m0000644000000000000000000001015515004363604021164 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #include @implementation NSMutableString(XmlRpcDecoder) - (void)appendXmlRpcString:(NSString *)_value { #if 1 // TODO: to be tested ! unsigned i, j, len; unichar *buf, *escbuf = NULL; if ((len = [_value length]) == 0) /* nothing to add ... */ return; if (len == 1) { /* a single char */ unichar c; switch ((c = [_value characterAtIndex:0])) { case '&': [self appendString:@"&"]; break; case '<': [self appendString:@"<"]; break; case '>': [self appendString:@">"]; break; case '"': [self appendString:@"""]; break; default: [self appendString:_value]; break; } return; } buf = calloc(len + 2, sizeof(unichar)); [_value getCharacters:buf]; for (i = 0, j = 0; i < len; i++) { switch (buf[i]) { case '&': case '<': case '>': case '"': { if (escbuf == NULL) { /* worst case: string consists of quotes */ escbuf = calloc(len * 6 + 2, sizeof(unichar)); memcpy(escbuf, buf, i * sizeof(unichar)); j = i; } escbuf[j++] = '&'; switch (buf[i]) { case '&': escbuf[j++] = 'a'; escbuf[j++] = 'm'; escbuf[j++] = 'p'; break; case '<': escbuf[j++] = 'l'; escbuf[j++] = 't'; break; case '>': escbuf[j++] = 'g'; escbuf[j++] = 't'; break; case '"': escbuf[j++] = 'q'; escbuf[j++] = 'u'; escbuf[j++] = 'o'; escbuf[j++] = 't'; break; } escbuf[j++] = ';'; break; } default: if (escbuf) escbuf[j++] = buf[i]; break; } } if (escbuf) { NSString *s; s = [[NSString alloc] initWithCharacters:escbuf length:j]; [self appendString:s]; [s release]; free(escbuf); } else [self appendString:_value]; if (buf) free(buf); #else #warning UNICODE !!! void (*addBytes)(id,SEL,const char *,unsigned); id dummy = nil; unsigned clen; unsigned char *cbuf; unsigned char *cstr; if ([_value length] == 0) return; clen = [_value cStringLength]; if (clen == 0) return; /* nothing to add .. */ cbuf = cstr = malloc(clen + 1); [_value getCString:cbuf]; cbuf[clen] = '\0'; dummy = [[NSMutableData alloc] initWithCapacity:2*clen]; addBytes = (void*)[dummy methodForSelector:@selector(appendBytes:length:)]; NSAssert(addBytes != NULL, @"could not get appendBytes:length: .."); while (*cstr) { switch (*cstr) { case '&': addBytes(dummy, @selector(appendBytes:length:), "&", 5); break; case '<': addBytes(dummy, @selector(appendBytes:length:), "<", 4); break; case '>': addBytes(dummy, @selector(appendBytes:length:), ">", 4); break; case '"': addBytes(dummy, @selector(appendBytes:length:), """, 6); break; default: addBytes(dummy, @selector(appendBytes:length:), cstr, 1); break; } cstr++; } free(cbuf); { NSString *tmp = nil; tmp = [[NSString alloc] initWithData:dummy encoding:[NSString defaultCStringEncoding]]; [self appendString:tmp]; [tmp release]; } #endif } @end /* NSMutableString(XmlRpcDecoder) */ SOPE/sope-xml/XmlRpc/XmlRpc.h0000644000000000000000000000177415004363604014663 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __XmlRpc_XmlRpc_H__ #define __XmlRpc_XmlRpc_H__ #include #include #include #include #endif /* __XmlRpc_XmlRpc_H__ */ SOPE/sope-xml/XmlRpc/COPYRIGHT0000644000000000000000000000010615004363604014564 0ustar rootrootCopyright (C) 2000-2005 SKYRIX Software AG Contact: info@skyrix.com SOPE/sope-xml/XmlRpc/NSNotification+XmlRpcCoding.m0000644000000000000000000000310715004363604020667 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcMethodResponse.h" #include "common.h" #include "XmlRpcCoder.h" @implementation NSNotification(XmlRpcCoding) - (NSString *)xmlRpcType { return @"struct"; } + (id)decodeObjectWithXmlRpcCoder:(XmlRpcDecoder *)_coder { self = (id)[NSNotification notificationWithName: [_coder decodeStringForKey:@"name"] object:[_coder decodeObjectForKey:@"object"] userInfo:[_coder decodeStructForKey:@"userInfo"]]; return self; } - (void)encodeWithXmlRpcCoder:(XmlRpcEncoder *)_coder { NSString *n; n = [self name]; [_coder encodeString:n forKey:@"name"]; [_coder encodeObject:[self object] forKey:@"object"]; [_coder encodeStruct:[self userInfo] forKey:@"userInfo"]; } @end /* NSNotification(XmlRpcCoding) */ SOPE/sope-xml/XmlRpc/XmlRpcMethodCall.m0000644000000000000000000000777715004363604016636 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "common.h" @interface XmlRpcMethodCall(PrivateMethodes) - (NSString *)_encodeXmlRpcMethodCall; @end @implementation XmlRpcMethodCall - (id)initWithXmlRpcString:(NSString *)_string { XmlRpcDecoder *coder; XmlRpcMethodCall *baseCall; if ([_string length] == 0) { [self release]; return nil; } coder = [[XmlRpcDecoder alloc] initForReadingWithString:_string]; baseCall = [coder decodeMethodCall]; [coder release]; if (baseCall == nil) { [self release]; return nil; } self = [self initWithMethodName:[baseCall methodName] parameters:[baseCall parameters]]; return self; } - (id)initWithXmlRpcData:(NSData *)_xmlRpcData { XmlRpcDecoder *coder; XmlRpcMethodCall *baseCall; if ([_xmlRpcData length] == 0) { [self release]; return nil; } coder = [[XmlRpcDecoder alloc] initForReadingWithData:_xmlRpcData]; baseCall = [coder decodeMethodCall]; [coder release]; if (baseCall == nil) { [self release]; return nil; } self = [self initWithMethodName:[baseCall methodName] parameters:[baseCall parameters]]; return self; } - (id)initWithMethodName:(NSString *)_name parameters:(NSArray *)_params { if ((self = [super init])) { self->methodName = [_name copy]; [self setParameters:_params]; } return self; } - (void)dealloc { [self->methodName release]; [self->parameters release]; [super dealloc]; } /* accessors */ - (void)setMethodName:(NSString *)_name { [self->methodName autorelease]; self->methodName = [_name copy]; } - (NSString *)methodName { return self->methodName; } - (void)setParameters:(NSArray *)_params { if (self->parameters != _params) { unsigned i, cc; id *objects; [self->parameters autorelease]; /* shallow copy parameters, it is implemented here 'by-hand', since skyrix-xml is not dependend on EOControl */ cc = [_params count]; objects = calloc(cc + 1, sizeof(id)); for (i = 0; i < cc; i++) objects[i] = [_params objectAtIndex:i]; self->parameters = [[NSArray alloc] initWithObjects:objects count:cc]; if (objects) free(objects); } } - (NSArray *)parameters { return self->parameters; } - (NSString *)xmlRpcString { return [self _encodeXmlRpcMethodCall]; } /* description */ - (NSString *)description { NSMutableString *s; s = [NSMutableString stringWithFormat:@"<0x%p[%@]: ", self, NSStringFromClass([self class])]; [s appendFormat:@"method=%@", [self methodName]]; [s appendFormat:@" #paras=%"PRIuPTR, [self->parameters count]]; [s appendString:@">"]; return s; } @end /* XmlRpcMethodCall */ @implementation XmlRpcMethodCall(PrivateMethodes) - (NSString *)_encodeXmlRpcMethodCall { NSMutableString *str; XmlRpcEncoder *coder; #if DEBUG NSAssert1(self->methodName, @"%s, methodName is not allowed to be nil!", __PRETTY_FUNCTION__); #endif str = [NSMutableString stringWithCapacity:512]; coder = [[XmlRpcEncoder alloc] initForWritingWithMutableString:str]; [coder encodeMethodCall:self]; [coder release]; coder = nil; return str; } @end /* XmlRpcMethodCall(PrivateMethodes) */ SOPE/sope-xml/XmlRpc/XmlRpcResponseDecoder.m0000644000000000000000000000476015004363604017673 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "XmlRpcCoder.h" #include "XmlRpcSaxHandler.h" #include #include "common.h" @implementation XmlRpcResponseDecoder static id saxResponseHandler = nil; static id responseParser = nil; - (void)_ensureSaxAndParser { if (saxResponseHandler == nil) { if ((saxResponseHandler = [[XmlRpcSaxResponseHandler alloc] init])==nil) { NSLog(@"%s: did not find sax handler ...", __PRETTY_FUNCTION__); return; } } if (responseParser != nil) return; responseParser = [[SaxXMLReaderFactory standardXMLReaderFactory] createXMLReaderForMimeType:@"text/xml"]; if (responseParser == nil) { NSLog(@"%s: did not find an XML parser ...", __PRETTY_FUNCTION__); return; } responseParser = [responseParser retain]; [responseParser setContentHandler:saxResponseHandler]; [responseParser setDTDHandler:saxResponseHandler]; [responseParser setErrorHandler:saxResponseHandler]; } - (id)decodeRootObject { static Class ExceptionClass = Nil; id result; [self _ensureSaxAndParser]; if (ExceptionClass == Nil) ExceptionClass = [NSException class]; [saxResponseHandler reset]; [responseParser parseFromSource:self->string systemId:nil]; result = [saxResponseHandler result]; if ([result isKindOfClass:ExceptionClass]) { return result; } else { // => XmlRpcValue XmlRpcValue *val = result; Class objClass = Nil; id obj; [self->value autorelease]; self->value = [val retain]; if ((objClass = NSClassFromString([val className])) != Nil) { obj = [objClass decodeObjectWithXmlRpcCoder:self]; return obj; } } return nil; } @end /* XmlRpcResponseDecoder */ SOPE/sope-xml/XmlRpc/GNUmakefile.preamble0000644000000000000000000000272615004363604017143 0ustar rootroot# compilation settings include ./Version libXmlRpc_HEADER_FILES_DIR = . libXmlRpc_HEADER_FILES_INSTALL_DIR = /XmlRpc libXmlRpc_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION) libXmlRpc_INSTALL_DIR=$(SOPE_SYSLIBDIR) libXmlRpc_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION) XmlRpc_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION) XmlRpc_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION) ADDITIONAL_CPPFLAGS += \ -O2 \ -Wall -DCOMPILE_FOR_GSTEP_MAKE=1 \ -DSOPE_MAJOR_VERSION=$(MAJOR_VERSION) \ -DSOPE_MINOR_VERSION=$(MINOR_VERSION) \ -DSOPE_SUBMINOR_VERSION=$(SUBMINOR_VERSION) # framework support XmlRpc_HEADER_FILES = $(libXmlRpc_HEADER_FILES) XmlRpc_OBJC_FILES = $(libXmlRpc_OBJC_FILES) libXmlRpc_LIBRARIES_DEPEND_UPON += -lSaxObjC $(BASE_LIBS) ifneq ($(GNUSTEP_BUILD_DIR),) libXmlRpc_LIB_DIRS += \ -L$(GNUSTEP_BUILD_DIR)/../SaxObjC/$(GNUSTEP_OBJ_DIR_NAME) \ -L$(GNUSTEP_BUILD_DIR)/../DOM/$(GNUSTEP_OBJ_DIR_NAME) XmlRpc_LIB_DIRS += -F$(GNUSTEP_BUILD_DIR)/../SaxObjC/ else libXmlRpc_LIB_DIRS += \ -L../SaxObjC/$(GNUSTEP_OBJ_DIR) \ -L../DOM/$(GNUSTEP_OBJ_DIR) XmlRpc_LIB_DIRS += -F../SaxObjC/ endif # Apple ifeq ($(FOUNDATION_LIB),apple) libXmlRpc_PREBIND_ADDR="0xC0400000" libXmlRpc_LDFLAGS += -seg1addr $(libXmlRpc_PREBIND_ADDR) #ADDITIONAL_INCLUDE_DIRS += -framework SaxObjC XmlRpc_FRAMEWORK_LIBS += -framework SaxObjC XmlRpc_LIBRARIES_DEPEND_UPON += -framework SaxObjC endif SOPE/sope-xml/COPYRIGHT0000644000000000000000000000010515004363604013356 0ustar rootrootCopyright (C) 2000-2005 SKYRIX Software AG Contact: info@skyrix.com SOPE/sope-xml/README-OSX.txt0000644000000000000000000000041715004363604014236 0ustar rootrootPlease refer to ../README-OSX.txt for compilation directives. Prebinding Notes (DEPRECATED, for reference only) ================================================= sope-xml: 0xC0000000 - 0xC0FFFFFF 0xC0000000 SaxObjC 0xC0200000 DOM 0xC0400000 XmlRpc 0xC0FF0000 sope-xml SOPE/sope-xml/common.make0000644000000000000000000000050015004363604014211 0ustar rootroot# GNUstep makefile include $(GNUSTEP_MAKEFILES)/common.make ADDITIONAL_CPPFLAGS += -pipe -Wall -Wno-protocol ADDITIONAL_INCLUDE_DIRS += -I.. ADDITIONAL_LIB_DIRS += \ -L./$(GNUSTEP_OBJ_DIR) \ -L../SaxObjC/$(GNUSTEP_OBJ_DIR) \ ifeq ($(FOUNDATION_LIB),nx) ADDITIONAL_LDFLAGS += -framework Foundation endif SOPE/sope-xml/TODO0000644000000000000000000000050515004363604012557 0ustar rootrootTODO ==== - add SAX wrapper for Parsifal ? http://www.saunalahti.fi/~samiuus/toni/xmlproc/ - add a DOM builder which can create a DOM from a libxml2 or CoreFoundation DOM tree instead of using SAX (should be much more efficient) - write a SAX driver based on NSXMLParser (should be an almost trivial 1:1 mapping) SOPE/sope-json/0000755000000000000000000000000015004363604012240 5ustar rootrootSOPE/sope-json/GNUmakefile0000644000000000000000000000032515004363604014312 0ustar rootroot# GNUstep makefile include ../config.make include $(GNUSTEP_MAKEFILES)/common.make SUBPROJECTS += SBJson -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/aggregate.make -include GNUmakefile.postamble SOPE/sope-json/SBJson/0000755000000000000000000000000015004363604013376 5ustar rootrootSOPE/sope-json/SBJson/Installation.markdown0000644000000000000000000000261315004363604017605 0ustar rootrootSuper-simple installation ========================= By *far* the simplest way to start using JSON in your iPhone, iPad, or Mac application is to simply copy all the source files (the contents of the `Classes` folder) into your own Xcode project. 1. In the Finder, open the `json-framework/Classes` folder and select all the files. 1. Drop-and-drop them on the **Classes** group in the **Groups & Files** menu of your Xcode project. 1. Tick the **Copy items into destination group's folder** option. 1. Use `#import "JSON.h"` in your source files. That should be it. Now create that Twitter client! Upgrading --------- If you're upgrading from a previous version, make sure you're deleting the old JSON classes first, moving all the files to Trash. Trouble-shooting ---------------- Check to see if the answers to the [Frequently Asked Questions][faq] are of any help. [faq]: http://github.com/stig/json-framework/wiki/FrequentlyAskedQuestions Alternative installation instructions ===================================== Copying the JSON Classes into your project isn't the *only* way to use this framework. I've created a couple of examples that link to this framework rather than copy the sources. Check them out at github: * [Linking to JSON Framework on the iPhone, iPad & iPod Touch](http://github.com/stig/JsonSampleIPhone) * [Linking to JSON Framework on the Mac](http://github.com/stig/JsonSampleMac) SOPE/sope-json/SBJson/Tests/0000755000000000000000000000000015004363604014500 5ustar rootrootSOPE/sope-json/SBJson/Tests/ProxyTest.m0000644000000000000000000000572415004363604016647 0ustar rootroot/* Copyright (C) 2009-2010 Stig Brautaset. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ #import "ProxyTest.h" #import @interface True : NSObject @end @implementation True - (id)proxyForJson { return [NSNumber numberWithBool:YES]; } @end @interface False : NSObject @end @implementation False - (id)proxyForJson { return [NSNumber numberWithBool:NO]; } @end @interface Bool : NSObject @end @implementation Bool - (id)proxyForJson { return [NSArray arrayWithObjects:[True new], [False new], nil]; } @end @implementation NSDate (Private) - (id)proxyForJson { return [NSArray arrayWithObject:[self description]]; } @end @implementation ProxyTest - (void)testUnsupportedWithoutProxy { STAssertNil([writer stringWithObject:[NSArray arrayWithObject:[NSObject new]]], nil); STAssertEquals([[writer.errorTrace objectAtIndex:0] code], (NSInteger)EUNSUPPORTED, nil); } - (void)testUnsupportedWithProxy { STAssertEqualObjects([writer stringWithObject:[NSArray arrayWithObject:[True new]]], @"[true]", nil); } - (void)testUnsupportedWithProxyWithoutWrapper { STAssertNil([writer stringWithObject:[True new]], nil); } - (void)testUnsupportedWithNestedProxy { STAssertEqualObjects([writer stringWithObject:[NSArray arrayWithObject:[Bool new]]], @"[[true,false]]", nil); } - (void)testUnsupportedWithProxyAsCategory { STAssertNotNil([writer stringWithObject:[NSArray arrayWithObject:[NSDate date]]], nil); } - (void)testUnsupportedWithProxyAsCategoryWithoutWrapper { STAssertNotNil([writer stringWithObject:[NSDate date]], nil); } @end SOPE/sope-json/SBJson/Tests/DataDrivenTest.h0000644000000000000000000000322115004363604017530 0ustar rootroot/* Copyright (C) 2007-2010 Stig Brautaset. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ #import "AbstractTest.h" @interface DataDrivenTest : AbstractTest { SBJsonWriter *prettyWriter; NSString *dir; NSDirectoryEnumerator *files; } @end SOPE/sope-json/SBJson/Tests/DataDrivenTest.m0000644000000000000000000001362515004363604017546 0ustar rootroot/* Copyright (C) 2007-2010 Stig Brautaset. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ #import "DataDrivenTest.h" #import @implementation DataDrivenTest - (void)setUp { [super setUp]; writer.sortKeys = YES; prettyWriter = [SBJsonWriter new]; prettyWriter.humanReadable = YES; prettyWriter.sortKeys = YES; dir = @"Tests/Data"; files = [[NSFileManager defaultManager] enumeratorAtPath:dir]; } - (void)tearDown { [prettyWriter release]; [super tearDown]; } - (void)testTerse { NSString *file; while ((file = [files nextObject])) { if (![[file pathExtension] isEqualToString:@"json"]) continue; NSRange range = [file rangeOfString:@"fail"]; if (range.location != NSNotFound) continue; NSString *jsonPath = [dir stringByAppendingPathComponent:file]; NSString *jsonText = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; STAssertNotNil(jsonText, @"Could not load %@", jsonPath); id parsed; STAssertNoThrow(parsed = [parser objectWithString:jsonText], jsonPath); STAssertNotNil(parsed, jsonPath); STAssertNil(parser.errorTrace, @"%@: %@", jsonPath, parser.errorTrace); NSString *written; STAssertNoThrow(written = [writer stringWithObject:parsed], jsonPath); STAssertNotNil(written, jsonPath); STAssertNil(writer.errorTrace, @"%@: %@", jsonPath, writer.errorTrace); NSString *tersePath = [jsonPath stringByAppendingPathExtension:@"terse"]; NSString *terseText = [NSString stringWithContentsOfFile:tersePath encoding:NSUTF8StringEncoding error:nil]; STAssertNotNil(terseText, @"Could not load %@", tersePath); // Chop off newline at end of string terseText = [terseText substringToIndex:[terseText length]-1]; STAssertEqualObjects(written, terseText, @"at %@", jsonPath); } } - (void)testPretty { NSString *file; while ((file = [files nextObject])) { if (![[file pathExtension] isEqualToString:@"json"]) continue; NSRange range = [file rangeOfString:@"fail"]; if (range.location != NSNotFound) continue; NSString *jsonPath = [dir stringByAppendingPathComponent:file]; NSString *jsonText = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; STAssertNotNil(jsonText, @"Could not load %@", jsonPath); id parsed; STAssertNoThrow(parsed = [parser objectWithString:jsonText], jsonPath); STAssertNotNil(parsed, jsonPath); STAssertNil(parser.errorTrace, @"%@: %@", jsonPath, parser.errorTrace); NSString *written; STAssertNoThrow(written = [prettyWriter stringWithObject:parsed], jsonPath); STAssertNotNil(written, jsonPath); STAssertNil(prettyWriter.errorTrace, @"%@: %@", jsonPath, prettyWriter.errorTrace); NSString *tersePath = [jsonPath stringByAppendingPathExtension:@"pretty"]; NSString *terseText = [NSString stringWithContentsOfFile:tersePath encoding:NSUTF8StringEncoding error:nil]; STAssertNotNil(terseText, @"Could not load %@", tersePath); // Chop off newline at end of string terseText = [terseText substringToIndex:[terseText length]-1]; STAssertEqualObjects(written, terseText, @"at %@", jsonPath); } } - (void)testFail { parser.maxDepth = 19; NSString *file; while ((file = [files nextObject])) { if (![file hasPrefix:@"fail"]) continue; NSString *path = [dir stringByAppendingPathComponent:file]; NSString *json = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; STAssertNil([parser objectWithString:json], path); STAssertNotNil(parser.errorTrace, path); } } @end SOPE/sope-json/SBJson/Tests/ErrorTest.h0000644000000000000000000000305615004363604016606 0ustar rootroot/* Copyright (C) 2010 Stig Brautaset. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ #import "AbstractTest.h" @interface ErrorTest : AbstractTest @end SOPE/sope-json/SBJson/Tests/ErrorTest.m0000644000000000000000000002477415004363604016625 0ustar rootroot/* Copyright (C) 2007-2010 Stig Brautaset. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ #import "ErrorTest.h" #import #define assertErrorContains(e, s) \ STAssertTrue([[e localizedDescription] hasPrefix:s], @"%@", [e userInfo]) #define assertUnderlyingErrorContains(e, s) \ STAssertTrue([[[[e userInfo] objectForKey:NSUnderlyingErrorKey] localizedDescription] hasPrefix:s], @"%@", [e userInfo]) #define assertUnderlyingErrorContains2(e, s) \ STAssertTrue([[[[[[e userInfo] objectForKey:NSUnderlyingErrorKey] userInfo] objectForKey:NSUnderlyingErrorKey] localizedDescription] hasPrefix:s], @"%@", [e userInfo]) @implementation ErrorTest #pragma mark Generator - (void)testUnsupportedObject { NSError *error = nil; STAssertNil([writer stringWithObject:[NSData data] error:&error], nil); STAssertNotNil(error, nil); } - (void)testNonStringDictionaryKey { NSArray *keys = [NSArray arrayWithObjects:[NSNull null], [NSNumber numberWithInt:1], [NSArray array], [NSDictionary dictionary], nil]; for (int i = 0; i < [keys count]; i++) { NSError *error = nil; NSDictionary *object = [NSDictionary dictionaryWithObject:@"1" forKey:[keys objectAtIndex:i]]; STAssertNil([writer stringWithObject:object error:&error], nil); STAssertNotNil(error, nil); } } - (void)testScalar { NSArray *fragments = [NSArray arrayWithObjects:@"foo", @"", [NSNull null], [NSNumber numberWithInt:1], [NSNumber numberWithBool:YES], nil]; for (int i = 0; i < [fragments count]; i++) { NSString *fragment = [fragments objectAtIndex:i]; // We don't check the convenience category here, like we do for parsing, // because the category is explicitly on the NSArray and NSDictionary objects. // STAssertNil([fragment JSONRepresentation], nil); NSError *error = nil; STAssertNil([writer stringWithObject:fragment error:&error], @"%@", fragment); assertErrorContains(error, @"Not valid type for JSON"); } } - (void)testInfinity { NSArray *obj = [NSArray arrayWithObject:[NSNumber numberWithDouble:INFINITY]]; NSError *error = nil; STAssertNil([writer stringWithObject:obj error:&error], nil); assertUnderlyingErrorContains(error, @"Infinity is not a valid number in JSON"); } - (void)testNegativeInfinity { NSArray *obj = [NSArray arrayWithObject:[NSNumber numberWithDouble:-INFINITY]]; NSError *error = nil; STAssertNil([writer stringWithObject:obj error:&error], nil); assertUnderlyingErrorContains(error, @"Infinity is not a valid number in JSON"); } - (void)testNaN { NSArray *obj = [NSArray arrayWithObject:[NSDecimalNumber notANumber]]; NSError *error = nil; STAssertNil([writer stringWithObject:obj error:&error], nil); assertUnderlyingErrorContains(error, @"NaN is not a valid number in JSON"); } #pragma mark Scanner - (void)testArray { NSError *error; STAssertNil([parser objectWithString:@"[1,,2]" error:&error], nil); assertErrorContains(error, @"Expected value"); STAssertNil([parser objectWithString:@"[1,,]" error:&error], nil); assertErrorContains(error, @"Expected value"); STAssertNil([parser objectWithString:@"[,1]" error:&error], nil); assertErrorContains(error, @"Expected value"); STAssertNil([parser objectWithString:@"[1,]" error:&error], nil); assertErrorContains(error, @"Trailing comma disallowed"); STAssertNil([parser objectWithString:@"[1" error:&error], nil); assertErrorContains(error, @"End of input while parsing array"); STAssertNil([parser objectWithString:@"[[]" error:&error], nil); assertErrorContains(error, @"End of input while parsing array"); // See if seemingly-valid arrays have nasty elements STAssertNil([parser objectWithString:@"[+1]" error:&error], nil); assertErrorContains(error, @"Expected value"); assertUnderlyingErrorContains(error, @"Leading + disallowed"); } - (void)testObject { NSError *error; STAssertNil([parser objectWithString:@"{1" error:&error], nil); assertErrorContains(error, @"Object key string expected"); STAssertNil([parser objectWithString:@"{null" error:&error], nil); assertErrorContains(error, @"Object key string expected"); STAssertNil([parser objectWithString:@"{\"a\":1,,}" error:&error], nil); assertErrorContains(error, @"Object key string expected"); STAssertNil([parser objectWithString:@"{,\"a\":1}" error:&error], nil); assertErrorContains(error, @"Object key string expected"); STAssertNil([parser objectWithString:@"{\"a\"" error:&error], nil); assertErrorContains(error, @"Expected ':'"); STAssertNil([parser objectWithString:@"{\"a\":" error:&error], nil); assertErrorContains(error, @"Object value expected"); STAssertNil([parser objectWithString:@"{\"a\":," error:&error], nil); assertErrorContains(error, @"Object value expected"); STAssertNil([parser objectWithString:@"{\"a\":1,}" error:&error], nil); assertErrorContains(error, @"Trailing comma disallowed"); STAssertNil([parser objectWithString:@"{" error:&error], nil); assertErrorContains(error, @"End of input while parsing object"); STAssertNil([parser objectWithString:@"{\"a\":{}" error:&error], nil); assertErrorContains(error, @"End of input while parsing object"); } - (void)testNumber { NSError *error; STAssertNil([parser objectWithString:@"[-" error:&error], nil); assertUnderlyingErrorContains(error, @"No digits after initial minus"); STAssertNil([parser objectWithString:@"[+1" error:&error], nil); assertUnderlyingErrorContains(error, @"Leading + disallowed in number"); STAssertNil([parser objectWithString:@"[01" error:&error], nil); assertUnderlyingErrorContains(error, @"Leading 0 disallowed in number"); STAssertNil([parser objectWithString:@"[0." error:&error], nil); assertUnderlyingErrorContains(error, @"No digits after decimal point"); STAssertNil([parser objectWithString:@"[1e" error:&error], nil); assertUnderlyingErrorContains(error, @"No digits after exponent"); STAssertNil([parser objectWithString:@"[1e-" error:&error], nil); assertUnderlyingErrorContains(error, @"No digits after exponent"); STAssertNil([parser objectWithString:@"[1e+" error:&error], nil); assertUnderlyingErrorContains(error, @"No digits after exponent"); } - (void)testNull { NSError *error; STAssertNil([parser objectWithString:@"[nil" error:&error], nil); assertUnderlyingErrorContains(error, @"Expected 'null'"); } - (void)testBool { NSError *error; STAssertNil([parser objectWithString:@"[truth" error:&error], nil); assertUnderlyingErrorContains(error, @"Expected 'true'"); STAssertNil([parser objectWithString:@"[fake" error:&error], nil); assertUnderlyingErrorContains(error, @"Expected 'false'"); } - (void)testString { NSError *error; STAssertNil([parser objectWithString:@"" error:&error], nil); assertErrorContains(error, @"Unexpected end of string"); STAssertNil([parser objectWithString:@"" error:&error], nil); assertErrorContains(error, @"Unexpected end of string"); STAssertNil([parser objectWithString:@"[\"" error:&error], nil); assertUnderlyingErrorContains(error, @"Unescaped control character"); STAssertNil([parser objectWithString:@"[\"foo" error:&error], nil); assertUnderlyingErrorContains(error, @"Unescaped control character"); STAssertNil([parser objectWithString:@"[\"\\uD834foo\"" error:&error], nil); assertUnderlyingErrorContains(error, @"Broken unicode character"); assertUnderlyingErrorContains2(error, @"Missing low character"); STAssertNil([parser objectWithString:@"[\"\\uD834\\u001E\"" error:&error], nil); assertUnderlyingErrorContains(error, @"Broken unicode character"); assertUnderlyingErrorContains2(error, @"Invalid low surrogate"); STAssertNil([parser objectWithString:@"[\"\\uDD1Ef\"" error:&error], nil); assertUnderlyingErrorContains(error, @"Broken unicode character"); assertUnderlyingErrorContains2(error, @"Invalid high character"); for (NSUInteger i = 0; i < 0x20; i++) { NSString *str = [NSString stringWithFormat:@"\"[%C\"", i]; STAssertNil([parser objectWithString:str error:&error], nil); assertErrorContains(error, @"Unescaped control character"); } } - (void)testObjectGarbage { NSError *error; STAssertNil([parser objectWithString:@"['1'" error:&error], nil); assertUnderlyingErrorContains(error, @"Unrecognised leading character"); STAssertNil([parser objectWithString:@"['hello'" error:&error], nil); assertUnderlyingErrorContains(error, @"Unrecognised leading character"); STAssertNil([parser objectWithString:@"[**" error:&error], nil); assertUnderlyingErrorContains(error, @"Unrecognised leading character"); STAssertNil([parser objectWithString:nil error:&error], nil); assertErrorContains(error, @"Input was 'nil'"); } @end SOPE/sope-json/SBJson/Tests/WriterTest.h0000644000000000000000000000305015004363604016763 0ustar rootroot/* Copyright (C) 2010 Stig Brautaset. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ #import "AbstractTest.h" @interface WriterTest : AbstractTest @end SOPE/sope-json/SBJson/Tests/Data/0000755000000000000000000000000015004363604015351 5ustar rootrootSOPE/sope-json/SBJson/Tests/Data/string-unicode.json0000644000000000000000000000033315004363604021175 0ustar rootroot{ "\u00e9\u2265": "e-acute and greater-than-or-equal-to", "42\u00e942\u226542": "e-acute and greater-than-or-equal-to, and 42", "\u00E9": "e-acute with upper-case hex", "\uD834\uDD1E": "G-clef (UTF16 surrogate pair)" } SOPE/sope-json/SBJson/Tests/Data/string-ctrl.json.pretty0000644000000000000000000000063615004363604022047 0ustar rootroot[ "\b", "\t", "\n", "\f", "\r", "\u0000", "\u0001", "\u0002", "\u0003", "\u0004", "\u0005", "\u0006", "\u0007", "\b", "\t", "\n", "\u000b", "\f", "\r", "\u000e", "\u000f", "\u0010", "\u0011", "\u0012", "\u0013", "\u0014", "\u0015", "\u0016", "\u0017", "\u0018", "\u0019", "\u001a", "\u001b", "\u001c", "\u001d", "\u001e", "\u001f", " " ] SOPE/sope-json/SBJson/Tests/Data/number.json.pretty0000644000000000000000000000023215004363604021057 0ustar rootroot[ -333, -333000, -4, -5, -9999, 0.0001, 0, 10000, 1, 2.5, 4, 50, 66.6, 98877665544332211009988776655443322110, 99.99, 5 ] SOPE/sope-json/SBJson/Tests/Data/string-ctrl.json.terse0000644000000000000000000000045315004363604021637 0ustar rootroot["\b","\t","\n","\f","\r","\u0000","\u0001","\u0002","\u0003","\u0004","\u0005","\u0006","\u0007","\b","\t","\n","\u000b","\f","\r","\u000e","\u000f","\u0010","\u0011","\u0012","\u0013","\u0014","\u0015","\u0016","\u0017","\u0018","\u0019","\u001a","\u001b","\u001c","\u001d","\u001e","\u001f"," "] SOPE/sope-json/SBJson/Tests/Data/string.json.terse0000644000000000000000000000030715004363604020673 0ustar rootroot[""," spaces ","/","\\ \" \\ \"","foo\"","foo\"\"","foo\"\"bar","foo\"bar","foo\\","foo\\\\bar","foo\\bar","foobar","with internal spaces","/unescaped/slashes","/escaped/slashes","\\/test\\/path"] SOPE/sope-json/SBJson/Tests/Data/null.json0000644000000000000000000000001315004363604017210 0ustar rootroot[null,null]SOPE/sope-json/SBJson/Tests/Data/format.json0000644000000000000000000000006715004363604017537 0ustar rootroot["one",2,{"foo":null,"quux":true,"bar":[1, 2, []]},{}] SOPE/sope-json/SBJson/Tests/Data/null.json.pretty0000644000000000000000000000002315004363604020537 0ustar rootroot[ null, null ] SOPE/sope-json/SBJson/Tests/Data/array.json0000644000000000000000000000007215004363604017361 0ustar rootroot[ [], ["foo"], ["foo",["bar"]], ["foo",["bar",["quux"]]] ]SOPE/sope-json/SBJson/Tests/Data/bool.json.pretty0000644000000000000000000000002415004363604020521 0ustar rootroot[ true, false ] SOPE/sope-json/SBJson/Tests/Data/string-unicode.json.terse0000644000000000000000000000026715004363604022324 0ustar rootroot{"42é42≥42":"e-acute and greater-than-or-equal-to, and 42","é":"e-acute with upper-case hex","é≥":"e-acute and greater-than-or-equal-to","턞":"G-clef (UTF16 surrogate pair)"} SOPE/sope-json/SBJson/Tests/Data/number.json.terse0000644000000000000000000000015115004363604020652 0ustar rootroot[-333,-333000,-4,-5,-9999,0.0001,0,10000,1,2.5,4,50,66.6,98877665544332211009988776655443322110,99.99,5] SOPE/sope-json/SBJson/Tests/Data/null.json.terse0000644000000000000000000000001415004363604020332 0ustar rootroot[null,null] SOPE/sope-json/SBJson/Tests/Data/array.json.terse0000644000000000000000000000006615004363604020505 0ustar rootroot[[],["foo"],["foo",["bar"]],["foo",["bar",["quux"]]]] SOPE/sope-json/SBJson/Tests/Data/jsonchecker/0000755000000000000000000000000015004363604017647 5ustar rootrootSOPE/sope-json/SBJson/Tests/Data/jsonchecker/fail16.json0000644000000000000000000000001015004363604021613 0ustar rootroot[\naked]SOPE/sope-json/SBJson/Tests/Data/jsonchecker/pass3.json.pretty0000644000000000000000000000021315004363604023115 0ustar rootroot{ "JSON Test Pattern pass3" : { "In this test" : "It is an object.", "The outermost value" : "must be an object or array." } } SOPE/sope-json/SBJson/Tests/Data/jsonchecker/fail4.json0000644000000000000000000000002015004363604021531 0ustar rootroot["extra comma",]SOPE/sope-json/SBJson/Tests/Data/jsonchecker/pass2.json.pretty0000644000000000000000000000145515004363604023125 0ustar rootroot[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ "Not too deep" ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] SOPE/sope-json/SBJson/Tests/Data/jsonchecker/pass1.json.pretty0000644000000000000000000000267115004363604023125 0ustar rootroot[ "JSON Test Pattern pass1", { "object with 1 member" : [ "array with 1 element" ] }, {}, [], -42, true, false, null, { "" : 23456789012000000000000000000000000000000000000000000000000000000000000000000, " s p a c e d " : [ 1, 2, 3, 4, 5, 6, 7 ], "# -- --> */" : " ", "/\\\"쫾몾ꮘﳞ볚\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" : "A key can be any string", "0123456789" : "digit", "ALPHA" : "ABCDEFGHIJKLMNOPQRSTUVWYZ", "E" : 12345678900000000000000000000000000, "address" : "50 St. James Street", "alpha" : "abcdefghijklmnopqrstuvwyz", "array" : [], "backslash" : "\\", "comment" : "// /* */": " ", " s p a c e d " :[1,2 , 3 , 4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7], "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", "quotes": "" \u0022 %22 0x22 034 "", "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" : "A key can be any string" }, 0.5 ,98.6 , 99.44 , 1066, 1e1, 0.1e1, 1e-1, 1e00,2e+00,2e-00 ,"rosebud"]SOPE/sope-json/SBJson/Tests/Data/jsonchecker/fail18.json0000644000000000000000000000006215004363604021624 0ustar rootroot[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]SOPE/sope-json/SBJson/Tests/Data/jsonchecker/pass2.json.terse0000644000000000000000000000006515004363604022714 0ustar rootroot[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] SOPE/sope-json/SBJson/Tests/Data/jsonchecker/fail27.json0000644000000000000000000000001615004363604021623 0ustar rootroot["line break"]SOPE/sope-json/SBJson/Tests/Data/jsonchecker/fail22.json0000644000000000000000000000004115004363604021614 0ustar rootroot["Colon instead of comma": false]SOPE/sope-json/SBJson/Tests/Data/jsonchecker/fail3.json0000644000000000000000000000004515004363604021537 0ustar rootroot{unquoted_key: "keys must be quoted"}SOPE/sope-json/SBJson/Tests/Data/jsonchecker/fail19.json0000644000000000000000000000002615004363604021625 0ustar rootroot{"Missing colon" null}SOPE/sope-json/SBJson/Tests/Data/jsonchecker/pass1.json.terse0000644000000000000000000000202715004363604022713 0ustar rootroot["JSON Test Pattern pass1",{"object with 1 member":["array with 1 element"]},{},[],-42,true,false,null,{"":23456789012000000000000000000000000000000000000000000000000000000000000000000," s p a c e d ":[1,2,3,4,5,6,7],"# -- --> */":" ","/\\\"쫾몾ꮘﳞ볚\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?":"A key can be any string","0123456789":"digit","ALPHA":"ABCDEFGHIJKLMNOPQRSTUVWYZ","E":12345678900000000000000000000000000,"address":"50 St. James Street","alpha":"abcdefghijklmnopqrstuvwyz","array":[],"backslash":"\\","comment":"// /* ignore*/ pos += 2; continue; } /* process binding */ startPos = pos; pos += 2; /* wbuf[pos + 1] != '$' */ while (pos < len) { if (wbuf[pos] != '$') pos++; else break; } if (pos == len) { /* end of string was reached */ [[NSException exceptionWithName: @"NSStringVariableBindingException" reason:[NSString stringWithFormat: @"did not find end of variable for string %@", self] userInfo:nil] raise]; } else { NSString *key = nil; key = [[NSString alloc] initWithCharacters:(unichar *)wbuf + startPos + 1 length:(pos - startPos - 1)]; [result addObject:key]; [key release]; } pos++; } if (wbuf != NULL) { free(wbuf); wbuf = NULL; } return [[result copy] autorelease]; } - (NSString *)stringByReplacingVariablesWithBindings:(id)_bindings stringForUnknownBindings:(NSString *)_unknown { unsigned len, pos = 0; unichar *wbuf = NULL; NSMutableString *str = nil; str = [self mutableCopy]; len = [str length]; wbuf = malloc(sizeof(unichar) * (len + 4)); [self getCharacters:wbuf]; while (pos < len) { if (pos + 1 == len) { /* last entry */ if (wbuf[pos] == '$') { /* found $ without end-char */ [[NSException exceptionWithName: @"NSStringVariableBindingException" reason:[NSString stringWithFormat: @"did not find end of variable for string %@", self] userInfo:nil] raise]; } break; } if (wbuf[pos] == '$') { if (wbuf[pos + 1] == '$') { /* found $$ --> $ */ [str deleteCharactersInRange:NSMakeRange(pos, 1)]; if (wbuf != NULL) { free(wbuf); wbuf = NULL; } len = [str length]; wbuf = malloc(sizeof(unichar) * (len + 4)); [str getCharacters:wbuf]; } else { unsigned startPos = pos; pos += 2; /* wbuf[pos + 1] != '$' */ while (pos < len) { if (wbuf[pos] != '$') pos++; else break; } if (pos == len) { /* end of string was reached */ [[NSException exceptionWithName: @"NSStringVariableBindingException" reason:[NSString stringWithFormat: @"did not find end of variable for string %@", self] userInfo:nil] raise]; } else { NSString *key; NSString *value; key = [[NSString alloc] initWithCharacters:(wbuf + startPos + 1) length:(pos - startPos - 1)]; if ((value = [_bindings valueForStringBinding:key]) == nil) { if (_unknown == nil) { [[NSException exceptionWithName: @"NSStringVariableBindingException" reason:[NSString stringWithFormat: @"did not find binding for " @"name %@ in binding-dictionary %@", [key autorelease], _bindings] userInfo:nil] raise]; } else value = _unknown; } [key release]; key = nil; [str replaceCharactersInRange: NSMakeRange(startPos, pos - startPos + 1) withString:value]; if (wbuf != NULL) { free(wbuf); wbuf = NULL; } len = [str length]; wbuf = malloc(sizeof(unichar) * (len + 4)); [str getCharacters:wbuf]; pos = startPos - 1 + [value length]; } } } pos++; } if (wbuf != NULL) { free(wbuf); wbuf = NULL; } { id tmp = str; str = [str copy]; [tmp release]; tmp = nil; } return [str autorelease]; } - (NSString *)stringByReplacingVariablesWithBindings:(id)_bindings { return [self stringByReplacingVariablesWithBindings:_bindings stringForUnknownBindings:nil]; } @end /* NSString(misc) */ @implementation NSString(FilePathVersioningMethods) /* "/path/file.txt;1" */ - (NSString *)pathVersion { NSRange r; r = [self rangeOfString:@";"]; if (r.length > 0) { return ([self length] > r.location) ? [self substringFromIndex:(r.location + r.length)] : (NSString *)@""; } return nil; } - (NSString *)stringByDeletingPathVersion { NSRange r; r = [self rangeOfString:@";"]; return (r.length > 0) ? [self substringToIndex:r.location] : self; } - (NSString *)stringByAppendingPathVersion:(NSString *)_version { return [[self stringByAppendingString:@";"] stringByAppendingString:_version]; } @end /* NSString(FilePathMethodsVersioning) */ @implementation NSString(NGScanning) - (NSRange)rangeOfString:(NSString *)_s skipQuotes:(NSString *)_quotes escapedByChar:(unichar)_escape { // TODO: speed ... // TODO: check correctness with invalid input ! static NSRange notFound = { 0, 0 }; NSCharacterSet *quotes; unsigned i, len, slen; unichar sc; if ((slen = [_s length]) == 0) return notFound; if ((len = [self length]) < slen) /* to short */ return notFound; if ([_quotes length] == 0) _quotes = @"'\""; quotes = [NSCharacterSet characterSetWithCharactersInString:_quotes]; sc = [_s characterAtIndex:0]; for (i = 0; i < len; i++) { unichar c; c = [self characterAtIndex:i]; if (c == sc) { /* start search section */ if (slen == 1) return NSMakeRange(i, 1); if ([[self substringFromIndex:i] hasPrefix:_s]) return NSMakeRange(i, slen); } else if ([quotes characterIsMember:c]) { /* skip quotes */ i++; c = [self characterAtIndex:i]; for (; i < len && ![quotes characterIsMember:c]; i++) { c = [self characterAtIndex:i]; if (c == _escape) { i++; /* skip next char (eg \') */ continue; } } } } return notFound; } - (NSRange)rangeOfString:(NSString *)_s skipQuotes:(NSString *)_quotes { return [self rangeOfString:_s skipQuotes:_quotes escapedByChar:'\\']; } @end /* NSString(NGScanning) */ @implementation NSString(MailQuoting) - (NSString *)stringByApplyingMailQuoting { NSString *s; unsigned i, len, nl; unichar *sourceBuf, *targetBuf; if ((len = [self length]) == 0) return @""; sourceBuf = malloc((len + 4) * sizeof(unichar)); [self getCharacters:sourceBuf]; for (nl = 0, i = 0; i < len; i++) { if (sourceBuf[i] == '\n') nl++; } if (nl == 0) { if (sourceBuf) free(sourceBuf); return [@"> " stringByAppendingString:self]; } targetBuf = malloc((len + 8 + (nl * 3)) * sizeof(unichar)); targetBuf[0] = '>'; targetBuf[1] = ' '; nl = 2; for (i = 0; i < len; i++) { targetBuf[nl] = sourceBuf[i]; nl++; if (sourceBuf[i] == '\n' && (i + 1 != len)) { targetBuf[nl] = '>'; nl++; targetBuf[nl] = ' '; nl++; } } s = [[NSString alloc] initWithCharacters:targetBuf length:nl]; if (targetBuf) free(targetBuf); if (sourceBuf) free(sourceBuf); return [s autorelease]; } @end /* NSString(MailQuoting) */ @implementation NSString(HeaderCapitalization) - (NSString *) asCapitalizedHeader { NSString *result; NSUInteger count, max; unichar *chars; BOOL capitalize = YES; max = [self length]; if (max == 3 && [[self lowercaseString] isEqualToString: @"dav"]) result = @"DAV"; else { chars = malloc (max * sizeof (unichar)); [self getCharacters: chars]; for (count = 0; count < max; count++) { if (capitalize) { if (chars[count] >= 97 && chars[count] <= 122) chars[count] -= 32; capitalize = NO; } else if (chars[count] == '-') capitalize = YES; } result = [NSString stringWithCharacters: chars length: max]; free (chars); } return result; } @end // linking void __link_NSString_misc(void) { __link_NSString_misc(); } SOPE/sope-core/NGExtensions/FdExt.subproj/NSURL+misc.m0000644000000000000000000003024215004363604021311 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSURL+misc.h" #include "common.h" static BOOL debugURLProcessing = NO; @implementation NSURL(misc) - (NSString *)pathWithCorrectTrailingSlash { #if COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY /* At least on OSX 10.3 the -path method missing the trailing slash, eg: http://localhost:20000/dbd.woa/so/localhost/ gives: /dbd.woa/so/localhost */ NSString *p; if ((p = [self path]) == nil) return nil; if ([p hasSuffix:@"/"]) return p; if (![[self absoluteString] hasSuffix:@"/"]) return p; /* so we are running into the bug ... */ return [p stringByAppendingString:@"/"]; #else return [self path]; #endif } - (NSString *)stringByAddingFragmentAndQueryToPath:(NSString *)_path { NSString *lFrag, *lQuery; if ([self isFileURL]) return _path; lFrag = [self fragment]; lQuery = [self query]; if ((lFrag != nil) || (lQuery != nil)) { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:([_path length] + 32)]; [ms appendString:_path]; if (lFrag) { [ms appendString:@"#"]; [ms appendString:lFrag]; } if (lQuery) { [ms appendString:@"?"]; [ms appendString:lQuery]; } return ms; } else return _path; } - (NSString *)stringValueRelativeToURL:(NSURL *)_base { /* Sample: self: http://localhost:20000/dbd.woa/so/localhost/Databases/A base: http://localhost:20000/dbd.woa/so/localhost/ => Databases/A Note: on Panther Foundation the -path misses the trailing slash! */ NSString *relPath; if (_base == self || _base == nil) { relPath = [self pathWithCorrectTrailingSlash]; relPath = [relPath urlPathRelativeToSelf]; relPath = [self stringByAddingFragmentAndQueryToPath:relPath]; if (debugURLProcessing) { NSLog(@"%s: no base or base is self => '%@'", __PRETTY_FUNCTION__, relPath); } return relPath; } /* check whether we are already marked relative to _base .. */ if ([self baseURL] == _base) { NSString *p; p = [self relativePath]; #if COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY /* see -pathWithCorrectTrailingSlash for bug description ... */ if (![p hasSuffix:@"/"]) { if ([[self absoluteString] hasSuffix:@"/"]) p = [p stringByAppendingString:@"/"]; } #endif p = [self stringByAddingFragmentAndQueryToPath:p]; if (debugURLProcessing) { NSLog(@"%s: url base and _base match => '%@'", __PRETTY_FUNCTION__, p); } return p; } /* check whether we are in the same path namespace ... */ if (![self isInSameNamespaceWithURL:_base]) { /* need to return full URL */ relPath = [self absoluteString]; if (debugURLProcessing) { NSLog(@"%s: url is in different namespace from base => '%@'", __PRETTY_FUNCTION__, relPath); } return relPath; } relPath = [[self pathWithCorrectTrailingSlash] urlPathRelativeToPath:[_base pathWithCorrectTrailingSlash]]; if (debugURLProcessing) { NSLog(@"%s: path '%@', base-path '%@' => rel '%@'", __PRETTY_FUNCTION__, [self path], [_base path], relPath); } relPath = [self stringByAddingFragmentAndQueryToPath:relPath]; if (debugURLProcessing) { NSLog(@"%s: same namespace, but no direct relative (%@, base %@) => '%@'", __PRETTY_FUNCTION__, [self absoluteString], [_base absoluteString], relPath); } return relPath; } static BOOL isEqual(id o1, id o2) { if (o1 == o2) return YES; if (o1 == nil || o2 == nil) return NO; return [o1 isEqual:o2]; } - (BOOL)isInSameNamespaceWithURL:(NSURL *)_url { if (_url == nil) return NO; if (_url == self) return YES; if ([self isFileURL] && [_url isFileURL]) return YES; if ([self baseURL] == _url) return YES; if ([_url baseURL] == self) return YES; if (![[self scheme] isEqualToString:[_url scheme]]) return NO; if (!isEqual([self host], [_url host])) return NO; if (!isEqual([self port], [_url port])) return NO; if (!isEqual([self user], [_url user])) return NO; return YES; } @end /* NSURL */ @implementation NSString(URLPathProcessing) - (NSString *)urlPathRelativeToSelf { /* eg: "/a/b/c.html" should resolve to: "c.html" Directories are a bit more difficult, eg: "/a/b/c/" is resolved to "../c/" */ NSString *p; NSString *lp; /* /SOGo/so/X/Mail/Y/INBOX/withsubdirs/ ..//SOGo/so/X/Mail/Y/INBOX/withsubdirs// */ p = self; lp = [p lastPathComponent]; if (![p hasSuffix:@"/"]) return lp; return [[@"../" stringByAppendingString:lp] stringByAppendingString:@"/"]; } - (NSString *)urlPathRelativeToRoot { NSString *p; p = self; if ([p isEqualToString:@"/"]) /* don't know better ... what is root-relative-to-root ? */ return @"/"; if ([p length] == 0) { NSLog(@"%s: invalid path (length 0), using /: %@", __PRETTY_FUNCTION__, self); return @"/"; } /* this is the same like the absolute path, only without a leading "/" .. */ return [p characterAtIndex:0] == '/' ? [p substringFromIndex:1] : p; } static NSString *calcRelativePathOfChildURL(NSString *self, NSString *_base) { /* the whole base URI is prefix of our URI: case a) b: "/a/b/c" s: "/a/b/c/d" >: "c/d" case b) b: "/a/b/c/" s: "/a/b/c/d" >: "d" case c) b: "/a/b/c" s: "/a/b/ccc/d" >: "ccc/d" b=s is already catched above and s is guaranteed to be longer than b. */ unsigned blen; NSString *result; if (debugURLProcessing) NSLog(@"%s: has base as prefix ...", __PRETTY_FUNCTION__); blen = [_base length]; if ([_base characterAtIndex:(blen - 1)] == '/') { /* last char of 'b' is '/' => case b) */ result = [self substringFromIndex:blen]; } else { /* last char of 'b' is not a slash (either case a) or case c)), both are handled in the same way (search last / ...) */ NSRange r; r = [_base rangeOfString:@"/" options:NSBackwardsSearch]; if (r.length == 0) { NSLog(@"%s: invalid base, found no '/': '%@' !", __PRETTY_FUNCTION__, _base); result = self; } else { /* no we have case b) ... */ result = [self substringFromIndex:(r.location + 1)]; } } return result; } - (NSString *)commonDirPathPrefixWithString:(NSString *)_other { // TODO: the implementation can probably be optimized a _LOT_ /* eg "/home/images/" vs "/home/index.html" => "/home/", _not_ "/home/i" ! */ NSString *s; unsigned len; NSRange r; if (_other == self) return self; s = [self commonPrefixWithString:_other options:0]; len = [s length]; if (len == 0) return s; if ([s characterAtIndex:(len - 1)] == '/') return s; r = [s rangeOfString:@"/" options:NSBackwardsSearch]; if (r.length == 0) /* hm, can't happen? */ return nil; return [s substringToIndex:(r.location + r.length)];; } static NSString *calcRelativePathOfNonChildURL(NSString *self, NSString *_base) { unsigned numSlashes; NSString *result; NSString *prefix; NSString *suffix; unsigned plen; prefix = [self commonDirPathPrefixWithString:_base]; plen = [prefix length]; suffix = [self substringFromIndex:plen]; numSlashes = 0; if (debugURLProcessing) { NSLog(@"%s: does not have base as prefix, common '%@'\n" @" self='%@'\n" @" base='%@'\n" @" suffix='%@'", __PRETTY_FUNCTION__, prefix, self, _base, suffix); } if (plen == 0) { NSLog(@"%s: invalid strings, no common prefix ...: '%@' and '%@' !", __PRETTY_FUNCTION__, self, _base); return self; } if (plen == 1) { /* common prefix is root. That is, nothing in common: b: "/a/b" s: "/l" >: "../l" b: "/a/b/" s: "/l" >: "../../l" (number of slashes without root * "..", then the trailer?) */ unsigned i, len; len = [_base length]; if ([prefix characterAtIndex:0] != '/') { NSLog(@"%s: invalid strings, common prefix '%@' is not '/': " @"'%@' and '%@' !", __PRETTY_FUNCTION__, self, _base, prefix); } for (i = 1 /* skip root */; i < len; i++) { if ([_base characterAtIndex:i] == '/') numSlashes++; } } else { /* base: /dev/en/projects/bsd/index.html self: /dev/en/macosx/ => ../../macosx/ */ NSString *basesuffix; unsigned i, len; basesuffix = [_base substringFromIndex:plen]; len = [basesuffix length]; for (i = 0; i < len; i++) { if ([basesuffix characterAtIndex:i] == '/') numSlashes++; } } if (debugURLProcessing) NSLog(@"%s: slashes: %d", __PRETTY_FUNCTION__, numSlashes); /* optimization for some depths */ switch (numSlashes) { case 0: /* no slashes in base: b:/a, s:/images/a => images/a */ result = suffix; break; case 1: /* one slash in base: b:/a/, s:/images/a => ../images/a, etc */ result = [@"../" stringByAppendingString:suffix]; break; case 2: result = [@"../../" stringByAppendingString:suffix]; break; case 3: result = [@"../../../" stringByAppendingString:suffix]; break; case 4: result = [@"../../../../" stringByAppendingString:suffix]; break; case 5: result = [@"../../../../../" stringByAppendingString:suffix];break; default: { NSMutableString *ms; unsigned i; ms = [NSMutableString stringWithCapacity:(numSlashes * 3)]; for (i = 0; i < numSlashes; i++) [ms appendString:@"../"]; [ms appendString:suffix]; result = ms; break; } } if (debugURLProcessing) NSLog(@"%s: => '%@'", __PRETTY_FUNCTION__, result); return result; } - (NSString *)urlPathRelativeToPath:(NSString *)_base { /* This can be used for URLs in the same namespace. It should never return an absolute path (it only does in error conditions). */ // TODO: the implementation can probably be optimized a _LOT_ if (_base == nil || [_base length] == 0) { NSLog(@"%s: invalid base (nil or length 0), using absolute path '%@' ...", __PRETTY_FUNCTION__, self); return self; } if ([_base isEqualToString:@"/"]) return [self urlPathRelativeToRoot]; if ([_base isEqualToString:self]) return [self urlPathRelativeToSelf]; if (debugURLProcessing) NSLog(@"%s: %@ relative to %@ ...", __PRETTY_FUNCTION__, self, _base); if ([self hasPrefix:_base]) return calcRelativePathOfChildURL(self, _base); return calcRelativePathOfNonChildURL(self, _base); } @end /* NSString(URLPathProcessing) */ @implementation NSURL(QueryComponents) - (NSDictionary *) queryComponents { NSString *query = [self query]; NSArray *pairs = [query componentsSeparatedByString: @"&"]; NSMutableDictionary *components = [NSMutableDictionary dictionary]; NSEnumerator *e = [pairs objectEnumerator]; NSString *pair; while ((pair = [e nextObject]) != nil) { NSString *key, *value; NSArray *keyVal = [pair componentsSeparatedByString: @"="]; if ([keyVal count] != 2) { continue; } key = [[keyVal objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; if ([key length] == 0) { continue; } value = [[keyVal objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; [components setObject:value forKey:key]; } return components; } @end /* NSURL(QueryComponents)*/ SOPE/sope-core/NGExtensions/FdExt.subproj/GNUmakefile0000644000000000000000000000203615004363604021353 0ustar rootroot# GNUstep makefile include ../../../config.make include ../../common.make SUBPROJECT_NAME = FdExt FdExt_PCH_FILE = common.h FdExt_OBJC_FILES = \ NSArray+enumerator.m \ NSAutoreleasePool+misc.m \ NSBundle+misc.m \ NSCalendarDate+misc.m \ NSCalendarDate+matrix.m \ NSData+gzip.m \ NSData+misc.m \ NSDictionary+KVC.m \ NSDictionary+misc.m \ NSEnumerator+misc.m \ NSException+misc.m \ NSFileManager+Extensions.m \ NSNull+misc.m \ NSObject+Logs.m \ NSObject+Values.m \ NSProcessInfo+misc.m \ NSRunLoop+FileObjects.m \ NSSet+enumerator.m \ NSString+Ext.m \ NSString+Encoding.m \ NSString+Escaping.m \ NSString+Formatting.m \ NSString+misc.m \ NSString+HTMLEscaping.m \ NSString+XMLEscaping.m \ NSString+URLEscaping.m \ NSURL+misc.m \ NGPropertyListParser.m \ ADDITIONAL_INCLUDE_DIRS += -I. -I../NGExtensions/ -I.. -I../.. ifeq ($(iseries),yes) ADDITIONAL_CPPFLAGS += -DISERIES=1 endif -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/subproject.make -include GNUmakefile.postamble SOPE/sope-core/NGExtensions/FdExt.subproj/common.h0000644000000000000000000000002715004363604020740 0ustar rootroot#include "../common.h" SOPE/sope-core/NGExtensions/FdExt.subproj/NSProcessInfo+misc.m0000644000000000000000000002237615004363604023112 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSProcessInfo+misc.h" #include "common.h" #include #ifdef __linux__ #include #include #endif #if !LIB_FOUNDATION_LIBRARY && !GNUSTEP_BASE_LIBRARY # import #endif @implementation NSProcessInfo(misc) /* arguments */ - (NSArray *)argumentsWithoutDefaults { NSMutableArray *ma; NSArray *a; unsigned count, i; BOOL foundDefault; a = [self arguments]; if ((count = [a count]) == 0) return nil; if (count == 1) return a; ma = [NSMutableArray arrayWithCapacity:count]; [ma addObject:[a objectAtIndex:0]]; // tool name for (i = 1, foundDefault = NO; i < count; i++) { NSString *arg; arg = [a objectAtIndex:i]; if ([arg hasPrefix:@"-"] && ([arg length] > 1)) { /* a default .. */ i++; /* consume value */ foundDefault = YES; continue; } [ma addObject:arg]; } return foundDefault ? (NSArray *)ma : a; } /* create temp file name */ - (NSString *)temporaryFileName:(NSString *)_prefix { static int cnt = 0; NSString *s; cnt++; s = [NSString stringWithFormat: @"%04X%llX%02X.tmp", getpid(), (long long)time(NULL), cnt]; return [_prefix stringByAppendingString:s]; } - (NSString *)temporaryFileName { NSString *prefix; prefix = [@"/tmp/" stringByAppendingPathComponent:[self processName]]; return [self temporaryFileName:prefix]; } /* return process-id (pid on Unix) */ - (id)processId { int pid; #if defined(__MINGW32__) pid = (int)GetCurrentProcessId(); #else pid = (int)getpid(); #endif return [NSNumber numberWithInt:pid]; } - (NSString *)procDirectoryPathForProcess { NSString *p; BOOL isDir; p = [@"/proc/" stringByAppendingString:[[self processId] stringValue]]; if (![[NSFileManager defaultManager] fileExistsAtPath:p isDirectory:&isDir]) return nil; return isDir ? p : (NSString *)nil; } - (NSDictionary *)procStatusDictionary { NSMutableDictionary *dict; NSString *procStatusPath; NSString *s; NSEnumerator *lines; NSString *line; procStatusPath = [[self procDirectoryPathForProcess] stringByAppendingPathComponent:@"status"]; s = [[NSString alloc] initWithContentsOfFile:procStatusPath]; if (s == nil) return nil; dict = [NSMutableDictionary dictionaryWithCapacity:32]; lines = [[s componentsSeparatedByString:@"\n"] objectEnumerator]; while ((line = [lines nextObject])) { NSString *key; NSRange r; id value; r = [line rangeOfString:@":"]; if (r.length == 0) continue; key = [line substringToIndex:r.location]; value = [[line substringFromIndex:(r.location + r.length)] stringByTrimmingSpaces]; if (value == nil) value = [NSNull null]; [dict setObject:value forKey:key]; } return [[dict copy] autorelease]; } static NSNumber *_int(int i) __attribute__((unused)); static NSNumber *_uint(unsigned int i) __attribute__((unused)); static NSNumber *_int(int i) { return [NSNumber numberWithInt:i]; } static NSNumber *_uint(unsigned int i) { return [NSNumber numberWithUnsignedInt:i]; } #define NG_GET_PROC_INFO \ FILE *fh;\ char pp[256];\ int res;\ int pid, ppid, pgrp, session, tty, tpgid;\ unsigned int flags, minflt, cminflt, majflt, cmajflt;\ int utime, stime, cutime, cstime, counter;\ unsigned char comm[256];\ char state = 0;\ int priority, starttime;\ unsigned int timeout, itrealvalue, rlim, startcode, endcode;\ unsigned long long rss, vsize;\ unsigned int startstack, kstkesp, kstkeip;\ int signal, blocked, sigignore, sigcatch;\ unsigned int wchan;\ \ pid = getpid();\ snprintf(pp, 255, "/proc/%i/stat", pid);\ fh = fopen(pp, "r");\ if (fh == NULL)\ res = -1;\ else {\ res = fscanf(fh,\ "%d %255s %c %d %d %d %d %d "\ "%u %u %u %u %u "\ "%d %d %d %d %d "\ "%d %u %u %d "\ "%llu %llu %u %u %u"\ "%u %u %u "\ "%d %d %d %d "\ "%u"\ ,\ &pid, &(comm[0]), &state, &ppid, &pgrp, &session, &tty, \ &tpgid,\ &flags, &minflt, &cminflt, &majflt, &cmajflt,\ &utime, &stime, &cutime, &cstime, &counter,\ &priority, &timeout, &itrealvalue, &starttime,\ &vsize, &rss, &rlim, &startcode, &endcode,\ &startstack, &kstkesp, &kstkeip,\ &signal, &blocked, &sigignore, &sigcatch,\ &wchan\ );\ fclose(fh); fh = NULL;\ } - (unsigned long long)virtualMemorySize { #ifdef __linux__ NG_GET_PROC_INFO; return vsize; #else return 0; #endif } - (unsigned long long)residentSetSize { #ifdef __linux__ NG_GET_PROC_INFO; return rss; #else return 0; #endif } - (unsigned int)residentSetSizeLimit { #ifdef __linux__ NG_GET_PROC_INFO; return rlim; #else return 0; #endif } - (unsigned int)fileDescriptorCount { #ifdef __linux__ int fd_count; char buf[64]; struct dirent *dp; DIR *dir; snprintf(buf, 64, "/proc/%i/fd/", getpid()); fd_count = 0; dir = opendir(buf); while ((dp = readdir(dir)) != NULL) { fd_count++; } closedir(dir); return fd_count; #else return 0; #endif } - (NSDictionary *)procStatDictionary { #ifdef __linux__ /* see 'man 5 proc' */ NSMutableDictionary *dict; NG_GET_PROC_INFO; if (res > 0) { dict = [NSMutableDictionary dictionaryWithCapacity:res]; if (res > 0) [dict setObject:_int(pid) forKey:@"pid"]; if (res > 1) [dict setObject:[NSString stringWithCString:(char *)comm] forKey:@"comm"]; if (res > 2) [dict setObject:[NSString stringWithCString:&state length:1] forKey:@"state"]; if (res > 3) [dict setObject:_int(ppid) forKey:@"ppid"]; if (res > 4) [dict setObject:_int(pgrp) forKey:@"pgrp"]; if (res > 5) [dict setObject:_int(session) forKey:@"session"]; if (res > 6) [dict setObject:_int(tty) forKey:@"tty"]; if (res > 7) [dict setObject:_int(tpgid) forKey:@"tpgid"]; if (res > 8) [dict setObject:_uint(flags) forKey:@"flags"]; if (res > 9) [dict setObject:_uint(minflt) forKey:@"minflt"]; if (res > 10) [dict setObject:_uint(cminflt) forKey:@"cminflt"]; if (res > 11) [dict setObject:_uint(majflt) forKey:@"majflt"]; if (res > 12) [dict setObject:_uint(cmajflt) forKey:@"cmajflt"]; if (res > 13) [dict setObject:_int(utime) forKey:@"utime"]; if (res > 14) [dict setObject:_int(stime) forKey:@"stime"]; if (res > 15) [dict setObject:_int(cutime) forKey:@"cutime"]; if (res > 16) [dict setObject:_int(cstime) forKey:@"cstime"]; if (res > 17) [dict setObject:_int(counter) forKey:@"counter"]; if (res > 18) [dict setObject:_int(priority) forKey:@"priority"]; if (res > 19) [dict setObject:_uint(timeout) forKey:@"timeout"]; if (res > 20) [dict setObject:_uint(itrealvalue) forKey:@"itrealvalue"]; if (res > 21) [dict setObject:_int(starttime) forKey:@"starttime"]; if (res > 22) [dict setObject:_uint(vsize) forKey:@"vsize"]; if (res > 23) [dict setObject:_uint(rss) forKey:@"rss"]; if (res > 24) [dict setObject:_uint(rlim) forKey:@"rlim"]; if (res > 25) [dict setObject:_uint(startcode) forKey:@"startcode"]; if (res > 26) [dict setObject:_uint(endcode) forKey:@"endcode"]; if (res > 27) [dict setObject:_uint(startstack) forKey:@"startstack"]; if (res > 28) [dict setObject:_uint(kstkesp) forKey:@"kstkesp"]; if (res > 29) [dict setObject:_uint(kstkeip) forKey:@"kstkeip"]; if (res > 30) [dict setObject:_int(signal) forKey:@"signal"]; if (res > 31) [dict setObject:_int(blocked) forKey:@"blocked"]; if (res > 32) [dict setObject:_int(sigignore) forKey:@"sigignore"]; if (res > 33) [dict setObject:_int(sigcatch) forKey:@"sigcatch"]; if (res > 34) [dict setObject:_uint(wchan) forKey:@"wchan"]; return dict; } else { NSLog(@"%s: couldn't scan /proc-info ...", __PRETTY_FUNCTION__); dict = nil; } return [[dict copy] autorelease]; #else return nil; #endif } @end /* NSProcessInfo(misc) */ // linking void __link_NSProcessInfo_misc(void) { __link_NSProcessInfo_misc(); } SOPE/sope-core/NGExtensions/FdExt.subproj/NSAutoreleasePool+misc.m0000644000000000000000000000760415004363604023760 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "NSAutoreleasePool+misc.h" #if defined(LIB_FOUNDATION_LIBRARY) BOOL __autoreleaseEnableRetainRemove = NO; #if !LIB_FOUNDATION_BOEHM_GC @implementation NSAutoreleasePool(misc) // retain/remove check + (void)enableRetainRemove:(BOOL)enable { __autoreleaseEnableRetainRemove = enable; } + (NSAutoreleasePool *)findReleasingPoolForObject:(id)_obj { NSAutoreleasePool *pool = nil; for (pool = [self defaultPool]; pool; pool = pool->parentPool) { NSAutoreleasePoolChunk *ch; int i; for (ch = pool->firstChunk; ch; ch = ch->next) { for (i = 0; i < ch->used; i++) { if (ch->objects[i] == _obj) return pool; } } //if ([pool doesReleaseObject:_obj]) // return pool; } return nil; } + (BOOL)retainAutoreleasedObject:(id)_obj { register NSAutoreleasePool *pool = nil; for (pool = [self defaultPool]; pool; pool = pool->parentPool) { register NSAutoreleasePoolChunk *ch; register int i; for (ch = pool->firstChunk; ch; ch = ch->next) { for (i = 0; i < ch->used; i++) { if (ch->objects[i] == _obj) { ch->objects[i] = nil; return YES; } } } //if ([pool doesReleaseObject:_obj]) // return pool; } return NO; } - (BOOL)retainAutoreleasedObject:(id)_obj { NSAutoreleasePoolChunk *ch; int i; for (ch = firstChunk; ch; ch = ch->next) { for (i = 0; i < ch->used; i++) { if (ch->objects[i] == _obj) { ch->objects[i] = nil; return YES; } } } return NO; } @end @implementation NSObject(RC) - (oneway void)release { #if BUILD_libFoundation_DLL && defined(__WIN32__) extern __declspec(dllimport) BOOL __autoreleaseEnableCheck; #else extern BOOL __autoreleaseEnableCheck; #endif // check if retainCount is Ok if (__autoreleaseEnableCheck) { unsigned int toCome = [NSAutoreleasePool autoreleaseCountForObject:self]; if (toCome + 1 > [self retainCount]) { NSLog(@"Release[0x%p<%@>] release check for object %@ " @"has %d references " @"and %d pending calls to release in autorelease pools\n", self, NSStringFromClass([self class]), self, [self retainCount], toCome); NSLog(@" description='%@'", [self description]); abort(); // core dump for debugging return; } } if (NSExtraRefCount(self) == 1) [self dealloc]; else NSDecrementExtraRefCountWasZero(self); } - (id)retain { extern BOOL __autoreleaseEnableRetainRemove; if (__autoreleaseEnableRetainRemove) { if ([NSAutoreleasePool retainAutoreleasedObject:self]) { NSLog(@"retained autoreleased object .."); return self; } } NSIncrementExtraRefCount(self); return self; } @end #endif // !LIB_FOUNDATION_BOEHM_GC #endif // defined(LIB_FOUNDATION_LIBRARY) void __link_NSAutoreleasePool_misc(void) { __link_NSAutoreleasePool_misc(); } SOPE/sope-core/NGExtensions/FdExt.subproj/NSString+Formatting.m0000644000000000000000000004445215004363604023304 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #include "NSString+Formatting.h" #include "NGMemoryAllocation.h" #if 0 #if !ISERIES # ifndef USE_VA_LIST_PTR # define USE_VA_LIST_PTR 1 # endif #else # define USE_VA_LIST_PTR 0 #endif // format // %|[justification]|[fieldwidth]|[precision]|formatChar // %[-]{digit}*[.{digit}*]conv static const char *formatChars = "diouxX" // integers "feEgG" // double "c" // int arg -> uchar "s" // string "@" // object "$" // string object ; static const char *formatAttrs = "#0- +,"; static const char *formatConv = "hlLqZ"; static Class StrClass = Nil; typedef enum { DEFAULT_TYPE = 0, SHORT_TYPE, LONG_TYPE, VERY_LONG_TYPE } NGFormatType; // implementation static inline NSString * wideString(const char *str, int width, char fillChar, BOOL isRightAligned) { unsigned char *tmp; register int cnt; int len; if (StrClass == Nil) StrClass = [NSString class]; if (width <= 0) return str ? [StrClass stringWithCString:str] : nil; if ((len = strlen(str)) >= width) return str ? [StrClass stringWithCString:str] : nil; tmp = malloc(width + 2); if (isRightAligned) { // right aligned for (cnt = 0; cnt < (width - len); cnt++) tmp[cnt] = fillChar; strncpy(tmp + (width - len), str, len); tmp[width] = '\0'; } else { // left aligned for (cnt = len; cnt < width; cnt++) tmp[cnt] = fillChar; strncpy(tmp, str, len); tmp[cnt] = '\0'; } return [[[StrClass alloc] initWithCStringNoCopy:tmp length:strlen(tmp) freeWhenDone:YES] autorelease]; } static inline NSString *xsSimpleFormatObject(char *fmt, id _value, NSString *_ds) { /* formats an object value in an simple format (this is only the '%{mods}{type}' part of a real format string !) The method to get the value of the object is determined by the {type} of the Format, eg: i becomes intValue, @ becomes description .. the decimal point in float-strings can be replaced by the _ds String. To do this, the result of the Format is scanned for '.' and _ds is expanded for this. */ int fmtLen = strlen(fmt); char fmtChar = fmt[fmtLen - 1]; NGFormatType typeMode = DEFAULT_TYPE; int width = -1; int prec = -1; BOOL alignRight = YES; char *pos = fmt + 1; char *tmp; if (StrClass == Nil) StrClass = [NSString class]; while (index(formatAttrs, *pos)) { if (*pos == '-') alignRight = NO; pos++; } /* width */ tmp = pos; while (isdigit((int)*pos)) pos++; if (tmp != pos) { char old = *pos; *pos = '\0'; width = atoi(tmp); *pos = old; } /* prec */ if (*pos == '.') { pos++; tmp = pos; while (isdigit((int)*pos)) pos++; if (tmp != pos) { char old = *pos; *pos = '\0'; prec = atoi(tmp); *pos = old; } } /* conversion */ if (index(formatConv, *pos)) { switch (*pos) { case 'h': typeMode = SHORT_TYPE; pos++; break; case 'l': typeMode = LONG_TYPE; pos++; if (*pos == 'l') { // long-long typeMode = VERY_LONG_TYPE; pos++; } break; case 'L': case 'q': typeMode = VERY_LONG_TYPE; pos++; break; } } if (index("diouxX", fmtChar)) { char buf[128]; int len = -1; switch (typeMode) { case SHORT_TYPE: { unsigned short int i = [(NSNumber *)_value unsignedShortValue]; len = sprintf(buf, fmt, i); break; } case LONG_TYPE: { unsigned long int i = [(NSNumber *)_value unsignedLongValue]; len = sprintf(buf, fmt, i); break; } case VERY_LONG_TYPE: { long long i = [(NSNumber *)_value unsignedLongLongValue]; len = sprintf(buf, fmt, i); break; } default: { unsigned int i = [(NSNumber *)_value unsignedIntValue]; len = sprintf(buf, fmt, i); break; } } return (len >= 0) ? [StrClass stringWithCString:buf length:len] : nil; } if (fmtChar == 'c') { char buf[64]; int i = [(NSNumber *)_value unsignedCharValue]; int len; len = sprintf(buf, fmt, (unsigned char)i); return (len > 0) ? [StrClass stringWithCString:buf length:len] : nil; } if (fmtChar == 'C') { // TODO: implement correctly /* 16bit unichar value */ char buf[64]; int i, len; /* TODO: evil hack */ fmt[fmtLen - 1] = 'c'; i = [(NSNumber *)_value unsignedCharValue]; len = sprintf(buf, fmt, (unsigned char)i); return (len > 0) ? [StrClass stringWithCString:buf length:len] : nil; } if (index("feEgG", fmtChar)) { unsigned char buf[256]; unsigned len; if (typeMode == VERY_LONG_TYPE) { long double i = [(NSNumber *)_value doubleValue]; len = sprintf(buf, fmt, i); } else { double i = [(NSNumber *)_value doubleValue]; len = sprintf(buf, fmt, i); } if (len >= 0) { NSMutableString *result; unsigned int cnt; char *ptr = buf; unsigned int bufCount = 0; if (_ds == nil) return [StrClass stringWithCString:buf length:len]; result = [NSMutableString stringWithCapacity:len + [_ds cStringLength]]; for (cnt = 0; cnt < len; cnt++) { if (buf[cnt] == '.') { if (bufCount > 0) { NSString *s; // TODO: cache selector s = [[StrClass alloc] initWithCString:ptr length:bufCount]; if (s) [result appendString:s]; [s release]; } if (_ds) [result appendString:_ds]; ptr = &(buf[cnt + 1]); bufCount = 0; } else { bufCount++; } if (bufCount > 0) { NSString *s; // TODO: cache selector s = [[StrClass alloc] initWithCString:ptr length:bufCount]; if (s) [result appendString:s]; [s release]; } return result; } } else return nil; } else { switch (fmtChar) { case 's': case 'S': { /* TODO: implement 'S', current mech is evil hack */ unsigned len; char *buffer = NULL; id result; if (_value == nil) return wideString("", width, ' ', alignRight); len = [(NSString *)_value cStringLength]; buffer = malloc(len + 10); [_value getCString:buffer]; buffer[len] = '\0'; result = wideString(buffer, width, ' ', alignRight); free(buffer); return result; } case '@': { id obj = _value; NSString *dstr = obj ? [obj description] : @""; char *buffer = NULL; unsigned len; if (dstr == nil) return wideString("", width, ' ', alignRight); len = [dstr cStringLength]; buffer = malloc(len + 10); [dstr getCString:buffer]; buffer[len] = '\0'; dstr = wideString(buffer, width, ' ', alignRight); free(buffer); return dstr; } case '$': { id obj = _value; NSString *dstr; char *cstr; dstr = obj ? [obj stringValue] : @""; cstr = (char *)[dstr cString]; if (cstr == NULL) cstr = ""; return wideString(cstr, width, ' ', alignRight); } default: fprintf(stderr, "WARNING(%s): unknown printf format used: '%s'\n", __PRETTY_FUNCTION__, fmt); break; } } return nil; } #if USE_VA_LIST_PTR static inline NSString *handleFormat(char *fmt, int fmtLen, va_list *_ap) { #else static inline NSString *handleFormat(char *fmt, int fmtLen, va_list _ap) { #endif char fmtChar; char typeMode = DEFAULT_TYPE; int width = -1; int prec = -1; BOOL alignRight = YES; char *pos = fmt + 1; char *tmp; if (StrClass == Nil) StrClass = [NSString class]; if (fmtLen == 0) return @""; fmtChar = fmt[fmtLen - 1]; while (index(formatAttrs, *pos)) { if (*pos == '-') alignRight = NO; pos++; } /* width */ tmp = pos; while (isdigit((int)*pos)) pos++; if (tmp != pos) { char old = *pos; *pos = '\0'; width = atoi(tmp); *pos = old; } /* prec */ if (*pos == '-') { pos++; tmp = pos; while (isdigit((int)*pos)) pos++; if (tmp != pos) { char old = *pos; *pos = '\0'; prec = atoi(tmp); *pos = old; } } /* conversion */ if (index(formatConv, *pos)) { switch (*pos) { case 'h': typeMode = SHORT_TYPE; pos++; break; case 'l': typeMode = LONG_TYPE; pos++; if (*pos == 'l') { // long-long typeMode = VERY_LONG_TYPE; pos++; } break; case 'L': case 'q': typeMode = VERY_LONG_TYPE; pos++; break; } } #if HEAVY_DEBUG && 0 printf(" width=%i prec=%i\n", width, prec); fflush(stdout); #endif if (index("diouxX", fmtChar)) { char buf[128]; int len = -1; switch (typeMode) { case SHORT_TYPE: { #if USE_VA_LIST_PTR unsigned short int i = va_arg(*_ap, int); #else unsigned short int i = va_arg(_ap, int); #endif len = sprintf(buf, fmt, i); break; } case LONG_TYPE: { #if USE_VA_LIST_PTR unsigned long int i = va_arg(*_ap, unsigned long int); #else unsigned long int i = va_arg(_ap, unsigned long int); #endif len = sprintf(buf, fmt, i); break; } case VERY_LONG_TYPE: { #if USE_VA_LIST_PTR long long i = va_arg(*_ap, long long); #else long long i = va_arg(_ap, long long); #endif len = sprintf(buf, fmt, i); break; } default: { #if USE_VA_LIST_PTR unsigned int i = va_arg(*_ap, unsigned int); #else unsigned int i = va_arg(_ap, unsigned int); #endif len = sprintf(buf, fmt, i); break; } } return (len >= 0) ? [StrClass stringWithCString:buf length:len] : nil; } if (fmtChar == 'c') { char buf[64]; #if USE_VA_LIST_PTR int i = va_arg(*_ap, int); #else int i = va_arg(_ap, int); #endif int len; if (i == 0) return @"<'\\0'-char>"; len = sprintf(buf, fmt, (unsigned char)i); #if HEAVY_DEBUG && 0 xsprintf("got format %s char %i made %s len %i\n", fmt, i, buf, len); #endif if (len == 0) return nil; return [StrClass stringWithCString:buf length:len]; } if (fmtChar == 'C') { /* 16bit unichar */ char buf[64]; #if USE_VA_LIST_PTR int i = va_arg(*_ap, int); #else int i = va_arg(_ap, int); #endif int len; if (i == 0) return @"<'\\0'-unichar>"; /* TODO: implement properly, evil hack */ fmt[fmtLen - 1] = 'c'; len = sprintf(buf, fmt, (unsigned char)i); #if HEAVY_DEBUG && 0 xsprintf("got format %s unichar %i made %s len %i\n", fmt, i, buf, len); #endif if (len == 0) return nil; return [StrClass stringWithCString:buf length:len]; } if (index("feEgG", fmtChar)) { char buf[256]; int len; if (typeMode == VERY_LONG_TYPE) { #if USE_VA_LIST_PTR long double i = va_arg(*_ap, long double); #else long double i = va_arg(_ap, long double); #endif len = sprintf(buf, fmt, i); } else { #if USE_VA_LIST_PTR double i = va_arg(*_ap, double); #else double i = va_arg(_ap, double); #endif len = sprintf(buf, fmt, i); } return (len >= 0) ? [StrClass stringWithCString:buf length:len] : nil; } { id result = nil; switch (fmtChar) { case 's': case 'S': /* unicode char array */ case '@': case '$': { char *cstr = NULL; BOOL owned = NO; if (fmtChar == 's') { #if USE_VA_LIST_PTR cstr = va_arg(*_ap, char *); #else cstr = va_arg(_ap, char *); #endif } else { #if USE_VA_LIST_PTR id obj = va_arg(*_ap, id); #else id obj = va_arg(_ap, id); #endif if (obj == nil) cstr = ""; else { NSString *d; if ((d = (fmtChar == '@') ?[obj description]:[obj stringValue])) { unsigned len = [d cStringLength]; cstr = NGMalloc(len + 1); [d getCString:cstr]; cstr[len] = '\0'; owned = YES; } } } if (cstr == NULL) cstr = ""; result = wideString(cstr, width, ' ', alignRight); if (owned) NGFree(cstr); break; } default: fprintf(stderr, "WARNING(%s): unknown printf format used: '%s'\n", __PRETTY_FUNCTION__, fmt); break; } return result; } return nil; } static inline NSString *_stringWithCFormat(const char *_format, va_list _ap) { const char *firstPercent; NSMutableString *result; if (StrClass == Nil) StrClass = [NSString class]; firstPercent = index(_format, '%'); #if 0 fprintf(stderr, "OWN: format='%s'\n", _format); fflush(stderr); #endif // first check whether there are any '%' in the format .. if (firstPercent == NULL) { // no formatting contained in _format return [StrClass stringWithCString:_format]; } result = [NSMutableString stringWithCapacity:256]; if ((firstPercent - _format) > 0) { NSString *s; s = [[StrClass alloc] initWithCString:_format length:(firstPercent - _format)]; if (s) [result appendString:s]; [s release]; _format = firstPercent; } while (*_format != '\0') { // until end of format string if (*_format == '%') { // found formatting character _format++; // skip '%' if (*_format == '%') { // was a quoted '%' [result appendString:@"%"]; _format++; } else { // check format char extFmt[16]; char *pos = extFmt; extFmt[0] = '%'; pos++; while ((*_format != '\0') && (index(formatChars, *_format) == NULL)) { *pos = *_format; _format++; pos++; } *pos = *_format; _format++; pos++; *pos = '\0'; // printf("handling ext format '%s'\n", extFmt); fflush(stdout); /* hack for iSeries port, ix86 seems to copy va_list iSeries don`t like pointers to va_list */ { NSString *s; #if USE_VA_LIST_PTR s = handleFormat(extFmt, strlen(extFmt), &_ap); #else s = handleFormat(extFmt, strlen(extFmt), _ap); #endif if (s) [result appendString:s]; } } } else { // normal char const char *start = _format; // remember start NSString *s; _format++; // skip found char // further increase format until '\0' or '%' while ((*_format != '\0') && (*_format != '%')) _format++; s = [[StrClass alloc] initWithCString:start length:(_format - start)]; if (s) [result appendString:s]; [s release]; } } return result; } @implementation NSString(XSFormatting) + (id)stringWithCFormat:(const char *)_format arguments:(va_list)_ap { return [self stringWithString:_stringWithCFormat(_format, _ap)]; } + (id)stringWithFormat:(NSString *)_format arguments:(va_list)_ap { unsigned len; char *cfmt; id s; len = [_format cStringLength] + 1; cfmt = malloc(len + 1); [_format getCString:cfmt]; cfmt[len] = '\0'; s = [self stringWithString:_stringWithCFormat(cfmt, _ap)]; free(cfmt); return s; } + (id)stringWithCFormat:(const char *)_format, ... { id result = nil; va_list ap; va_start(ap, _format); result = [self stringWithString:_stringWithCFormat(_format, ap)]; va_end(ap); return result; } + (id)stringWithFormat:(NSString *)_format, ... { id result = nil; unsigned len; char *cfmt; va_list ap; len = [_format cStringLength]; cfmt = malloc(len + 1); [_format getCString:cfmt]; cfmt[len] = '\0'; va_start(ap, _format); result = [self stringWithString:_stringWithCFormat(cfmt, ap)]; va_end(ap); free(cfmt); return result; } - (id)initWithFormat:(NSString *)_format arguments:(va_list)_ap { unsigned len; char *cfmt; len = [_format cStringLength]; cfmt = malloc(len + 1); [_format getCString:cfmt]; cfmt[len] = '\0'; self = [self initWithString:_stringWithCFormat(cfmt, _ap)]; free(cfmt); return self; } @end /* NSString(XSFormatting) */ @implementation NSMutableString(XSFormatting) - (void)appendFormat:(NSString *)_format arguments:(va_list)_ap { unsigned len; NSString *s; char *cfmt; len = [_format cStringLength]; cfmt = malloc(len + 4); [_format getCString:cfmt]; cfmt[len] = '\0'; s = _stringWithCFormat(cfmt, _ap); if (cfmt) free(cfmt); if (s) [self appendString:s]; } - (void)appendFormat:(NSString *)_format, ... { unsigned len; char *cfmt; NSString *s; va_list ap; len = [_format cStringLength]; cfmt = malloc(len + 4); [_format getCString:cfmt]; cfmt[len] = '\0'; va_start(ap, _format); s = _stringWithCFormat(cfmt, ap); va_end(ap); if (cfmt) free(cfmt); if (s) [self appendString:s]; } @end /* NSMutableString(XSFormatting) */ #endif // var args wrappers int xs_sprintf(char *str, const char *format, ...) { va_list ap; int result; va_start(ap, format); result = xs_vsprintf(str, format, ap); va_end(ap); return result; } int xs_snprintf(char *str, size_t size, const char *format, ...) { va_list ap; int result; va_start(ap, format); result = xs_vsnprintf(str, size, format, ap); va_end(ap); return result; } /* static linking */ void __link_NSString_Formatting(void) { __link_NSString_Formatting(); } SOPE/sope-core/NGExtensions/FdExt.subproj/NSObject+Values.m0000644000000000000000000001035315004363604022362 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "NSObject+Values.h" #include "common.h" @implementation NSObject(NGValues) - (BOOL)boolValue { // this returns always YES (the id != nil) return YES; } - (signed char)charValue { return (char)[self intValue]; } - (unsigned char)unsignedCharValue { return (unsigned char)[self intValue]; } - (signed short)shortValue { return (short)[self intValue]; } - (unsigned short)unsignedShortValue { return (unsigned short)[self unsignedIntValue]; } - (signed int)intValue { return [[self stringValue] intValue]; } - (unsigned int)unsignedIntValue { return (unsigned int)[self intValue]; } - (signed long)longValue { return (long)[self intValue]; } - (unsigned long)unsignedLongValue { return (unsigned long)[self unsignedIntValue]; } - (signed long long)longLongValue { return [[self stringValue] longLongValue]; } - (unsigned long long)unsignedLongLongValue { return [[self stringValue] unsignedLongLongValue]; } - (float)floatValue { return [[self stringValue] floatValue]; } - (double)doubleValue { return [[self stringValue] doubleValue]; } - (NSString *)stringValue { return [self description]; } @end /* NSObject(Values) */ @implementation NSString(NGValues) + (NSString *) stringWithUnsignedLongLong: (unsigned long long)value { return [NSString stringWithFormat: @"0x%.16llx", value]; } - (BOOL)boolValue { unsigned len; unichar c1; if ((len = [self length]) == 0) return NO; switch (len) { case 1: c1 = [self characterAtIndex:0]; if (c1 == '1') return YES; return NO; case 2: // NO, no (this is false in any case ;-) return NO; case 3: c1 = [self characterAtIndex:0]; if (c1 != 'Y' && c1 != 'y') return NO; if ([@"YES" isEqualToString:self]) return YES; if ([@"yes" isEqualToString:self]) return YES; break; case 4: c1 = [self characterAtIndex:0]; if (c1 != 'T' && c1 != 't') return NO; if ([@"TRUE" isEqualToString:self]) return YES; if ([@"true" isEqualToString:self]) return YES; break; case 5: // FALSE, false (this is false in any case ;-) return NO; } return NO; } - (NSString *)stringValue { return self; } - (unsigned char)unsignedCharValue { /* Note: this is a hack to support bool values with KVC operations. Problem is, that bools in Objective-C have no own type code and the runtime will use uchar to represent a bool. Note: there are platforms where int as used as the BOOL base type? */ register unsigned len; register unichar c1; if ((len = [self length]) == 0) return 0; c1 = [self characterAtIndex:0]; if (!isdigit(c1)) { switch (len) { case 2: // NO, no (this is false in any case ;-) break; case 3: c1 = [self characterAtIndex:0]; if (c1 != 'Y' && c1 != 'y') return NO; if ([@"YES" isEqualToString:self]) return YES; if ([@"yes" isEqualToString:self]) return YES; break; case 4: c1 = [self characterAtIndex:0]; if (c1 != 'T' && c1 != 't') return NO; if ([@"TRUE" isEqualToString:self]) return YES; if ([@"true" isEqualToString:self]) return YES; break; } } return [self intValue]; } - (unsigned long long)unsignedLongLongValue { return strtoull([self lossyCString], NULL, 0); } @end /* NSString(Values) */ void __link_NGExtensions_NSObjectValues(void) { /* required for static linking */ __link_NGExtensions_NSObjectValues(); } SOPE/sope-core/NGExtensions/FdExt.subproj/NSObject+Logs.m0000644000000000000000000001140215004363604022023 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSObject+Logs.h" #include "NGLoggerManager.h" #include "NGLogger.h" #include "common.h" @implementation NSObject(NGLogs) static Class StringClass = Nil; static inline Class NSStringClass(void) { if (StringClass == Nil) StringClass = [NSString class]; return StringClass; } - (BOOL)isDebuggingEnabled { #if DEBUG return YES; #else return NO; #endif } - (id)logger { static NSMapTable *loggerForClassMap = NULL; static NGLoggerManager *lm = nil; NGLogger *logger; if (!loggerForClassMap) { loggerForClassMap = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks, NSNonRetainedObjectMapValueCallBacks, 200); lm = [NGLoggerManager defaultLoggerManager]; } logger = NSMapGet(loggerForClassMap, object_getClass(self)); if (!logger) { logger = [lm loggerForClass: object_getClass(self)]; NSMapInsert(loggerForClassMap, object_getClass(self), logger); } return logger; } - (id)debugLogger { return [self logger]; } - (NSString *)loggingPrefix { /* improve perf ... */ return [NSStringClass() stringWithFormat:@"<0x%p[%@]>", self, NSStringFromClass([self class])]; } - (void)debugWithFormat:(NSString *)_fmt arguments:(va_list)_va { #if DEBUG NGLogger *logger; NSString *msg, *msg2; /* This does some fancy formatting and calls [NGLogger logLevel:message:] * thereby bypassing the logLevel check normally done in the logger. * So we must do it here */ logger = [self debugLogger]; if ((![self isDebuggingEnabled]) || ([logger logLevel] < NGLogLevelDebug)) return; msg = [[NSStringClass() alloc] initWithFormat:_fmt arguments:_va]; msg2 = [[NSStringClass() alloc] initWithFormat: @"<%@>D %@", [self loggingPrefix], msg]; [logger logLevel:NGLogLevelDebug message:msg2]; [msg2 release]; [msg release]; #else # warning debug is disabled, debugWithFormat wont print anything .. #endif } - (void)logWithFormat:(NSString *)_fmt arguments:(va_list)_va { NGLogger *logger; NSString *msg; logger = [self logger]; if (![logger isLogInfoEnabled]) return; msg = [[NSStringClass() alloc] initWithFormat:_fmt arguments:_va]; [logger logWithFormat:@"%@ %@", [self loggingPrefix], msg]; [msg release]; } - (void)warnWithFormat:(NSString *)_fmt arguments:(va_list)_va { NGLogger *logger; NSString *msg; logger = [self logger]; if (![logger isLogWarnEnabled]) return; msg = [[NSStringClass() alloc] initWithFormat:_fmt arguments:_va]; [logger warnWithFormat:@"%@ %@", [self loggingPrefix], msg]; [msg release]; } - (void)errorWithFormat:(NSString *)_fmt arguments:(va_list)_va { NGLogger *logger; NSString *msg; logger = [self logger]; if (![logger isLogErrorEnabled]) return; msg = [[NSStringClass() alloc] initWithFormat:_fmt arguments:_va]; [logger errorWithFormat:@"%@ %@", [self loggingPrefix], msg]; [msg release]; } - (void)fatalWithFormat:(NSString *)_fmt arguments:(va_list)_va { NGLogger *logger; NSString *msg; logger = [self logger]; if (![logger isLogFatalEnabled]) return; msg = [[NSStringClass() alloc] initWithFormat:_fmt arguments:_va]; [logger fatalWithFormat:@"%@ %@", [self loggingPrefix], msg]; [msg release]; } - (void)debugWithFormat:(NSString *)_fmt, ... { va_list ap; va_start(ap, _fmt); [self debugWithFormat:_fmt arguments:ap]; va_end(ap); } - (void)logWithFormat:(NSString *)_fmt, ... { va_list ap; va_start(ap, _fmt); [self logWithFormat:_fmt arguments:ap]; va_end(ap); } - (void)warnWithFormat:(NSString *)_fmt, ... { va_list ap; va_start(ap, _fmt); [self warnWithFormat:_fmt arguments:ap]; va_end(ap); } - (void)errorWithFormat:(NSString *)_fmt, ... { va_list ap; va_start(ap, _fmt); [self errorWithFormat:_fmt arguments:ap]; va_end(ap); } - (void)fatalWithFormat:(NSString *)_fmt, ... { va_list ap; va_start(ap, _fmt); [self fatalWithFormat:_fmt arguments:ap]; va_end(ap); } @end /* NSObject(NGLogs) */ SOPE/sope-core/NGExtensions/FdExt.subproj/NSString+Ext.m0000644000000000000000000001317615004363604021731 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSString+Ext.h" #include "common.h" #include @implementation NSString(GSAdditions) - (NSString *)stringWithoutPrefix:(NSString *)_prefix { return ([self hasPrefix:_prefix]) ? [self substringFromIndex:[_prefix length]] : (NSString *)[[self copy] autorelease]; } - (NSString *)stringWithoutSuffix:(NSString *)_suffix { return ([self hasSuffix:_suffix]) ? [self substringToIndex:([self length] - [_suffix length])] : (NSString *)[[self copy] autorelease]; } - (NSString *)stringByTrimmingLeadWhiteSpaces { // should check 'whitespaceAndNewlineCharacterSet' .. unsigned len; if ((len = [self length]) > 0) { unichar *buf; unsigned idx; buf = calloc(len + 1, sizeof(unichar)); [self getCharacters:buf]; for (idx = 0; (idx < len) && (buf[idx] == 32); idx++) ; self = [NSString stringWithCharacters:&(buf[idx]) length:(len - idx)]; free(buf); return self; } else return [[self copy] autorelease]; } - (NSString *)stringByTrimmingTailWhiteSpaces { // should check 'whitespaceAndNewlineCharacterSet' .. NSUInteger len; if ((len = [self length]) > 0) { unichar *buf; NSUInteger idx; buf = calloc(len + 1, sizeof(unichar)); [self getCharacters:buf]; for (idx = (len - 1); (idx > 0) && (buf[idx] == 32); idx--) ; self = [NSString stringWithCharacters:buf length:(idx + 1)]; free(buf); return self; } else return [[self copy] autorelease]; } - (NSString *)stringByTrimmingWhiteSpaces { return [[self stringByTrimmingTailWhiteSpaces] stringByTrimmingLeadWhiteSpaces]; } #ifndef GNUSTEP - (NSString *)stringByReplacingString:(NSString *)_orignal withString:(NSString *)_replacement { /* very slow solution .. */ if ([self rangeOfString:_orignal].length == 0) return [[self copy] autorelease]; return [[self componentsSeparatedByString:_orignal] componentsJoinedByString:_replacement]; } - (NSString *)stringByTrimmingLeadSpaces { unsigned len; if ((len = [self length]) > 0) { unichar *buf; unsigned idx; buf = calloc(len + 1, sizeof(unichar)); [self getCharacters:buf]; for (idx = 0; (idx < len) && isspace(buf[idx]); idx++) ; self = [NSString stringWithCharacters:&(buf[idx]) length:(len - idx)]; free(buf); return self; } else return [[self copy] autorelease]; } - (NSString *)stringByTrimmingTailSpaces { unsigned len; if ((len = [self length]) > 0) { unichar *buf; unsigned idx; buf = calloc(len + 1, sizeof(unichar)); [self getCharacters:buf]; for (idx = (len - 1); (idx >= 0) && isspace(buf[idx]); idx--) ; self = [NSString stringWithCharacters:buf length:(idx + 1)]; free(buf); return self; } else return [[self copy] autorelease]; } - (NSString *)stringByTrimmingSpaces { return [[self stringByTrimmingTailSpaces] stringByTrimmingLeadSpaces]; } #endif @end /* NSString(GSAdditions) */ #if !GNUSTEP @implementation NSMutableString(GNUstepCompatibility) - (void)trimLeadSpaces { [self setString:[self stringByTrimmingLeadSpaces]]; } - (void)trimTailSpaces { [self setString:[self stringByTrimmingTailSpaces]]; } - (void)trimSpaces { [self setString:[self stringByTrimmingSpaces]]; } @end /* NSMutableString(GNUstepCompatibility) */ #endif /* !GNUSTEP */ @implementation NSString(lfNSURLUtilities) - (BOOL)isAbsoluteURL { NSRange r; unsigned i; if ([self hasPrefix:@"mailto:"]) return YES; if ([self hasPrefix:@"javascript:"]) return YES; r = [self rangeOfString:@"://"]; if (r.length == 0) { if ([self hasPrefix:@"file:"]) return YES; return NO; } if ([self hasPrefix:@"/"]) return NO; for (i = 0; i < r.location; i++) { if (!isalpha([self characterAtIndex:i])) return NO; } return YES; } - (NSString *)urlScheme { unsigned i, count; unichar c = 0; if ((count = [self length]) == 0) return nil; for (i = 0; i < count; i++) { c = [self characterAtIndex:i]; if (!isalpha(c)) break; } if ((c != ':') || (i < 1)) return nil; return [self substringToIndex:i]; } @end /* NSString(lfNSURLUtilities) */ #if !LIB_FOUNDATION_LIBRARY @implementation NSString(KVCCompatibility) - (id)valueForUndefinedKey:(NSString *)_key { NSLog(@"WARNING: tried to access undefined KVC key '%@' on str object: %@", _key, self); return nil; } @end #endif SOPE/sope-core/NGExtensions/FdExt.subproj/NSString+HTMLEscaping.m0000644000000000000000000001261215004363604023401 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSString+misc.h" #include "common.h" #include @implementation NSString(HTMLEscaping) - (NSString *)stringByEscapingHTMLStringUsingCharacters { NSData *data; register unsigned i, len, j; const wchar_t *chars; wchar_t *buf; unsigned escapeCount; if ((len = [self length]) == 0) return @""; data = [self dataUsingEncoding: NSUTF32LittleEndianStringEncoding]; chars = [data bytes]; len = [data length]; /* check for characters to escape ... */ for (i = 0, escapeCount = 0; i < len/4; i++) { switch (chars[i]) { case '&': case '"': case '<': case '>': escapeCount++; break; default: if (chars[i] > 127) escapeCount++; break; } } if (escapeCount == 0 ) return [[self copy] autorelease]; buf = (wchar_t *)calloc(len+(escapeCount*5)+1, sizeof(wchar_t)); for (i = 0, j = 0; i < len/4; i++) { switch (chars[i]) { /* escape special chars */ case '&': buf[j] = '&'; j++; buf[j] = 'a'; j++; buf[j] = 'm'; j++; buf[j] = 'p'; j++; buf[j] = ';'; j++; break; case '<': buf[j] = '&'; j++; buf[j] = 'l'; j++; buf[j] = 't'; j++; buf[j] = ';'; j++; break; case '>': buf[j] = '&'; j++; buf[j] = 'g'; j++; buf[j] = 't'; j++; buf[j] = ';'; j++; break; default: /* escape big chars */ if (chars[i] > 127) { unsigned char nbuf[16]; unsigned int k; sprintf((char *)nbuf, "&#%i;", (int)chars[i]); for (k = 0; nbuf[k] != '\0'; k++) { buf[j] = nbuf[k]; j++; } } else { /* nothing to escape */ buf[j] = chars[i]; j++; } break; } } self = [[[NSString alloc] initWithBytesNoCopy: buf length: j*sizeof(wchar_t) encoding: NSUTF32LittleEndianStringEncoding freeWhenDone: YES] autorelease]; return self; } - (NSString *)stringByEscapingHTMLAttributeValueUsingCharacters { register unsigned i, len, j; register unichar *chars, *buf; unsigned escapeCount; if ((len = [self length]) == 0) return @""; chars = malloc((len + 3) * sizeof(unichar)); [self getCharacters:chars]; /* check for characters to escape ... */ for (i = 0, escapeCount = 0; i < len; i++) { switch (chars[i]) { case '&': case '"': case '<': case '>': case '\t': case '\n': case '\r': escapeCount++; break; default: if (chars[i] > 127) escapeCount++; break; } } if (escapeCount == 0 ) { /* nothing to escape ... */ if (chars) free(chars); return [[self copy] autorelease]; } buf = calloc((len + 3) + (escapeCount * 8), sizeof(unichar)); for (i = 0, j = 0; i < len; i++) { switch (chars[i]) { /* escape special chars */ case '&': buf[j] = '&'; j++; buf[j] = 'a'; j++; buf[j] = 'm'; j++; buf[j] = 'p'; j++; buf[j] = ';'; j++; break; case '"': buf[j] = '&'; j++; buf[j] = 'q'; j++; buf[j] = 'u'; j++; buf[j] = 'o'; j++; buf[j] = 't'; j++; buf[j] = ';'; j++; break; case '<': buf[j] = '&'; j++; buf[j] = 'l'; j++; buf[j] = 't'; j++; buf[j] = ';'; j++; break; case '>': buf[j] = '&'; j++; buf[j] = 'g'; j++; buf[j] = 't'; j++; buf[j] = ';'; j++; break; case '\t': buf[j] = '&'; j++; buf[j] = '#'; j++; buf[j] = '9'; j++; buf[j] = ';'; j++; break; case '\n': buf[j] = '&'; j++; buf[j] = '#'; j++; buf[j] = '1'; j++; buf[j] = '0'; j++; buf[j] = ';'; j++; break; case '\r': buf[j] = '&'; j++; buf[j] = '#'; j++; buf[j] = '1'; j++; buf[j] = '3'; j++; buf[j] = ';'; j++; break; default: /* escape big chars */ if (chars[i] > 127) { unsigned char nbuf[16]; unsigned int k; sprintf((char *)nbuf, "&#%i;", (int)chars[i]); for (k = 0; nbuf[k] != '\0'; k++) { buf[j] = nbuf[k]; j++; } } else { /* nothing to escape */ buf[j] = chars[i]; j++; } break; } } self = [NSString stringWithCharacters:buf length:j]; if (chars) free(chars); if (buf) free(buf); return self; } - (NSString *)stringByEscapingHTMLString { return [self stringByEscapingHTMLStringUsingCharacters]; } - (NSString *)stringByEscapingHTMLAttributeValue { return [self stringByEscapingHTMLAttributeValueUsingCharacters]; } @end /* NSString(HTMLEscaping) */ SOPE/sope-core/NGExtensions/FdExt.subproj/NSBundle+misc.m0000644000000000000000000000301515004363604022056 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "NSBundle+misc.h" #ifndef LIB_FOUNDATION_LIBRARY @implementation NSBundle(misc) - (NSString*)pathForResource:(NSString*)name ofType:(NSString*)ext inDirectory:(NSString*)directory forLocalizations:(NSArray*)localizationNames { if(!localizationNames) { return [self pathForResource:name ofType:ext inDirectory:directory]; } else { unsigned i, count; count = [localizationNames count]; for(i = 0; i < count; i++) { NSString *lname, *path; lname = [localizationNames objectAtIndex:i]; path = [self pathForResource:name ofType:ext inDirectory:directory forLocalization:lname]; if(path) return path; } } return nil; } @end /* NSBundle(misc) */ #endif SOPE/sope-core/NGExtensions/FdExt.subproj/NSString+Encoding.m0000644000000000000000000002013215004363604022705 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "common.h" #if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY # import #else # include # import #endif #if GNUSTEP_BASE_LIBRARY #import #endif // TODO: should move different implementations to different files ... #if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY @interface NSString(Encoding_PrivateAPI) + (NSStringEncoding)stringEncodingForEncodingNamed:(NSString *)encoding; @end @implementation NSString(Encoding) + (NSStringEncoding)stringEncodingForEncodingNamed:(NSString *)_encoding { CFStringEncoding cfEncoding; if(_encoding == nil) return 0; _encoding = [_encoding lowercaseString]; cfEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)_encoding); if(cfEncoding == kCFStringEncodingInvalidId) return 0; return CFStringConvertEncodingToNSStringEncoding(cfEncoding); } + (NSString *)stringWithData:(NSData *)_data usingEncodingNamed:(NSString *)_encoding { NSStringEncoding encoding; encoding = [NSString stringEncodingForEncodingNamed:_encoding]; return [[[NSString alloc] initWithData:_data encoding:encoding] autorelease]; } - (NSData *)dataUsingEncodingNamed:(NSString *)_encoding { NSStringEncoding encoding; encoding = [NSString stringEncodingForEncodingNamed:_encoding]; return [self dataUsingEncoding:encoding]; } @end /* NSString(Encoding) */ #else /* ! NeXT_Foundation_LIBRARY */ @implementation NSString(Encoding) #if GNUSTEP_BASE_LIBRARY + (NSStringEncoding)stringEncodingForEncodingNamed:(NSString *)_encoding { return [GSMimeDocument encodingFromCharset:_encoding]; } #endif #if LIB_FOUNDATION_LIBRARY + (NSStringEncoding)stringEncodingForEncodingNamed:(NSString *)_encoding { NSString *s = [_encoding lowercaseString]; unsigned len = [s length]; if (s == nil) return 0; switch(len) { case 4: if ([s isEqualToString:@"utf8"]) return NSUTF8StringEncoding; break; case 5: if ([s isEqualToString:@"utf-8"]) return NSUTF8StringEncoding; if ([s isEqualToString:@"ascii"]) return NSASCIIStringEncoding; break; case 6: if ([s isEqualToString:@"latin1"]) return NSISOLatin1StringEncoding; if ([s isEqualToString:@"latin9"]) return NSISOLatin9StringEncoding; break; case 10: if ([s isEqualToString:@"iso-8859-1"]) return NSISOLatin1StringEncoding; break; case 11: if ([s isEqualToString:@"iso-8859-15"]) return NSISOLatin9StringEncoding; break; } //NSLog(@"%s: could not derive NSStringEncoding from name: '%@'", _encoding); return 0; } #endif #ifdef __linux__ #if __BYTE_ORDER == __LITTLE_ENDIAN static NSString *unicharEncoding = @"UTF-16LE"; #else static NSString *unicharEncoding = @"UTF-16BE"; #endif /* __BYTE_ORDER */ #else static NSString *unicharEncoding = @"UCS-2-INTERNAL"; #endif static int IconvLogEnabled = -1; static void checkDefaults(void) { NSUserDefaults *ud; if (IconvLogEnabled == -1) { ud = [NSUserDefaults standardUserDefaults]; IconvLogEnabled = [ud boolForKey:@"IconvLogEnabled"]?1:0; //NSLog(@"Note: using '%@' on Linux.", unicharEncoding); } } static char *iconv_wrapper(id self, char *_src, unsigned _srcLen, NSString *_fromEncode, NSString *_toEncode, unsigned *outLen_) { iconv_t type; size_t inbytesleft, outbytesleft, write, outlen; const char *fromEncode, *toEncode; char *inbuf, *outbuf, *tm; checkDefaults(); if (IconvLogEnabled) { [self logWithFormat:@"FromEncode: %@; ToEncode: %@", _fromEncode, _toEncode]; } _fromEncode = [_fromEncode uppercaseString]; _toEncode = [_toEncode uppercaseString]; if (0 && [_fromEncode isEqualToString:_toEncode]) { outlen = _srcLen; outbuf = calloc(sizeof(char), outlen+1); memcpy(outbuf, _src, _srcLen); *outLen_ = outlen; return outbuf; } fromEncode = [_fromEncode cString]; toEncode = [_toEncode cString]; type = iconv_open(toEncode, fromEncode); inbuf = NULL; outbuf = NULL; if (type == (iconv_t)-1) { [self logWithFormat:@"%s: Could not handle iconv encoding. FromEncoding:%@" @" to encoding:%@", __PRETTY_FUNCTION__, _fromEncode, _toEncode]; goto CLEAR_AND_RETURN; } inbytesleft = _srcLen; inbuf = _src; outlen = inbytesleft * 3; outbuf = calloc(outlen + 1, sizeof(char));; tm = outbuf; outbytesleft = outlen; write = iconv(type, (void*)&inbuf, &inbytesleft, &tm, &outbytesleft); if (write == (size_t)-1) { if (errno == EILSEQ) { [self logWithFormat:@"Got invalid multibyte sequence. ToEncode: %@" @" FromEncode: %@.", _toEncode, _fromEncode]; if (IconvLogEnabled) { [self logWithFormat:@"ByteSequence:\n%s\n", _src]; } goto CLEAR_AND_RETURN; } else if (errno == EINVAL) { [self logWithFormat:@"Got incomplete multibyte sequence. ToEncode: %@" @" FromEncode: %@", _toEncode, _fromEncode]; if (IconvLogEnabled) [self logWithFormat:@"ByteSequence:\n%s\n", _src]; } else if (errno == E2BIG) { [self logWithFormat: @"Got to small outputbuffer (inbytesleft=%d, outbytesleft=%d, " @"outlen=%d). ToEncode: %@ FromEncode: %@", inbytesleft, outbytesleft, outlen, _toEncode, _fromEncode]; if (IconvLogEnabled) [self logWithFormat:@"ByteSequence:\n%s\n", _src]; goto CLEAR_AND_RETURN; } else { [self logWithFormat:@"Got unexpected error. ToEncode: %@" @" FromEncode: %@", _toEncode, _fromEncode]; goto CLEAR_AND_RETURN; } } #if DEBUG_ICONV NSLogL(@"outlen %d outbytesleft %d", outlen, outbytesleft); #endif if (type) iconv_close(type); *outLen_ = outlen - outbytesleft; return outbuf; CLEAR_AND_RETURN: if (type && (type != (iconv_t)-1)) iconv_close(type); if (outbuf) { free(outbuf); outbuf = NULL; } return NULL; } + (NSString *)stringWithData:(NSData *)_data usingEncodingNamed:(NSString *)_encoding { void *inbuf, *res; unsigned len, inbufLen; NSString *result; if (![_encoding length]) return nil; inbufLen = [_data length]; inbuf = calloc(sizeof(char), inbufLen + 4); [_data getBytes:inbuf]; result = nil; res = iconv_wrapper(self, inbuf, inbufLen, _encoding, unicharEncoding, &len); if (res) { result = [[NSString alloc] initWithCharacters:res length:(len / 2)]; free(res); res = NULL; } if (inbuf) free(inbuf); inbuf = NULL; return [result autorelease]; } - (NSData *)dataUsingEncodingNamed:(NSString *)_encoding { unichar *chars; char *res; unsigned inputLen, resLen; NSData *data; if (![_encoding length]) return nil; data = nil; inputLen = [self length]; chars = calloc(sizeof(unichar), inputLen + 4); [self getCharacters:chars]; res = iconv_wrapper(self, (char *)chars, inputLen*2, unicharEncoding, _encoding, &resLen); if (res) data = [NSData dataWithBytes:res length:resLen]; if (chars) free(chars); chars = NULL; return data; } @end /* NSString(Encoding) */ #endif /* ! NeXT_Foundation_LIBRARY */ SOPE/sope-core/NGExtensions/FdExt.subproj/NSNull+misc.m0000644000000000000000000001430415004363604021562 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSNull+misc.h" #include "common.h" #if LIB_FOUNDATION_LIBRARY || GNUSTEP_BASE_LIBRARY #if __GNU_LIBOBJC__ >= 20100911 # include #else # include # include # include #endif # ifndef GNUSTEP # import # endif #else # import #endif @implementation NSNull(misc) static int _doAbort = -1; static inline BOOL doAbort(void) { if (_doAbort == -1) { _doAbort = [[NSUserDefaults standardUserDefaults] boolForKey:@"NSNullAbortOnMessage"] ? 1 : 0; } return _doAbort ? YES : NO; } - (BOOL)isNotNull { return NO; } - (BOOL)isNotEmpty { return NO; } - (BOOL)isNull { #if DEBUG && 0 NSLog(@"WARNING(%s): called deprecated -isNull on NSNull (use -isNotNull) !", __PRETTY_FUNCTION__); if (doAbort()) abort(); #endif return YES; } - (NSString *)stringValue { #if DEBUG && 0 NSLog(@"WARNING(%s): " @"NSNull -stringValue returns empty string.", __PRETTY_FUNCTION__); if (doAbort()) abort(); #endif return @""; } - (double)doubleValue { #if DEBUG && 0 NSLog(@"WARNING(%s): " @"NSNull -doubleValue returns 0.0.", __PRETTY_FUNCTION__); if (doAbort()) abort(); #endif return 0.0; } - (unsigned int)length { #if DEBUG && 0 NSLog(@"WARNING(%s): " @"called NSNull -length (returns 0) !!!", __PRETTY_FUNCTION__); if (doAbort()) abort(); #endif return 0; } - (unsigned int)count { #if DEBUG && 0 NSLog(@"WARNING(%s): " @"called NSNull -count (returns 0) !!!", __PRETTY_FUNCTION__); if (doAbort()) abort(); #endif return 0; } - (BOOL)isEqualToString:(NSString *)_s { /* Note: I think we can keep this as a regular method */ return _s == (id)self || _s == nil ? YES : NO; } - (BOOL)hasPrefix:(NSString *)_s { /* Note: I think we can keep this as a regular method */ return _s == (id)self || _s == nil ? YES : NO; } - (BOOL)hasSuffix:(NSString *)_s { /* Note: I think we can keep this as a regular method */ return _s == (id)self || _s == nil ? YES : NO; } - (unichar)characterAtIndex:(unsigned int)_idx { #if DEBUG && 0 NSLog(@"WARNING(%s): " @"called NSNull -characterAtIndex:%d - returning 0!", __PRETTY_FUNCTION__, _idx); if (doAbort()) abort(); #endif return 0; } /* key-value coding */ - (void)takeValue:(id)_value forKey:(NSString *)_key { /* do nothing */ } - (id)valueForKey:(NSString *)_key { if ([_key isEqualToString:@"isNotNull"]) { static NSNumber *noNum = nil; if (noNum == nil) noNum = [NSNumber numberWithBool:NO]; return noNum; } if ([_key isEqualToString:@"isNull"]) { static NSNumber *yesNum = nil; if (yesNum == nil) yesNum = [NSNumber numberWithBool:YES]; return yesNum; } /* do nothing */ return nil; } /* forwarding ... */ #if !GNU_RUNTIME - (BOOL)respondsToSelector:(SEL)_sel { /* fake that we have a selector */ return YES; } - (NSString *)descriptionWithLocale:(id)_locale indent:(int)_indent { return @""; } - (NSString *)descriptionWithLocale:(id)_locale { return @""; } #endif - (void)forwardInvocation:(NSInvocation *)_invocation { NSMethodSignature *sig; NSLog(@"ERROR(%s): called selector %@ on NSNull !", __PRETTY_FUNCTION__, NSStringFromSelector([_invocation selector])); if (doAbort()) abort(); if ((sig = [_invocation methodSignature])) { const char *ret; if ((ret = [sig methodReturnType])) { switch (*ret) { case _C_INT: { int v = 0; [_invocation setReturnValue:&v]; break; } case _C_UINT: { unsigned int v = 0; [_invocation setReturnValue:&v]; break; } case _C_ID: case _C_CLASS: { id v = nil; [_invocation setReturnValue:&v]; break; } default: NSLog(@" didn't set return value for type '%s'", ret); break; } } else NSLog(@" no method return type in signature %@", sig); } else NSLog(@" no method signature in invocation %@", _invocation); } @end /* NSNull(misc) */ @implementation NSObject(NSNullMisc) - (BOOL)isNotNull { return YES; } - (BOOL)isNotEmpty { return [self isNotNull]; } - (BOOL)isNull { #if DEBUG && 0 NSLog(@"%s: WARNING, called -isNull on NSObject (use -isNotNull) !", __PRETTY_FUNCTION__); #endif return NO; } @end /* NSObject(NSNullMisc) */ @implementation NSString(NSNullMisc) - (BOOL)isNotEmpty { unsigned i, len; if ((len = [self length]) == 0) return NO; // TODO: just check the first char for performance ... // But: a single space should be treated as emtpy, since this is very common // in SQL (Sybase in special) for (i = 0; i < len; i++) { if (!isspace([self characterAtIndex:i])) return YES; } return NO; } @end /* NSString(NSNullMisc) */ @implementation NSArray(NSNullMisc) - (BOOL)isNotEmpty { return [self count] == 0 ? NO : YES; } @end /* NSArray(NSNullMisc) */ @implementation NSSet(NSNullMisc) - (BOOL)isNotEmpty { return [self count] == 0 ? NO : YES; } @end /* NSSet(NSNullMisc) */ @implementation NSDictionary(NSNullMisc) - (BOOL)isNotEmpty { return [self count] == 0 ? NO : YES; } @end /* NSDictionary(NSNullMisc) */ @implementation NSData(NSNullMisc) - (BOOL)isNotEmpty { return [self length] == 0 ? NO : YES; } @end /* NSData(NSNullMisc) */ SOPE/sope-core/NGExtensions/FdExt.subproj/NSCalendarDate+matrix.m0000644000000000000000000000672615004363604023541 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSCalendarDate+misc.h" #include "common.h" @implementation NSCalendarDate(CalMatrix) static BOOL debugCalMatrix = NO; - (NSArray *)calendarMatrixWithStartDayOfWeek:(short)_caldow onlyCurrentMonth:(BOOL)_onlyThisMonth { // Note: we keep clock time! NSAutoreleasePool *pool; NSCalendarDate *firstInMonth; NSArray *matrix; NSArray *weeks[8] = { nil, nil, nil, nil, nil, nil, nil, nil }; NSCalendarDate *week[8] = { nil, nil, nil, nil, nil, nil, nil, nil }; unsigned firstDoW, numDaysInLastMonth, i, j, curday, curweek, curmonth; /* all the date operations use autorelease, so we wrap it in a pool */ pool = [[NSAutoreleasePool alloc] init]; if (debugCalMatrix) NSLog(@"calmatrix for: %@", self); firstInMonth = [[self firstDayOfMonth] beginOfDay]; firstDoW = [firstInMonth dayOfWeek]; curmonth = [firstInMonth monthOfYear]; numDaysInLastMonth = (firstDoW < _caldow) ? (firstDoW + 7 - _caldow) : (firstDoW - _caldow); if (debugCalMatrix) { NSLog(@" LAST: %d FIRST-DOW: %d START-DOW: %d", numDaysInLastMonth, firstDoW, _caldow); } /* first week */ if (_onlyThisMonth) { j = 0; /* this is the position where first week days are added */ } else { /* add dates from last month */ for (i = numDaysInLastMonth; i > 0; i--) { week[numDaysInLastMonth - i] = [firstInMonth dateByAddingYears:0 months:0 days:-i]; } j = numDaysInLastMonth; } week[j] = firstInMonth; j++; for (i = numDaysInLastMonth + 1; i < 7; i++, j++) { week[j] = [firstInMonth dateByAddingYears:0 months:0 days:(i - numDaysInLastMonth)]; } curday = 7 - numDaysInLastMonth; curweek = 1; if (debugCalMatrix) NSLog(@" current day after 1st week: %d, week: %d", curday, curweek); /* finish first week */ weeks[0] = [[NSArray alloc] initWithObjects:week count:j]; /* follow up weeks */ while (curweek < 7) { BOOL foundNewMonth = NO; for (i = 0; i < 7; i++, curday++) { week[i] = [firstInMonth dateByAddingYears:0 months:0 days:curday]; if (!foundNewMonth && curday > 27) { foundNewMonth = ([week[i] monthOfYear] != curmonth) ? YES : NO; if (foundNewMonth && _onlyThisMonth) break; } } if (i > 0) { weeks[curweek] = [[NSArray alloc] initWithObjects:week count:i]; curweek++; } if (foundNewMonth) break; } /* build final matrix */ matrix = [[NSArray alloc] initWithObjects:weeks count:curweek]; for (i = 0; i < 8; i++) { [weeks[i] release]; weeks[i] = nil; } if (debugCalMatrix) NSLog(@"matrix for %@: %@", self, matrix); [pool release]; return [matrix autorelease]; } @end /* NSCalendarDate(CalMatrix) */ SOPE/sope-core/NGExtensions/FdExt.subproj/NSData+gzip.m0000644000000000000000000001204515004363604021537 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSData+gzip.h" #include "common.h" #ifdef Assert # undef Assert #endif #include #ifndef DEF_MEM_LEVEL /* zutil.h */ # if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 # else # define DEF_MEM_LEVEL MAX_MEM_LEVEL # endif # define OS_CODE 0x07 /* TODO: probably need to adjust that ... */ #endif #undef Assert @implementation NSData(gzip) - (NSData *)gzip { return [self gzipWithLevel:Z_DEFAULT_COMPRESSION]; } static inline void putLong(uLong x, NSMutableData *data, IMP addBytes) { int n; for (n = 0; n < 4; n++) { unsigned char c = (int)(x & 0xff); addBytes(data, @selector(appendBytes:length:), &c, 1); x >>= 8; } } - (NSData *)gzipWithLevel:(int)_level { NSMutableData *data = nil; int errorCode = 0; unsigned len = [self length]; void *src = (void *)[self bytes]; IMP addBytes = NULL; char outBuf[4096]; z_stream out; uLong crc; NSAssert1((_level >= NGGZipMinimalCompression && _level <= NGGZipMaximalCompression) || (_level == Z_DEFAULT_COMPRESSION), @"invalid compression level %i (0-9)", _level); data = [NSMutableData dataWithCapacity: (len / 10 < 128) ? len : len / 10]; addBytes = [data methodForSelector:@selector(appendBytes:length:)]; out.zalloc = (alloc_func)NULL; out.zfree = (free_func)NULL; out.opaque = (voidpf)NULL; out.next_out = (Byte*)&outBuf; out.avail_out = sizeof(outBuf); out.next_in = Z_NULL; out.avail_in = 0; errorCode = Z_OK; crc = crc32(0L, Z_NULL, 0); errorCode = deflateInit2(&out, _level, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0); // windowBits is passed <0 to suppress zlib header if (errorCode != Z_OK) { NSLog(@"ERROR: could not init deflate !"); return nil; } { // add gzip header char buf[10] = { 0x1f, 0x8b, // magic Z_DEFLATED, 0, // flags 0, 0, 0, 0, // time 0, OS_CODE // flags }; addBytes(data, @selector(appendBytes:length:), &buf, 10); } { // gz_write out.next_in = src; out.avail_in = len; while (out.avail_in > 0) { if (out.avail_out == 0) { out.next_out = (void *)&outBuf; // reset buffer position addBytes(data, @selector(appendBytes:length:), &outBuf, sizeof(outBuf)); out.avail_out = sizeof(outBuf); } errorCode = deflate(&out, Z_NO_FLUSH); if (errorCode != Z_OK) { NSLog(@"ERROR: could not deflate chunk !"); if (out.state) deflateEnd(&out); return nil; } } crc = crc32(crc, src, len); } { // gz_flush BOOL done = NO; out.next_in = NULL; out.avail_in = 0; // should be zero already anyway for (;;) { len = sizeof(outBuf) - out.avail_out; if (len > 0) { addBytes(data, @selector(appendBytes:length:), &outBuf, len); out.next_out = (void *)&outBuf; out.avail_out = sizeof(outBuf); } if (done) break; errorCode = deflate(&out, Z_FINISH); // deflate has finished flushing only when it hasn't used up // all the available space in the output buffer: done = (out.avail_out != 0 || errorCode == Z_STREAM_END); if (errorCode != Z_OK && errorCode != Z_STREAM_END) break; } if (errorCode != Z_STREAM_END) { NSLog(@"ERROR: flush failed."); if (out.state) deflateEnd(&out); return nil; } } { // write trailer (checksum and filesize) putLong(crc, data, addBytes); putLong(out.total_in, data, addBytes); } if (out.state) deflateEnd(&out); return data; } - (NSData *)compress { return [self compressWithLevel: 3]; } - (NSData *)compressWithLevel: (int) level { NSData *result; Bytef *destBuffer; unsigned long destLen; int rc; destLen = [self length]; destBuffer = NSZoneMalloc (NULL, destLen); rc = compress2 (destBuffer, &destLen, [self bytes], destLen, level); if (rc == Z_OK) result = [NSData dataWithBytesNoCopy: destBuffer length: destLen freeWhenDone: YES]; else result = nil; return result; } @end void __link_NSData_gzip(void) { __link_NSData_gzip(); } SOPE/sope-core/NGExtensions/FdExt.subproj/NSDictionary+misc.m0000644000000000000000000000350215004363604022753 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "NSDictionary+misc.h" @implementation NSDictionary(misc) - (NSDictionary *)dictionaryByExchangingKeysAndValues { NSDictionary *reverse; NSArray *oKeys; unsigned i, len; id *keys, *values; oKeys = [self allKeys]; if ((len = [oKeys count]) == 0) return [[self copy] autorelease]; keys = calloc(len + 10, sizeof(id)); values = calloc(len + 10, sizeof(id)); for (i = 0; i < len; i++) { values[i] = [oKeys objectAtIndex:i]; keys[i] = [self objectForKey:values[i]]; } reverse = [[NSDictionary alloc] initWithObjects:values forKeys:keys count:len]; free(keys); free(values); return [reverse autorelease]; } @end /* NSDictionary(misc) */ @implementation NSMutableDictionary(misc) - (void)removeObjectsForKeysV:(id)_firstKey, ... { va_list ap; va_start(ap, _firstKey); while (_firstKey) { [self removeObjectForKey:_firstKey]; _firstKey = va_arg(ap, id); } va_end(ap); } @end /* NSMutableDictionary(misc) */ void __link_NSDictionary_misc() { __link_NSDictionary_misc(); } SOPE/sope-core/NGExtensions/FdExt.subproj/NSRunLoop+FileObjects.m0000644000000000000000000000727715004363604023517 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created by Helge Hess on Mon Mar 11 2002. #if !LIB_FOUNDATION_LIBRARY #include #include "NSRunLoop+FileObjects.h" #include "FileObjectHolder.h" #import #import #include "common.h" NSString *NSFileObjectBecameActiveNotificationName = @"NSFileObjectBecameActiveNotification"; #if GNUSTEP_BASE_LIBRARY @interface NSObject(FileObjectWatcher) < RunLoopEvents > @end @implementation NSObject(FileObjectWatcher) - (NSDate *)timedOutEvent:(void *)_fdData type: (RunLoopEventType)_type forMode: (NSString *)_mode { NSLog(@"%s: timed out ...", __PRETTY_FUNCTION__); return nil; } - (void)receivedEvent:(void *)_fdData type:(RunLoopEventType)_type extra:(void *)_extra forMode:(NSString *)_mode { if ([self isOpen]) { NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; [nc postNotificationName:NSFileObjectBecameActiveNotificationName object:self]; } } @end /* NSObject(FileObjectWatcher) */ #endif @implementation NSRunLoop(FileObjects) #if GNUSTEP_BASE_LIBRARY /* implement using -addEvent:type:watcher:forMode: */ - (void)addFileObject:(id)_fileObject activities:(NSUInteger)_activities forMode:(NSString *)_mode { NSInteger evType = 0; _fileObject = RETAIN(_fileObject); [self addEvent:(void *) ((NSInteger) [_fileObject fileDescriptor]) type:evType watcher:_fileObject forMode:_mode]; } - (void)removeFileObject:(id)_fileObject forMode:(NSString *)_mode { int evType = 0; _fileObject = AUTORELEASE(_fileObject); [self removeEvent:(void *) ((NSInteger) [_fileObject fileDescriptor]) type:evType forMode:_mode all:NO]; } #else /* eg MacOSX Foundation ... */ static NSMutableArray *activeHandles = nil; - (void)addFileObject:(id)_fileObject activities:(unsigned int)_activities forMode:(NSString *)_mode { FileObjectHolder *fo; if (activeHandles == nil) activeHandles = [[NSMutableArray alloc] init]; fo = [[FileObjectHolder alloc] initWithFileObject:_fileObject activities:_activities mode:_mode]; [activeHandles addObject:fo]; [fo wait]; [fo release]; } - (FileObjectHolder *)_findHolderForObject:(id)_fileObject { NSEnumerator *e; FileObjectHolder *fo; if (activeHandles == nil) return NULL; e = [activeHandles objectEnumerator]; while ((fo = [e nextObject])) { if ([fo fileObject] == _fileObject) break; } return fo; } - (void)removeFileObject:(id)_fileObject forMode:(NSString *)_mode { FileObjectHolder *fo; if ((fo = [self _findHolderForObject:_fileObject]) == nil) { NSLog(@"found no holder for fileobject %@ ...", _fileObject); return; } [fo retain]; [activeHandles removeObject:fo]; [fo stopWaiting]; [fo release]; } #endif /* !GNUSTEP_BASE_LIBRARY */ @end /* NSRunLoop(FileObjects) */ #endif /* !LIB_FOUNDATION_LIBRARY */ SOPE/sope-core/NGExtensions/FdExt.subproj/NSFileManager+Extensions.m0000644000000000000000000001110015004363604024215 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSFileManager+Extensions.h" #include "NGFileFolderInfoDataSource.h" #import #include "common.h" @interface NSFileManagerGlobalID : EOGlobalID < NSCopying > { @public NSString *path; } @end // TODO: support -lastException // TODO: add stuff like -dictionaryAtPath:, -arrayAtPath:, -propertyListAtPath: @implementation NSFileManager(ExtendedFileManagerImp) /* directories */ - (BOOL)createDirectoriesAtPath:(NSString *)_p attributes:(NSDictionary *)_a { unsigned i, count; NSArray *pc; BOOL isDir; if ([_p length] == 0) return NO; if ([self fileExistsAtPath:_p isDirectory:&isDir]) return isDir; pc = [_p pathComponents]; if ((count = [pc count]) == 0) return YES; for (i = 0; i < count; i++) { NSString *fp; NSRange r; r.location = 0; r.length = i + 1; fp = [NSString pathWithComponents:[pc subarrayWithRange:r]]; if ([self fileExistsAtPath:fp isDirectory:&isDir]) { if (!isDir) /* exists, but is a file */ return NO; continue; } if (![self createDirectoryAtPath:fp attributes:_a]) /* failed to create */ return NO; } return YES; } /* path modifications */ - (NSString *)standardizePath:(NSString *)_path { if (![_path isAbsolutePath]) _path = [[self currentDirectoryPath] stringByAppendingPathComponent:_path]; return [_path stringByStandardizingPath]; } - (NSString *)resolveSymlinksInPath:(NSString *)_path { return [_path stringByResolvingSymlinksInPath]; } - (NSString *)expandTildeInPath:(NSString *)_path { return [_path stringByExpandingTildeInPath]; } /* feature check */ - (BOOL)supportsVersioningAtPath:(NSString *)_path { return NO; } - (BOOL)supportsLockingAtPath:(NSString *)_path { return NO; } - (BOOL)supportsFolderDataSourceAtPath:(NSString *)_path { return YES; } - (BOOL)supportsFeature:(NSString *)_featureURI atPath:(NSString *)_path { if ([_featureURI isEqualToString:NGFileManagerFeature_DataSources]) return YES; return NO; } /* writing */ - (BOOL)writeContents:(NSData *)_content atPath:(NSString *)_path { return [_content writeToFile:_path atomically:YES]; } /* global-IDs */ - (EOGlobalID *)globalIDForPath:(NSString *)_path { NSFileManagerGlobalID *gid; _path = [self standardizePath:_path]; gid = [[NSFileManagerGlobalID alloc] init]; gid->path = [_path copy]; return [gid autorelease]; } - (NSString *)pathForGlobalID:(EOGlobalID *)_gid { NSFileManagerGlobalID *gid; if (![_gid isKindOfClass:[NSFileManagerGlobalID class]]) /* not a gid we can handle ... */ return nil; gid = (NSFileManagerGlobalID *)_gid; return gid->path; } /* datasources (work on folders) */ - (EODataSource *)dataSourceAtPath:(NSString *)_path { return [[[NGFileFolderInfoDataSource alloc] initWithFolderPath:_path] autorelease]; } - (EODataSource *)dataSource { return [self dataSourceAtPath:[self currentDirectoryPath]]; } /* trash */ - (BOOL)supportsTrashFolderAtPath:(NSString *)_path { return NO; } - (NSString *)trashFolderForPath:(NSString *)_path { return nil; } - (BOOL)trashFileAtPath:(NSString *)_path handler:(id)_handler { // TODO: support trashfolder on MacOSX ? return NO; } @end /* NSFileManager(ExtendedFileManagerImp) */ @implementation NSFileManagerGlobalID - (void)dealloc { [self->path release]; [super dealloc]; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { /* global IDs are immutable, so we can return an retained object ... */ return [self retain]; } /* description */ - (NSString *)description { NSMutableString *ms = [NSMutableString stringWithCapacity:32]; [ms appendFormat:@"<0x%p[%@]", self, NSStringFromClass([self class])]; [ms appendFormat:@" path=%@", self->path]; [ms appendString:@">"]; return ms; } @end /* NSFileManagerGlobalID */ SOPE/sope-core/NGExtensions/FdExt.subproj/NSCalendarDate+misc.m0000644000000000000000000004066415004363604023167 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSCalendarDate+misc.h" #include "common.h" #include #define NUMBER_OF_SECONDS_IN_DAY (24 * 60 * 60) @implementation NSCalendarDate(misc) + (NSCalendarDate *)mondayOfWeek:(int)_weekNumber inYear:(int)_year timeZone:(NSTimeZone *)_tz { NSCalendarDate *janFirst; janFirst = [NSCalendarDate dateWithYear:_year month:1 day:1 hour:0 minute:0 second:0 timeZone:_tz]; return [janFirst mondayOfWeek:_weekNumber]; } - (NSCalendarDate *)mondayOfWeek:(int)_weekNumber { NSCalendarDate *mondayOfWeek; short lastWeek; mondayOfWeek = [self firstMondayAndLastWeekInYear:&lastWeek]; if (_weekNumber == 1) return mondayOfWeek; return [mondayOfWeek dateByAddingYears:0 months:0 days:(7 * (_weekNumber - 1))]; } + (NSArray *)mondaysOfYear:(int)_year timeZone:(NSTimeZone *)_tz { NSCalendarDate *janFirst; janFirst = [NSCalendarDate dateWithYear:_year month:1 day:1 hour:0 minute:0 second:0 timeZone:_tz]; return [janFirst mondaysOfYear]; } - (NSArray *)mondaysOfYear { NSArray *array; NSMutableArray *mondays; NSCalendarDate *mondayOfWeek; short lastWeek; int i; mondayOfWeek = [self firstMondayAndLastWeekInYear:&lastWeek]; mondays = [[NSMutableArray alloc] initWithCapacity:55]; for (i = 0; i < lastWeek; i++) { #if 0 // hh: can someone explain this ?! if (i > 0) { mondayOfWeek = [mondayOfWeek addYear:0 month:0 day:7 hour:0 minute:0 second:0]; } mondayOfWeek = [[mondayOfWeek copy] autorelease]; [mondays addObject:mondayOfWeek]; #else NSCalendarDate *tmp; tmp = [mondayOfWeek dateByAddingYears:0 months:0 days:(i * 7)]; [mondays addObject:tmp]; #endif } array = [mondays copy]; [mondays release]; return [array autorelease]; } - (NSCalendarDate *)firstMondayAndLastWeekInYear:(short *)_lastWeek { NSTimeZone *tz; int currentYear; short lastWeek; NSCalendarDate *janFirst; NSCalendarDate *silvester; NSCalendarDate *mondayOfWeek; tz = [self timeZone]; currentYear = [self yearOfCommonEra]; if ([self weekOfYear] == 53) { NSCalendarDate *nextJanFirst = nil; nextJanFirst = [NSCalendarDate dateWithYear:(currentYear + 1) month:1 day:1 hour:0 minute:0 second:0 timeZone:tz]; if ([nextJanFirst weekOfYear] == 1) currentYear++; } janFirst = [NSCalendarDate dateWithYear:currentYear month:1 day:1 hour:0 minute:0 second:0 timeZone:tz]; silvester = [NSCalendarDate dateWithYear:currentYear month:12 day:31 hour:23 minute:59 second:59 timeZone:tz]; lastWeek = [silvester weekOfYear]; if (lastWeek == 53) { NSCalendarDate *nextJanFirst = nil; nextJanFirst = [NSCalendarDate dateWithYear:currentYear+1 month:1 day:1 hour:0 minute:0 second:0 timeZone:tz]; if ([nextJanFirst weekOfYear] == 1) lastWeek = 52; } if ([janFirst weekOfYear] != 1) { mondayOfWeek = [janFirst mondayOfWeek]; #if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY mondayOfWeek = [mondayOfWeek dateByAddingYears:0 months:0 days:7 hours:0 minutes:0 seconds:0]; #else mondayOfWeek = [mondayOfWeek addYear:0 month:0 day:7 hour:0 minute:0 second:0]; #endif } else { mondayOfWeek = [janFirst mondayOfWeek]; } if (_lastWeek) *_lastWeek = lastWeek; return mondayOfWeek; } - (NSCalendarDate *)firstDayOfMonth { NSTimeInterval tv; NSCalendarDate *first; int dayOfMonth; NSTimeZone *tz; dayOfMonth = [self dayOfMonth]; tz = [self timeZone]; tv = (1 - dayOfMonth) * NUMBER_OF_SECONDS_IN_DAY; tv = [self timeIntervalSince1970] + tv; first = [NSCalendarDate dateWithTimeIntervalSince1970:tv]; [first setTimeZone:tz]; return first; } - (NSCalendarDate *)lastDayOfMonth { int offset = [self numberOfDaysInMonth] - [self dayOfMonth]; return [self dateByAddingYears:0 months:0 days:offset]; } - (int)numberOfDaysInMonth { static int leapYearMonths[12] = {31,29,31,30,31,30,31,31,30,31,30,31}; static int nonLeapYearMonths[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; int *numberOfDaysInMonth = [self isInLeapYear] ? leapYearMonths : nonLeapYearMonths; return numberOfDaysInMonth[[self monthOfYear] - 1]; } - (BOOL)isInLeapYear { unsigned year = [self yearOfCommonEra]; return (((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0); } - (int)weekOfMonth { /* returns 1-6 */ int dayOfMonth; int weekOfYear; int firstWeekOfYear; dayOfMonth = [self dayOfMonth]; /* 1-31 */ if (dayOfMonth == 1) return 1; /* could be done smarter (by calculating on dayOfWeek) */ weekOfYear = [self weekOfYear]; firstWeekOfYear = [[self firstDayOfMonth] weekOfYear]; return (weekOfYear - firstWeekOfYear + 1); } - (int)weekOfYear { static int whereToStart[] = { 6, 7, 8, 9, 10, 4, 5 }; NSCalendarDate *janFirst; int year, day, weekOfYear; NSTimeZone *tz; year = [self yearOfCommonEra]; day = [self dayOfYear] - 1; tz = [self timeZone]; janFirst = [NSCalendarDate dateWithYear:year month:1 day:1 hour:0 minute:0 second:0 timeZone:tz]; weekOfYear = (day + whereToStart[[janFirst dayOfWeek]]) / 7; if (weekOfYear == 0) { NSCalendarDate *silvesterLastYear; silvesterLastYear = [NSCalendarDate dateWithYear:(year - 1) month:12 day:31 hour:0 minute:0 second:0 timeZone:tz]; return [silvesterLastYear weekOfYear]; } #if 0 if (weekOfYear == 53) { NSCalendarDate *nextJanFirst = nil; int janYear = year + 1; int janDay; int week; nextJanFirst = [NSCalendarDate dateWithYear:janYear month:1 day:1 hour:0 minute:0 second:0 timeZone:[self timeZone]]; janDay = [nextJanFirst dayOfYear]; week = (janDay + whereToStart[[nextJanFirst dayOfWeek]]) / 7; if (week == 1) return 52; } #endif return weekOfYear; } - (short)numberOfWeeksInYear { NSCalendarDate *silvester; NSCalendarDate *dayOfLastWeek; NSTimeZone *tz; short currentYear; currentYear = [self yearOfCommonEra]; tz = [self timeZone]; silvester = [NSCalendarDate dateWithYear:currentYear month:12 day:31 hour:23 minute:59 second:59 timeZone:tz]; dayOfLastWeek = [silvester dateByAddingYears:0 months:0 days:-3 hours:0 minutes:0 seconds:0]; return [dayOfLastWeek weekOfYear]; } - (NSCalendarDate *)mondayOfWeek { NSTimeInterval tv; NSCalendarDate *monday; int dayOfWeek; NSTimeZone *tz; dayOfWeek = [self dayOfWeek]; tz = [self timeZone]; if (dayOfWeek == 0) dayOfWeek = 7; // readjust Sunday tv = (1 - dayOfWeek) * NUMBER_OF_SECONDS_IN_DAY; tv = [self timeIntervalSince1970] + tv; monday = [NSCalendarDate dateWithTimeIntervalSince1970:tv]; [monday setTimeZone:tz]; return monday; } - (NSCalendarDate *)beginOfDay { NSTimeZone *tz; tz = [self timeZone]; return [NSCalendarDate dateWithYear:[self yearOfCommonEra] month: [self monthOfYear] day: [self dayOfMonth] hour:0 minute:0 second:0 timeZone: tz]; } - (NSCalendarDate *)endOfDay { NSTimeZone *tz; tz = [self timeZone]; return [NSCalendarDate dateWithYear:[self yearOfCommonEra] month: [self monthOfYear] day: [self dayOfMonth] hour:23 minute:59 second:59 timeZone: tz]; } - (BOOL)isDateOnSameDay:(NSCalendarDate *)_date { if ([self dayOfYear] != [_date dayOfYear]) return NO; if ([self yearOfCommonEra] != [_date yearOfCommonEra]) return NO; return YES; } - (BOOL)isDateInSameWeek:(NSCalendarDate *)_date { if ([self weekOfYear] != [_date weekOfYear]) return NO; if ([self yearOfCommonEra] != [_date yearOfCommonEra]) return NO; return YES; } - (BOOL)isToday { NSCalendarDate *d; BOOL result; d = [[NSCalendarDate alloc] init]; [d setTimeZone:[self timeZone]]; result = [self isDateOnSameDay:d]; [d release]; return result; } - (BOOL)isForenoon { return [self hourOfDay] >= 12 ? NO : YES; } - (BOOL)isAfternoon { return [self hourOfDay] >= 12 ? YES : NO; } - (NSCalendarDate *)yesterday { return [self dateByAddingYears:0 months:0 days:-1 hours:0 minutes:0 seconds:0]; } - (NSCalendarDate *)tomorrow { return [self dateByAddingYears:0 months:0 days:1 hours:0 minutes:0 seconds:0]; } - (NSCalendarDate *)lastYear { return [self dateByAddingYears:-1 months:0 days:0 hours:0 minutes:0 seconds:0]; } - (NSCalendarDate *)nextYear { return [self dateByAddingYears:1 months:0 days:0 hours:0 minutes:0 seconds:0]; } - (NSCalendarDate *)hour:(int)_hour minute:(int)_minute second:(int)_second { NSTimeZone *tz; tz = [self timeZone]; return [NSCalendarDate dateWithYear:[self yearOfCommonEra] month: [self monthOfYear] day: [self dayOfMonth] hour:_hour minute:_minute second:_second timeZone: tz]; } - (NSCalendarDate *)hour:(int)_hour minute:(int)_minute { return [self hour:_hour minute:_minute second:0]; } /* Y2K support */ - (NSCalendarDate *)y2kDate { NSCalendarDate *newDate; int year; year = [self yearOfCommonEra]; if (year >= 70 && year < 135) { newDate = [[NSCalendarDate alloc] initWithYear:(year + 1900) month:[self monthOfYear] day:[self dayOfMonth] hour:[self hourOfDay] minute:[self minuteOfHour] second:[self secondOfMinute] timeZone:[self timeZone]]; } else if (year >= 0 && year < 70) { newDate = [[NSCalendarDate alloc] initWithYear:(year + 2000) month:[self monthOfYear] day:[self dayOfMonth] hour:[self hourOfDay] minute:[self minuteOfHour] second:[self secondOfMinute] timeZone:[self timeZone]]; } else newDate = [self retain]; return [newDate autorelease]; } - (NSCalendarDate *)dateByAddingYears:(int)_years months:(int)_months days:(int)_days { #if 0 /* this expects that NSCalendarDate accepts invalid days, like 2000-02-31 */ int newYear, newMonth, newDay; newYear = [self yearOfCommonEra] + _years; newMonth = [self monthOfYear] + _months; newDay = [self dayOfMonth] + _days; // this doesn't check month overflow !! return [NSCalendarDate dateWithYear:newYear month:newMonth day:newDay hour:[self hourOfDay] minute:[self minuteOfHour] second:[self secondOfMinute] timeZone:[self timeZone]]; #else // but this does it return [self dateByAddingYears:_years months:_months days:_days hours:0 minutes:0 seconds:0]; #endif } /* calculate easter ... */ - (NSCalendarDate *)easterOfYear { /* algorithm taken from: http://www.uni-bamberg.de/~ba1lw1/fkal.html#Algorithmus */ int y; unsigned m, n; int a, b, c, d, e; unsigned easterMonth, easterDay; y = [self yearOfCommonEra]; if ((y > 1699) && (y < 1800)) { m = 23; n = 3; } else if ((y > 1799) && (y < 1900)) { m = 23; n = 4; } else if ((y > 1899) && (y < 2100)) { m = 24; n = 5; } else if ((y > 2099) && (y < 2200)) { m = 24; n = 6; } else return nil; a = y % 19; b = y % 4; c = y % 7; d = (19 * a + m) % 30; e = (2 * b + 4 * c + 6 * d + n) % 7; easterMonth = 3; easterDay = 22 + d + e; if (easterDay > 31) { easterDay -= 31; easterMonth = 4; if (easterDay == 26) easterDay = 19; if ((easterDay == 25) && (d == 28) && (a > 10)) easterDay = 18; } return [NSCalendarDate dateWithYear:y month:easterMonth day:easterDay hour:0 minute:0 second:0 timeZone:[self timeZone]]; } #if !LIB_FOUNDATION_LIBRARY - (id)valueForUndefinedKey:(NSString *)_key { NSLog(@"WARNING: tried to access undefined KVC key '%@' on date object: %@", _key, self); return nil; } #endif /* Oct. 15, 1582 */ #define IGREG (15+31L*(10+12L*1582)) - (long)julianNumber { long jul; int ja, jy, jm, year, month, day; year = [self yearOfCommonEra]; month = [self monthOfYear]; day = [self dayOfMonth]; jy = year; if (jy == 0) return 0; if (jy < 0) jy++; if (month > 2) jm = month + 1; else { jy--; jm = month + 13; } jul = (long) (floor(365.25 * jy) + floor(30.6001 * jm) + day + 1720995); if (day + 31L * (month + 12L * year) >= IGREG) { ja = (int)(0.01 * jy); jul += 2 - ja + (int) (0.25 * ja); } return jul; } + (NSCalendarDate *)dateForJulianNumber:(long)_jn { long ja, jalpha, jb, jc, jd, je; unsigned day, month, year; if (_jn >= IGREG) { jalpha = (long)(((float) (_jn - 1867216) - 0.25) / 36524.25); ja = _jn + 1 + jalpha - (long)(0.25 * jalpha); } else { ja = _jn; } jb = ja + 1524; jc = (long)(6680.0 + ((float)(jb - 2439870) - 122.1) / 365.25); jd = (long)(365 * jc + (0.25 * jc)); je = (long)((jb - jd) / 30.6001); day = jb - jd - (long)(30.6001 * je); month = je - 1; if (month > 12) month -= 12; year = jc - 4715; if (month > 2) year--; if (year <= 0) year--; return [NSCalendarDate dateWithYear:year month:month day:day hour:12 minute:0 second:0 timeZone:nil]; } @end /* NSCalendarDate(misc) */ @implementation NSString(FuzzyDayOfWeek) - (int)dayOfWeekInEnglishOrGerman { NSString *s; unichar c1; unsigned len; if ((len = [self length]) == 0) return -1; if (isdigit([self characterAtIndex:0])) return [self intValue]; if (len < 2) /* need at least two chars */ return -1; s = [self lowercaseString]; c1 = [s characterAtIndex:1]; switch ([s characterAtIndex:0]) { case 'm': // Monday, Montag, Mittwoch return (c1 == 'i') ? 3 /* Wednesday */ : 1 /* Monday */; case 't': // Tuesday, Thursday return (c1 == 'u') ? 2 /* Tuesday */ : 4 /* Thursday */; case 'f': // Friday, Freitag return 5 /* Friday */; case 's': // Saturday, Sunday, Samstag, Sonntag, Sonnabend if (c1 == 'a') return 6; /* Saturday */ if (c1 == 'o' && [s hasPrefix:@"sonna"]) return 6; /* Sonnabend */ return 0 /* Sunday */; case 'w': // Wed return 3 /* Wednesday */; } return -1; } @end /* NSString(FuzzyDayOfWeek) */ /* static linking */ void __link_NSCalendarDate_misc(void) { __link_NSCalendarDate_misc(); } SOPE/sope-core/NGExtensions/FdExt.subproj/NSException+misc.m0000644000000000000000000000442615004363604022612 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSException+misc.h" #import #include "common.h" @implementation NSObject(NSExceptionNGMiscellaneous) - (BOOL)isException { return NO; } - (BOOL)isExceptionOrNull { return NO; } @end /* NSObject(NSExceptionNGMiscellaneous) */ @implementation NSNull(NSExceptionNGMiscellaneous) - (BOOL)isException { return NO; } - (BOOL)isExceptionOrNull { return YES; } @end /* NSNull(NSExceptionNGMiscellaneous) */ @implementation NSException(NGMiscellaneous) - (BOOL)isException { return YES; } - (BOOL)isExceptionOrNull { return YES; } - (id)initWithReason:(NSString *)_reason { return [self initWithReason:_reason userInfo:nil]; } - (id)initWithReason:(NSString *)_reason userInfo:(id)_userInfo { return [self initWithName:NSStringFromClass([self class]) reason:_reason userInfo:_userInfo]; } - (id)initWithFormat:(NSString *)_format,... { NSString *tmp = nil; va_list ap; if (_format == nil) NSLog(@"ERROR(%s): missing format!", __PRETTY_FUNCTION__); va_start(ap, _format); tmp = [[NSString alloc] initWithFormat: _format ? _format : (NSString *)@"Exception" arguments:ap]; va_end(ap); self = [self initWithReason:tmp userInfo:nil]; [tmp release]; tmp = nil; return self; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { // TODO: should make a real copy? return (id)[self retain]; } @end /* NSException(NGMiscellaneous) */ void __link_NGExtensions_NSExceptionMisc() { __link_NGExtensions_NSExceptionMisc(); } SOPE/sope-core/NGExtensions/FdExt.subproj/NSString+URLEscaping.m0000644000000000000000000002066615004363604023307 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSString+misc.h" #include "common.h" /* TODO: support new Panther API?: - (NSString *)stringByAddingPercentEscapesUsingEncoding:(NSStringEncoding)e - (NSString *)stringByReplacingPercentEscapesUsingEncoding:(NSStringEncoding)e */ @implementation NSString(URLEscaping) static int useUTF8Encoding = -1; static inline BOOL doUseUTF8Encoding(void) { if (useUTF8Encoding == -1) { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; useUTF8Encoding = [ud boolForKey:@"NGUseUTF8AsURLEncoding"] ? 1 : 0; //if (useUTF8Encoding) // NSLog(@"Note: Using UTF-8 as URL encoding in NGExtensions."); } return useUTF8Encoding ? YES : NO; } static inline BOOL isUrlAlpha(unsigned char _c) { return (((_c >= 'a') && (_c <= 'z')) || ((_c >= 'A') && (_c <= 'Z'))) ? YES : NO; } static inline BOOL isUrlDigit(unsigned char _c) { return ((_c >= '0') && (_c <= '9')) ? YES : NO; } static inline BOOL isUrlSafeChar(unsigned char _c) { switch (_c) { case '$': case '-': case '_': case '.': #if 0 /* see OGo bug #1260, required for forms */ case '+': #endif case '@': // TODO: not a safe char?! return YES; default: return NO; } } static inline BOOL isUrlExtraChar(unsigned char _c) { switch (_c) { case '!': case '*': case '"': case '\'': case '|': case ',': return YES; } return NO; } static inline BOOL isUrlEscapeChar(unsigned char _c) { return (_c == '%') ? YES : NO; } static inline BOOL isUrlReservedChar(unsigned char _c) { switch (_c) { case '=': case ';': case '/': case '#': case '?': case ':': case ' ': return YES; } return NO; } static inline BOOL isUrlXalpha(unsigned char _c) { if (isUrlAlpha(_c)) return YES; if (isUrlDigit(_c)) return YES; if (isUrlSafeChar(_c)) return YES; if (isUrlExtraChar(_c)) return YES; if (isUrlEscapeChar(_c)) return YES; return NO; } static inline BOOL isUrlHexChar(unsigned char _c) { if (isUrlDigit(_c)) return YES; if ((_c >= 'a') && (_c <= 'f')) return YES; if ((_c >= 'A') && (_c <= 'F')) return YES; return NO; } static inline BOOL isUrlAlphaNum(unsigned char _c) { return (isUrlAlpha(_c) || isUrlDigit(_c)) ? YES : NO; } static inline BOOL isToBeEscaped(unsigned char _c) { return (isUrlAlphaNum(_c) || (_c == '_') || isUrlSafeChar(_c)) ? NO : YES; } static void NGEscapeUrlBuffer(const unsigned char *_source, unsigned char *_dest, unsigned srclen) { register const unsigned char *src = (void*)_source; register unsigned i; for (i = 0; i < srclen; i++, src++) { #if 0 // explain! if (*src == ' ') { // a ' ' becomes a '+' *_dest = '+'; _dest++; } #endif if (!isToBeEscaped(*src)) { *_dest = *src; _dest++; } else { // any other char is escaped .. *_dest = '%'; _dest++; sprintf((char *)_dest, "%02X", (unsigned)*src); _dest += 2; } } *_dest = '\0'; } static inline int _valueOfHexChar(register unichar _c) { switch (_c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return (_c - 48); // 0-9 (ascii-char)'0' - 48 => (int)0 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': return (_c - 55); // A-F, A=10..F=15, 'A'=65..'F'=70 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': return (_c - 87); // a-f, a=10..F=15, 'a'=97..'f'=102 default: return -1; } } static inline BOOL _isHexDigit(register unichar _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 YES; default: return NO; } } static void NGUnescapeUrlBuffer(const unsigned char *_source, unsigned char *_dest) { BOOL done = NO; while (!done && (*_source != '\0')) { char c = *_source; //if (c == '+') // '+' stands for a space // *_dest = ' '; if (c == '%') { _source++; c = *_source; if (c == '\0') { *_dest = '%'; done = YES; } else if (_isHexDigit(c)) { // hex-escaped char, like '%F3' int decChar = _valueOfHexChar(c); _source++; c = *_source; decChar = decChar * 16 + _valueOfHexChar(c); *_dest = (unsigned char)decChar; } else // escaped char, like '%%' -> '%' *_dest = c; } else // char passed through *_dest = c; _dest++; _source++; } *_dest = '\0'; } - (BOOL)containsURLEscapeCharacters { register unsigned i, len; register unichar (*charAtIdx)(id,SEL,unsigned); if ((len = [self length]) == 0) return NO; charAtIdx = (void*)[self methodForSelector:@selector(characterAtIndex:)]; for (i = 0; i < len; i++) { if (charAtIdx(self, @selector(characterAtIndex:), i) == '%') return YES; } return NO; } - (BOOL)containsURLInvalidCharacters { register NSUInteger i, len; const char *utf8String; utf8String = [self UTF8String]; len = strlen (utf8String); for (i = 0; i < len; i++) { if (isToBeEscaped(utf8String[i])) return YES; } return NO; } - (NSString *)stringByUnescapingURL { /* Input is a URL string - per definition ASCII(?!), like "hello%98%88.txt" output is a unicode string (never longer than the input) Note that the input itself is in some encoding! That is, the input is turned into a buffer eg containing UTF-8 and needs to be converted into a unicode string. */ unsigned len; char *cstr; char *buffer = NULL; NSString *s; if (![self containsURLEscapeCharacters]) /* scan for '%' */ return [[self copy] autorelease]; if ((len = [self cStringLength]) == 0) return @""; cstr = malloc(len + 10); [self getCString:cstr]; /* this is OK, a URL is always in ASCII! */ cstr[len] = '\0'; buffer = malloc(len + 4); NGUnescapeUrlBuffer((unsigned char *)cstr, (unsigned char *)buffer); if (doUseUTF8Encoding()) { /* OK, the input is considered UTF-8 encoded in a string */ s = [[NSString alloc] initWithUTF8String:buffer]; /* We fallback to ISO-8859-1 here, as this method totally ignores the charset */ if (!s) s = [[NSString alloc] initWithCString:buffer encoding: NSISOLatin1StringEncoding]; if (buffer != NULL) free(buffer); buffer = NULL; } else { s = [[NSString alloc] initWithCStringNoCopy:buffer length:strlen(buffer) freeWhenDone:YES]; } if (cstr != NULL) free(cstr); cstr = NULL; return [s autorelease]; } - (NSString *)stringByEscapingURL { unsigned len; NSString *s; NSData *data; char *buffer = NULL; NSStringEncoding encoding; if ((len = [self length]) == 0) return @""; if (![self containsURLInvalidCharacters]) // needs to be escaped ? return [[self copy] autorelease]; // steps: // a) encode into a data buffer! (eg UTF8 or ISO) // b) encode that buffer into URL encoding // c) create an ASCII string from that encoding = (doUseUTF8Encoding() ? NSUTF8StringEncoding : NSISOLatin1StringEncoding); if ((data = [self dataUsingEncoding:encoding]) == nil) return nil; if ((len = [data length]) == 0) return @""; buffer = malloc(len * 3 + 2); NGEscapeUrlBuffer([data bytes], (unsigned char *)buffer, len); /* the following assumes that the default-encoding is ASCII compatible */ s = [[NSString alloc] initWithBytesNoCopy:buffer length:strlen(buffer) encoding:NSASCIIStringEncoding freeWhenDone:YES]; return [s autorelease]; } @end /* NSString(URLEscaping) */ SOPE/sope-core/NGExtensions/FdExt.subproj/NSDictionary+KVC.m0000644000000000000000000000245615004363604022452 0ustar rootroot/* Copyright (C) 2000-2008 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if GNUSTEP_BASE_LIBRARY #import "common.h" #import "NSDictionary+KVC.h" @implementation NSDictionary(KVC) // TODO: it should be addressed to gnustep-base - (id)valueForUndefinedKey:(NSString *)key { return nil; } - (id)handleQueryWithUnboundKey:(NSString *)key { return nil; } - (void)setValue:(id)value forUndefinedKey:(NSString *)key { return; } - (void)handleTakeValue:(id)value forUnboundKey:(NSString *)key { return; } @end /* NSDictionary(KVC) */ void __link_NSDictionary_KVC() { __link_NSDictionary_KVC(); } #endif SOPE/sope-core/NGExtensions/FdExt.subproj/NSData+misc.m0000644000000000000000000000253715004363604021526 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "NSData+misc.h" @implementation NSData(misc) - (BOOL)hasPrefix:(NSData *)_data { return [self hasPrefixBytes:[_data bytes] length:[_data length]]; } - (BOOL)hasPrefixBytes:(const void *)_bytes length:(unsigned)_len { if (_len > [self length]) return NO; else { const unsigned char *ownBytes = [self bytes]; register unsigned i; for (i = 0; i < _len; i++) { if (((unsigned char *)_bytes)[i] != ownBytes[i]) return NO; } return YES; } } @end /* NSData(misc) */ void __link_NSData_misc() { __link_NSData_misc(); } SOPE/sope-core/NGExtensions/FdExt.subproj/NSEnumerator+misc.m0000644000000000000000000000717415004363604023000 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "NSEnumerator+misc.h" #import #import #include "common.h" @interface _NGFilterEnumerator : NSEnumerator { NSEnumerator *source; } + (NSEnumerator *)filterEnumeratorWithSource:(NSEnumerator *)_e; - (NSEnumerator *)source; @end @interface _NGQualifierFilterEnumerator : _NGFilterEnumerator { EOQualifier *q; } - (void)setQualifier:(EOQualifier *)_q; - (EOQualifier *)qualifier; @end @interface _NGSelFilterEnumerator : _NGFilterEnumerator { SEL sel; id arg; } - (void)setSelector:(SEL)_s; - (SEL)selector; - (void)setArgument:(id)_arg; - (id)argument; @end @implementation NSEnumerator(misc) - (NSEnumerator *)filterWithQualifier:(EOQualifier *)_qualifier { id e; e = [_NGQualifierFilterEnumerator filterEnumeratorWithSource:self]; [e setQualifier:_qualifier]; return e; } - (NSEnumerator *)filterWithQualifierString:(NSString *)_s { EOQualifier *q; q = [EOQualifier qualifierWithQualifierFormat:_s]; return [self filterWithQualifier:q]; } - (NSEnumerator *)filterWithSelector:(SEL)_selector withObject:(id)_argument { id e; e = [_NGSelFilterEnumerator filterEnumeratorWithSource:self]; [e setSelector:_selector]; [e setArgument:_argument]; return e; } @end /* NSEnumerator(misc) */ @implementation _NGFilterEnumerator - (id)initWithSource:(NSEnumerator *)_e { self->source = [_e retain]; return self; } - (void)dealloc { [self->source release]; [super dealloc]; } + (NSEnumerator *)filterEnumeratorWithSource:(NSEnumerator *)_e { return [[(_NGFilterEnumerator *)[self alloc] initWithSource:_e] autorelease]; } - (NSEnumerator *)source { return self->source; } - (id)nextObject { return [self->source nextObject]; } @end /* _NGFilterEnumerator */ @implementation _NGQualifierFilterEnumerator - (void)dealloc { [self->q release]; [super dealloc]; } - (void)setQualifier:(EOQualifier *)_q { ASSIGN(self->q, _q); } - (EOQualifier *)qualifier { return self->q; } - (id)nextObject { while (YES) { id obj; if ((obj = [self->source nextObject]) == nil) return nil; if (self->q == nil) return obj; if ([(id)self->q evaluateWithObject:obj]) return obj; } } @end /* _NGQualifierFilterEnumerator */ @implementation _NGSelFilterEnumerator - (void)dealloc { [self->arg release]; [super dealloc]; } - (void)setSelector:(SEL)_s { self->sel = _s; } - (SEL)selector { return self->sel; } - (void)setArgument:(id)_arg { ASSIGN(self->arg, _arg); } - (id)argument { return self->arg; } - (id)nextObject { while (YES) { id obj; BOOL (*m)(id,SEL,id); if ((obj = [self->source nextObject]) == nil) return nil; if ((m = (void *)[obj methodForSelector:self->sel]) == NULL) continue; if (m(obj, self->sel, self->arg)) return obj; } } @end /* _NGSelFilterEnumerator */ SOPE/sope-core/NGExtensions/FdExt.subproj/NSString+XMLEscaping.m0000644000000000000000000000740415004363604023300 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSString+misc.h" #include "common.h" @implementation NSString(XMLEscaping) - (NSString *)stringByEscapingXMLStringUsingCharacters { register unsigned i, len, j; register unichar *chars, *buf; unsigned escapeCount; if ((len = [self length]) == 0) return @""; chars = malloc((len + 3) * sizeof(unichar)); [self getCharacters:chars]; /* check for characters to escape ... */ for (i = 0, escapeCount = 0; i < len; i++) { switch (chars[i]) { case '&': case '"': case '<': case '>': escapeCount++; break; default: if (chars[i] > 127) escapeCount++; break; } } if (escapeCount == 0 ) { /* nothing to escape ... */ if (chars) free(chars); return [[self copy] autorelease]; } buf = malloc(((len + 3) * sizeof(unichar)) + (escapeCount * 8 * sizeof(unichar))); for (i = 0, j = 0; i < len; i++) { switch (chars[i]) { /* escape special chars */ case '&': buf[j] = '&'; j++; buf[j] = 'a'; j++; buf[j] = 'm'; j++; buf[j] = 'p'; j++; buf[j] = ';'; j++; break; case '"': buf[j] = '&'; j++; buf[j] = 'q'; j++; buf[j] = 'u'; j++; buf[j] = 'o'; j++; buf[j] = 't'; j++; buf[j] = ';'; j++; break; case '<': buf[j] = '&'; j++; buf[j] = 'l'; j++; buf[j] = 't'; j++; buf[j] = ';'; j++; break; case '>': buf[j] = '&'; j++; buf[j] = 'g'; j++; buf[j] = 't'; j++; buf[j] = ';'; j++; break; default: /* escape big chars */ if (chars[i] > 127) { unsigned char nbuf[16]; unsigned int k; sprintf((char *)nbuf, "&#%i;", (int)chars[i]); for (k = 0; nbuf[k] != '\0'; k++) { buf[j] = nbuf[k]; j++; } } else { /* nothing to escape */ buf[j] = chars[i]; j++; } break; } } self = [NSString stringWithCharacters:buf length:j]; if (chars) free(chars); if (buf) free(buf); return self; } - (NSString *)stringByEscapingXMLString { return [self stringByEscapingXMLStringUsingCharacters]; } - (NSString *)stringByEscapingXMLAttributeValue { return [self stringByEscapingHTMLAttributeValue]; } /* XML FQNs */ - (BOOL)xmlIsFQN { if ([self length] == 0) return NO; return [self characterAtIndex:0] == '{' ? YES : NO; } - (NSString *)xmlNamespaceURI { NSRange r; r = [self rangeOfString:@"}" options:(NSLiteralSearch | NSBackwardsSearch)]; if (r.length == 0) return nil; if ([self characterAtIndex:0] != '{') return nil; r.length = (r.location - 1); r.location = 1; return [self substringWithRange:r]; } - (NSString *)xmlLocalName { NSRange r; r = [self rangeOfString:@"}" options:(NSLiteralSearch | NSBackwardsSearch)]; if (r.length == 0) return nil; if ([self characterAtIndex:0] != '{') return nil; return [self substringFromIndex:(r.location + r.length)]; } @end /* NSString(XMLEscaping) */ SOPE/sope-core/NGExtensions/NGExtensions/0000755000000000000000000000000015004363604017167 5ustar rootrootSOPE/sope-core/NGExtensions/NGExtensions/NSData+gzip.h0000644000000000000000000000220515004363604021416 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGZlib_NSData_gzip_H__ #define __NGZlib_NSData_gzip_H__ #import #define NGGZipMinimalCompression 0 #define NGGZipMaximalCompression 9 @interface NSData(gzip) - (NSData *)gzipWithLevel:(int)_compressionLevel; - (NSData *)gzip; - (NSData *)compress; - (NSData *)compressWithLevel: (int) level; @end #endif /* __NGZlib_NSData_gzip_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGLogging.h0000644000000000000000000000257715004363604021166 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGLogging_H_ #define __NGExtensions_NGLogging_H_ /* NGLogging is a new logging framework, modeled in a similar fashion as Log4J - without some of its bloat. Documentation is currently provided in the headers only. */ #include #include #include #include #include #include #include #include #endif /* __NGExtensions_NGLogging_H_ */ SOPE/sope-core/NGExtensions/NGExtensions/NGRuleContext.h0000644000000000000000000000413515004363604022044 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGRuleEngine_NGRuleContext_H__ #define __NGRuleEngine_NGRuleContext_H__ #import /* NGRuleContext This is a specialized rule evaluation object for key based (assignment) rules. It exports evaluated rule values using key-value coding, thereby giving a very simple access somewhat similar to CSS. */ @class NSString, NSArray, NSMutableDictionary; @class NGRuleModel; @interface NGRuleContext : NSObject { NSMutableDictionary *storedValues; NGRuleModel *model; BOOL debugOn; } + (id)ruleContextWithModelInUserDefault:(NSString *)_defName; + (id)ruleContextWithModel:(NGRuleModel *)_model; - (id)initWithModel:(NGRuleModel *)_model; /* accessors */ - (void)setModel:(NGRuleModel *)_model; - (NGRuleModel *)model; - (void)setDebugEnabled:(BOOL)_flag; - (BOOL)isDebuggingEnabled; /* values */ - (void)takeStoredValue:(id)_value forKey:(NSString *)_key; - (id)storedValueForKey:(NSString *)_key; - (void)reset; - (void)takeValue:(id)_value forKey:(NSString *)_key; /* processing */ - (id)valueForKey:(NSString *)_key; - (id)inferredValueForKey:(NSString *)_key; - (NSArray *)allPossibleValuesForKey:(NSString *)_key; - (NSArray *)valuesForKeyPath:(NSString *)_kp takingSuccessiveValues:(NSArray *)_values forKeyPath:(NSString *)_valkp; @end #endif /* __NGRuleEngine_NGRuleContext_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGObjectMacros.h0000644000000000000000000000324515004363604022144 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGObjectMacros_H__ #define __NGExtensions_NGObjectMacros_H__ #ifndef ASSIGN # define ASSIGN(object, value) \ ({id __object = (id)object; \ id __value = (id)value; \ if (__value != __object) { \ object = (__value) ? [__value retain] : nil; \ if (__object) [__object release]; \ }}) #endif #ifndef ASSIGNCOPY # define ASSIGNCOPY(object, value) \ ({id __object = (id)object; \ id __value = (id)value; \ if (__value != __object) { \ object = __value ? [__value copy] : nil; \ if (__object) [__object release]; \ }}) #endif #ifndef RETAIN # define RETAIN(__XXX__) [__XXX__ retain] #endif #ifndef RELEASE # define RELEASE(__XXX__) [__XXX__ release] #endif #ifndef AUTORELEASE # define AUTORELEASE(__XXX__) [__XXX__ autorelease] #endif #endif /* __NGExtensions_NGObjectMacros_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGLogFileHandleAppender.h0000644000000000000000000000264515004363604023710 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGLogFileHandleAppender_H_ #define __NGExtensions_NGLogFileHandleAppender_H_ /* NGLogFileHandleAppender Suits as an abstract base class for all NSFileHandle based appenders. */ #include #import /* for NSStringEncoding */ @class NSFileHandle, NSDictionary; @interface NGLogFileHandleAppender : NGLogAppender { NSFileHandle *fh; NSStringEncoding encoding; BOOL flushImmediately; } - (BOOL)isFileHandleOpen; - (void)openFileHandleWithConfig:(NSDictionary *)_config; - (void)closeFileHandle; @end #endif /* __NGExtensions_NGLogFileHandleAppender_H_ */ SOPE/sope-core/NGExtensions/NGExtensions/NGCustomFileManager.h0000644000000000000000000000601015004363604023127 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGCustomFileManager_H__ #define __NGCustomFileManager_H__ #include /* An abstract baseclass for developing custom filemanagers which are ideally based on other filemanager classes. */ @class NGCustomFileManagerInfo; @interface NGCustomFileManager : NGFileManager { } /* customization */ - (NSString *)makeAbsolutePath:(NSString *)_path; - (NGCustomFileManagerInfo *)fileManagerInfoForPath:(NSString *)_path; @end @interface NGCustomFileManager(NGFileManagerVersioning) /* versioning */ - (BOOL)checkoutFileAtPath:(NSString *)_path handler:(id)_handler; - (BOOL)releaseFileAtPath:(NSString *)_path handler:(id)_handler; - (BOOL)rejectFileAtPath:(NSString *)_path handler:(id)_handler; - (BOOL)checkoutFileAtPath:(NSString *)_path version:(NSString *)_version handler:(id)_handler; /* versioning data */ - (NSString *)lastVersionAtPath:(NSString *)_path; - (NSArray *)versionsAtPath:(NSString *)_path; - (NSData *)contentsAtPath:(NSString *)_path version:(NSString *)_version; - (NSDictionary *)fileAttributesAtPath:(NSString *)_path traverseLink:(BOOL)_followLink version:(NSString *)_version; @end @interface NGCustomFileManager(NGFileManagerDataSources) /* datasources (work on folders) */ - (EODataSource *)dataSourceAtPath:(NSString *)_path; - (EODataSource *)dataSource; // works on current-directory-path @end @interface NGCustomFileManager(NGFileManagerLocking) - (BOOL)lockFileAtPath:(NSString *)_path handler:(id)_handler; - (BOOL)unlockFileAtPath:(NSString *)_path handler:(id)_handler; - (BOOL)isFileLockedAtPath:(NSString *)_path; /* access rights */ - (BOOL)isLockableFileAtPath:(NSString *)_path; - (BOOL)isUnlockableFileAtPath:(NSString *)_path; @end @interface NGCustomFileManagerInfo : NSObject { @private NGCustomFileManager *master; /* non retained */ id fileManager; } - (id)initWithCustomFileManager:(NGCustomFileManager *)_master fileManager:(id)_fm; - (void)resetMaster; /* accessors */ - (NGCustomFileManager *)master; - (id)fileManager; /* operations */ - (NSString *)rewriteAbsolutePath:(NSString *)_path; /* capabilities */ - (BOOL)supportsGlobalIDs; @end #endif /* __NGCustomFileManager_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSCalendarDate+misc.h0000644000000000000000000000655215004363604023047 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSCalendarDate_misc_H__ #define __NGExtensions_NSCalendarDate_misc_H__ #import #import #if NeXT_Foundation_LIBRARY || GNUSTEP_BASE_LIBRARY # import #endif @class NSArray, NSTimeZone; @interface NSCalendarDate(misc) - (int)weekOfMonth; - (int)weekOfYear; - (short)numberOfWeeksInYear; + (NSArray *)mondaysOfYear:(int)_year timeZone:(NSTimeZone *)_tz; - (NSArray *)mondaysOfYear; - (NSCalendarDate *)firstMondayAndLastWeekInYear:(short *)_lastWeek; + (NSCalendarDate *)mondayOfWeek:(int)_weekNumber inYear:(int)_year timeZone:(NSTimeZone *)_tz; - (NSCalendarDate *)mondayOfWeek:(int)_weekNumber; + (NSCalendarDate *)dateForJulianNumber:(long)_jn; - (long)julianNumber; - (NSCalendarDate *)firstDayOfMonth; - (NSCalendarDate *)lastDayOfMonth; - (NSCalendarDate *)mondayOfWeek; - (NSCalendarDate *)beginOfDay; - (NSCalendarDate *)endOfDay; - (int)numberOfDaysInMonth; - (BOOL)isDateOnSameDay:(NSCalendarDate *)_date; - (BOOL)isDateInSameWeek:(NSCalendarDate *)_date; - (BOOL)isInLeapYear; - (BOOL)isToday; - (NSCalendarDate *)yesterday; - (NSCalendarDate *)tomorrow; - (BOOL)isForenoon; - (BOOL)isAfternoon; - (NSCalendarDate *)nextYear; - (NSCalendarDate *)lastYear; /* returns a date on the same day with the specified time */ - (NSCalendarDate *)hour:(int)_hour minute:(int)_minute second:(int)_second; - (NSCalendarDate *)hour:(int)_hour minute:(int)_minute; /* applies the following modifications: if year >= 70 && year < 135 year = 1900 + year elif year >= 0 && year < 70 year = 2000 + year */ - (NSCalendarDate *)y2kDate; /* adding years, months and days while *keeping* the clock time, eg: d1 = [NSCalendarDate dateWithYear:2000 month:2 day:15 hour:12 minute:0 second:0 timeZone:@"MET"]; d2 = [d1 dateByAddingYear:0 month:3 day:0]; [d2 hourOfDay] will be '15' though the timezone changed from MET to MET-DST. -dateByAddingYears:months:days:hours:minutes:seconds: which can be found in NSCalendarDate will not keep the clock time (the time will be adjusted in the new DST timezone */ - (NSCalendarDate *)dateByAddingYears:(int)_years months:(int)_months days:(int)_days; /* calculate easter ... */ - (NSCalendarDate *)easterOfYear; @end @interface NSCalendarDate(CalMatrix) - (NSArray *)calendarMatrixWithStartDayOfWeek:(short)_caldow onlyCurrentMonth:(BOOL)_onlyThisMonth; @end @interface NSString(FuzzyDayOfWeek) - (int)dayOfWeekInEnglishOrGerman; @end #endif /* __NGExtensions_NSCalendarDate_misc_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/EOQualifierGrouping.h0000644000000000000000000000163615004363604023226 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _EOQualifierGrouping_h__ #define _EOQualifierGrouping_h__ #include #endif /* _EOQualifierGrouping_h__ */ SOPE/sope-core/NGExtensions/NGExtensions/EOKeyGrouping.h0000644000000000000000000000161415004363604022031 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _EOKeyGrouping_h__ #define _EOKeyGrouping_h__ #include #endif /* _EOKeyGrouping_h__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGRuleAssignment.h0000644000000000000000000000346315004363604022533 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGRuleEngine_NGRuleAssignment_H__ #define __NGRuleEngine_NGRuleAssignment_H__ #import #import /* NGRuleAssignment Assignments are the right-hand side of a rule in the rule system, if a rule is selected by qualifier and priority the assignment is the "thing" which is executed. NGRuleKeyAssignment Special case of NGRuleAssignment which evaluates the "value" as a keypath relative to the context. */ @class NSString; @interface NGRuleAssignment : NSObject < EOKeyValueArchiving > { NSString *keyPath; id value; } + (id)assignmentWithKeyPath:(NSString *)_kp value:(id)_value; - (id)initWithKeyPath:(NSString *)_kp value:(id)_value; /* accessors */ - (void)setKeyPath:(NSString *)_kp; - (NSString *)keyPath; - (void)setValue:(id)_value; - (id)value; /* operations */ - (BOOL)isCandidateForKey:(NSString *)_key; - (id)fireInContext:(id)_ctx; @end @interface NGRuleKeyAssignment : NGRuleAssignment { } @end #endif /* __NGRuleEngine_NGRuleAssignment_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGQuotedPrintableCoding.h0000644000000000000000000000527515004363604024024 0ustar rootroot/* Copyright (C) 2000-2006 SKYRIX Software AG Copyright (C) 2006 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGQuotedPrintableCoding_H__ #define __NGExtensions_NGQuotedPrintableCoding_H__ #import #import #include /* Quoted Printable encoder/decoder As specified in RFC 822 / 2045 / 2047. Note that 2045 and 2047 specify different variants (Q vs content-transfer-encoding) TODO: explain what it does. It doesn't seem to decode a full line like "=?iso-8859-1?q?Yannick=20DAmboise?=" but only turns "=20D" style encodings to their charcode. Note: apparently sope-mime contains a category on NSData which provides a method to decode the full value: -decodeQuotedPrintableValueOfMIMEHeaderField: (NGMimeMessageParser) */ @interface NSData(QuotedPrintableCoding) /* Decode a quoted printable encoded data. Returns nil if decoding failed. The first method does the RFC 2047 variant, the second RFC 2045 (w/o _ replacing) */ - (NSData *)dataByDecodingQuotedPrintable; - (NSData *)dataByDecodingQuotedPrintableTransferEncoding; /* Decode data in quoted printable encoding. Returns nil if encoding failed. */ - (NSData *)dataByEncodingQuotedPrintable; @end /* Note: you should avoid NSString methods for QP, its defined on byte level */ @interface NSString(QuotedPrintableCoding) - (NSString *)stringByDecodingQuotedPrintable; - (NSString *)stringByEncodingQuotedPrintable; @end NGExtensions_EXPORT int NGEncodeQuotedPrintable(const char *_src, unsigned _srcLen, char *_dest, unsigned _destLen); NGExtensions_EXPORT int NGDecodeQuotedPrintable(const char *_src, unsigned _srcLen, char *_dest, unsigned _destLen); NGExtensions_EXPORT int NGDecodeQuotedPrintableX(const char *_src, unsigned _srcLen, char *_dest, unsigned _destLen, BOOL _replaceUnderline); #endif /* __NGExtensions_NGQuotedPrintableCoding_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSString+Formatting.h0000644000000000000000000000467715004363604023173 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSString_Formatting_H__ #define __NGExtensions_NSString_Formatting_H__ #import // category @interface NSString(XSFormatting) + (id)stringWithCFormat:(const char *)_format arguments:(va_list)_ap; + (id)stringWithCFormat:(const char *)_format, ...; @end @interface NSMutableString(XSFormatting) - (void)appendFormat:(NSString *)_format arguments:(va_list)_ap; - (void)appendFormat:(NSString *)_format, ...; @end // C support functions static inline int xs_vsnprintf(char *_str, size_t max, const char *fmt, va_list _ap) { NSString *obj = [NSString stringWithCFormat:_str arguments:_ap]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 [obj getCString:_str maxLength:(max - 1) encoding:[NSString defaultCStringEncoding]]; return strlen(_str); #else [obj getCString:_str maxLength:(max - 1)]; return [obj cStringLength]; // return the len the string would have consumed #endif } static inline int xs_vsprintf (char *_str, const char *_fmt, va_list _ap) { NSString *obj = [NSString stringWithCFormat:_str arguments:_ap]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 [obj getCString:_str maxLength:65535 /* no limit ... */ encoding:[NSString defaultCStringEncoding]]; return strlen(_str); #else [obj getCString:_str]; return [obj cStringLength]; // return the length of the string #endif } /* Could use formats .. // __attribute__ ((format (printf, 2, 3))); // __attribute__ ((format (printf, 3, 4))); */ int xs_sprintf (char *str, const char *format, ...); int xs_snprintf(char *str, size_t size, const char *format, ...); #endif /* __NGExtensions_NSString_Formatting_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSEnumerator+misc.h0000644000000000000000000000232615004363604022654 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSEnumerator_misc_H__ #define __NGExtensions_NSEnumerator_misc_H__ #import @class NSEnumerator, EOQualifier; @interface NSEnumerator(misc) - (NSEnumerator *)filterWithQualifier:(EOQualifier *)_qualifier; - (NSEnumerator *)filterWithQualifierString:(NSString *)_q; - (NSEnumerator *)filterWithSelector:(SEL)_selector withObject:(id)_argument; @end #endif /* __NGExtensions_NSEnumerator_misc_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGMemoryAllocation.h0000644000000000000000000000216215004363604023044 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGMemoryAllocation_H__ #define __NGExtensions_NGMemoryAllocation_H__ #if !(__GNU_LIBOBJC__ >= 20100911) #include #endif #include #define NGMalloc malloc #define NGMallocAtomic malloc #define NGFree free #define NGRealloc realloc #endif /* __NGExtensions_NGMemoryAllocation_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/EOQualifier+plist.h0000644000000000000000000000213015004363604022630 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOQualifier_plist_h__ #define __EOQualifier_plist_h__ #import @class NSDictionary, NSString; @interface EOQualifier(plist) - (id)initWithDictionary:(NSDictionary *)_dictionary; - (id)initWithString:(NSString *)_string; - (id)initWithPropertyList:(id)_plist owner:(id)_owner; @end #endif SOPE/sope-core/NGExtensions/NGExtensions/NGCalendarDateRange.h0000644000000000000000000000425515004363604023057 0ustar rootroot/* Copyright (C) 2004 Marcus Mueller This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGCalendarDateRange_H_ #define __NGExtensions_NGCalendarDateRange_H_ #import #import #import @class NSString, NSCalendarDate; @interface NGCalendarDateRange : NSObject { NSCalendarDate *startDate; NSCalendarDate *endDate; } + (id)calendarDateRangeWithStartDate:(NSCalendarDate *)_start endDate:(NSCalendarDate *)_end; - (id)initWithStartDate:(NSCalendarDate *)_start endDate:(NSCalendarDate *)_end; /* accessors */ - (NSCalendarDate *)startDate; - (NSCalendarDate *)endDate; /* comparison */ - (NSComparisonResult)compare:(NGCalendarDateRange *)other; /* operations */ - (NGCalendarDateRange *)intersectionDateRange:(NGCalendarDateRange *)other; - (NGCalendarDateRange *)unionDateRange:(NGCalendarDateRange *)other; - (BOOL)doesIntersectWithDateRange:(NGCalendarDateRange *)_other; - (BOOL)containsDate:(NSCalendarDate *)date; - (BOOL)containsDateRange:(NGCalendarDateRange *)_range; - (NSTimeInterval)duration; @end @interface NSArray(NGCalendarDateRanges) - (NSArray *)arrayByCreatingDateRangesFromObjectsWithStartDateKey:(NSString *)s andEndDateKey:(NSString *)e; - (NSUInteger)indexOfFirstIntersectingDateRange:(NGCalendarDateRange *)_range; - (BOOL)dateRangeArrayContainsDate:(NSCalendarDate *)_date; - (NSArray *)arrayByCompactingContainedDateRanges; @end #endif /* __NGExtensions_NGCalendarDateRange_H_ */ SOPE/sope-core/NGExtensions/NGExtensions/NGStack.h0000644000000000000000000000417015004363604020634 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGStack_H__ #define __NGExtensions_NGStack_H__ #import #import #import @class NSArray; @protocol NGStack < NSObject > // state - (NSUInteger)stackPointer; - (NSUInteger)count; - (BOOL)isEmpty; // operations - (void)push:(id)_obj; - (id)pop; - (void)clear; // elements - (id)elementAtTop; - (NSEnumerator *)topDownEnumerator; - (NSEnumerator *)bottomUpEnumerator; @end @interface NGStack : NSObject < NGStack, NSCoding, NSCopying > { @protected unsigned int stackPointer; unsigned int capacity; id *stack; } + (id)stackWithCapacity:(NSUInteger)_capacity; + (id)stack; + (id)stackWithArray:(NSArray *)_array; - (id)init; - (id)initWithCapacity:(NSUInteger)_capacity; // designated initializer - (id)initWithArray:(NSArray *)_array; // state - (NSUInteger)capacity; - (NSUInteger)stackPointer; - (NSUInteger)count; - (BOOL)isEmpty; // elements - (id)elementAtTop; - (id)elementAtBottom; - (NSEnumerator *)topDownEnumerator; - (NSEnumerator *)bottomUpEnumerator; // operations - (void)push:(id)_obj; - (id)pop; - (void)clear; // description - (NSArray *)toArray; // array representation, bottom element first @end @interface NGStackException : NSException @end @interface NSMutableArray(Stack) < NGStack > @end #endif /* __NGExtensions_NGStack_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGRuleModel.h0000644000000000000000000000365115004363604021462 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGRuleEngine_NGRuleModel_H__ #define __NGRuleEngine_NGRuleModel_H__ #import #import /* NGRuleModel A rule model is a specialized sequence of rules. */ // TODO: need some method to join two models (two allow one model being // configured as a default but still have fallback rules in another) @class NSArray, NSMutableArray, NSURL; @class NGRule; @interface NGRuleModel : NSObject < EOKeyValueArchiving > { NSMutableArray *rules; } + (id)ruleModelWithPropertyList:(id)_plist; + (id)ruleModelWithContentsOfUserDefault:(NSString *)_defName; - (id)init; - (id)initWithRules:(NSArray *)_rules; - (id)initWithPropertyList:(id)_plist; - (id)initWithContentsOfFile:(NSString *)_path; - (id)initWithContentsOfUserDefault:(NSString *)_defaultName; - (id)initWithKeyValueArchiveAtURL:(NSURL *)_url; /* accessors */ - (void)setRules:(NSArray *)_rules; - (NSArray *)rules; - (void)addRule:(NGRule *)_rule; - (void)removeRule:(NGRule *)_rule; - (void)addRules:(NSArray *)_rules; /* operations */ - (NSArray *)candidateRulesForKey:(NSString *)_key; @end #endif /* __NGRuleEngine_NGRuleModel_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSObject+Logs.h0000644000000000000000000000356715004363604021722 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSObject_Logs_H__ #define __NGExtensions_NSObject_Logs_H__ #import #import @interface NSObject(NGLogs) /* default loggers for object */ - (id)logger; - (id)debugLogger; /* "end user" methods, variable argument logging methods .. */ - (void)debugWithFormat:(NSString *)_fmt, ...; - (void)logWithFormat:(NSString *)_fmt, ...; - (void)warnWithFormat:(NSString *)_fmt, ...; - (void)errorWithFormat:(NSString *)_fmt, ...; - (void)fatalWithFormat:(NSString *)_fmt, ...; /* prefix, override that, to make a special logging prefix */ - (NSString *)loggingPrefix; /* says whether debugging is enabled for object ... */ - (BOOL)isDebuggingEnabled; /*"designated" logging methods */ - (void)debugWithFormat:(NSString *)_fmt arguments:(va_list)_va; - (void)logWithFormat:(NSString *)_fmt arguments:(va_list)_va; - (void)warnWithFormat:(NSString *)_fmt arguments:(va_list)_va; - (void)errorWithFormat:(NSString *)_fmt arguments:(va_list)_va; - (void)fatalWithFormat:(NSString *)_fmt arguments:(va_list)_va; @end #endif /* __NGExtensions_NSObject_Logs_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGLogEvent.h0000644000000000000000000000274115004363604021314 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGLogEvent_H_ #define __NGExtensions_NGLogEvent_H_ /* NGLogEvent Instances of this class encapsulate log events, retaining all vital information associated with it. Log events are generally passed on to log appenders for further treatment. */ #import #import #include @class NSString, NSCalendarDate; @interface NGLogEvent : NSObject { NSString *msg; NGLogLevel level; NSTimeInterval date; } - (id)initWithLevel:(NGLogLevel)_level message:(NSString *)_msg; /* accessors */ - (NGLogLevel)level; - (NSString *)message; - (NSCalendarDate *)date; @end #endif /* __NGExtensions_NGLogEvent_H_ */ SOPE/sope-core/NGExtensions/NGExtensions/EOQualifier+CtxEval.h0000644000000000000000000000352615004363604023055 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_EOQualifier_ContextEvaluation_H__ #define __NGExtensions_EOQualifier_ContextEvaluation_H__ #import #import @interface EOQualifier(ContextEvaluation) - (BOOL)evaluateWithObject:(id)_object context:(id)_context; @end @interface NSArray(ContextEvaluation) - (NSArray *)filteredArrayUsingQualifier:(EOQualifier *)_qualifier context:(id)_context; @end @interface NSObject(ContextQualifierComparisons) - (BOOL)isEqualTo:(id)_object inContext:(id)_context; - (BOOL)isNotEqualTo:(id)_object inContext:(id)_context; - (BOOL)isLessThan:(id)_object inContext:(id)_context; - (BOOL)isGreaterThan:(id)_object inContext:(id)_context; - (BOOL)isLessThanOrEqualTo:(id)_object inContext:(id)_context; - (BOOL)isGreaterThanOrEqualTo:(id)_object inContext:(id)_context; - (BOOL)doesContain:(id)_object inContext:(id)_context; - (BOOL)isLike:(NSString *)_object inContext:(id)_context; - (BOOL)isCaseInsensitiveLike:(NSString *)_object inContext:(id)_context; @end #endif /* __NGExtensions_EOQualifier_ContextEvaluation_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/IndexFunc.h0000644000000000000000000000223015004363604021220 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_IndexFunc_H__ #define __NGExtensions_IndexFunc_H__ #if defined(WIN32) && !defined(__CYGWIN32__) static inline const char *index(register const char *_str, register unsigned char _c) { if (_str == NULL) return NULL; while ((*_str != '\0') && (*_str != _c)) _str++; if (*_str == _c) return _str; return NULL; } #endif #endif /* __NGExtensions_IndexFunc_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/AutoDefines.h0000644000000000000000000000354715004363604021557 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_AutoDefines_H__ #define __NGExtensions_AutoDefines_H__ // TODO: can we remove that? #if defined(__MINGW32__) # define WITH_OPENSTEP 0 # define GNUSTEP 1 #elif defined(__CYGWIN32__) # define WITH_OPENSTEP 0 # ifndef GNUSTEP # define GNUSTEP 1 # endif #elif defined(NeXT) || defined(WIN32) # define WITH_OPENSTEP 1 # define GNUSTEP 0 # ifndef NeXT_RUNTIME # define NeXT_RUNTIME 1 # endif #elif defined(__APPLE__) # ifndef WITH_OPENSTEP # define WITH_OPENSTEP 1 # endif # if !GNU_RUNTIME # ifndef NeXT_RUNTIME # define NeXT_RUNTIME 1 # endif # ifndef APPLE_RUNTIME # define APPLE_RUNTIME 1 # endif # endif # if !GNUSTEP_BASE_LIBRARY && !LIB_FOUNDATION_LIBRARY # ifndef COCOA_Foundation_LIBRARY # define COCOA_Foundation_LIBRARY 1 # endif # ifndef NeXT_Foundation_LIBRARY # define NeXT_Foundation_LIBRARY 1 # endif # ifndef APPLE_Foundation_LIBRARY # define APPLE_Foundation_LIBRARY 1 # endif # endif #else # define WITH_OPENSTEP 0 # define GNUSTEP 1 #endif #endif /* __NGExtensions_AutoDefines_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGLogEventFormatter.h0000644000000000000000000000447415004363604023205 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGLogEventFormatter_H_ #define __NGExtensions_NGLogEventFormatter_H_ /* NGLogEventFormatter Suits as factory and base class for all custom log event formatters. Its purpose is to offer a lightweight interface to transform NGLogEvent objects into string representations. NGLogEventFormatter honours the following user default keys: User Default key Function ---------------------------------------------------------------------------- NGLogDefaultLogEventFormatterClass The formatter class to use if no class information was provided by the configuration. The fallback is "NGLogEventFormatter". The following keys in the configuration dictionary will be recognized: Key Function ---------------------------------------------------------------------------- "Class" The class to use for instance creation. If no class name is provided, the fallback path described above will be taken. */ #import #include @class NSDictionary, NGLogEvent; @interface NGLogEventFormatter : NSObject { } + (id)logEventFormatterFromConfig:(NSDictionary *)_config; - (id)initWithConfig:(NSDictionary *)_config; /* formatting */ - (NSString *)formattedEvent:(NGLogEvent *)_event; @end #endif /* __NGExtensions_NGLogEventFormatter_H_ */ SOPE/sope-core/NGExtensions/NGExtensions/NSProcessInfo+misc.h0000644000000000000000000000316315004363604022765 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NSProcessInfo_misc_H__ #define __NSProcessInfo_misc_H__ #import @interface NSProcessInfo(misc) /* arguments */ - (NSArray *)argumentsWithoutDefaults; /* create temp file name */ - (NSString *)temporaryFileName:(NSString *)_prefix; - (NSString *)temporaryFileName; /* return process-id (pid on Unix) */ - (id)processId; /* return path to proc directory for this process */ - (NSString *)procDirectoryPathForProcess; /* returns contents of /proc/pid/status */ - (NSDictionary *)procStatusDictionary; /* returns contents of /proc/pid/stat mapped as in 'man 5 proc' */ - (NSDictionary *)procStatDictionary; /* wrappers */ - (unsigned long long)virtualMemorySize; - (unsigned long long)residentSetSize; - (unsigned int)residentSetSizeLimit; - (unsigned int)fileDescriptorCount; @end #endif /* __NSProcessInfo_misc_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGRuleEngine.h0000644000000000000000000000165115004363604021625 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include SOPE/sope-core/NGExtensions/NGExtensions/NGBaseTypes.h0000644000000000000000000000264615004363604021474 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGBaseTypes_H__ #define __NGExtensions_NGBaseTypes_H__ #import #import #import static inline NSNumber *shortObj(short _s) { return [NSNumber numberWithShort:_s]; } static inline NSNumber *intObj(int _i) { return [NSNumber numberWithInt:_i]; } static inline NSNumber *floatObj(float _f) { return [NSNumber numberWithFloat:_f]; } static inline NSNumber *doubleObj(double _d) { return [NSNumber numberWithDouble:_d]; } static inline NSString *cstrObj(const char *_c) { return [NSString stringWithCString:_c]; } #endif /* __NGExtensions_NGBaseTypes_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSString+misc.h0000644000000000000000000000713315004363604022002 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSString_misc_H__ #define __NGExtensions_NSString_misc_H__ #import @class NSSet, NSDictionary, NSString; @interface NSObject(StringBindings) - (NSString *)valueForStringBinding:(NSString *)_key; @end @interface NSString(misc) /* Replaces keys, which enclosed in '$', with values from _bindings. The values are retrieved using the '-valueForStringBinding:' method which per default use -valueForKey: and -objectForKey: for NSDictionary objects. For using of $ escape it with $$. Example: source: @"du da blah $var$ doof" dest = [source stringByReplacingVariablesWithBindings: @{ var = @"dummy"; }]; => dest: @"du da blah dummy doof" */ - (NSString *)stringByReplacingVariablesWithBindings:(id)_bindings; /* If there are variables with no binding, _unkown is used instead. If _unkown is nil and there are unknown bindings, an exception will be thrown. */ - (NSString *)stringByReplacingVariablesWithBindings:(id)_bindings stringForUnknownBindings:(NSString *)_unknown; /* Returns all binding variables. ('aaa $doof$ $bla$' --> (doof, bla) ) */ - (NSSet *)bindingVariables; @end @interface NSString(FilePathVersioningMethods) /* "/PATH/file.txt;1" */ - (NSString *)pathVersion; - (NSString *)stringByDeletingPathVersion; - (NSString *)stringByAppendingPathVersion:(NSString *)_version; @end /* NSString(FilePathMethodsVersioning) */ @interface NSString(URLEscaping) /* These functions encode/decode HTTP style URL paths, which can escape spaces and special chars. Chars are escaped using the '%' hex-notation: Encode: 'Hello World' => 'Hello%20World' '& ?' => '%26%20%3F' */ - (BOOL)containsURLEscapeCharacters; - (NSString *)stringByUnescapingURL; - (NSString *)stringByEscapingURL; @end @interface NSString(HTMLEscaping) - (NSString *)stringByEscapingHTMLString; - (NSString *)stringByEscapingHTMLAttributeValue; @end @interface NSString(XMLEscaping) - (NSString *)stringByEscapingXMLString; - (NSString *)stringByEscapingXMLAttributeValue; /* The following methods work in "fully-qualified XML names", in this format: '{namespace}name' */ - (BOOL)xmlIsFQN; - (NSString *)xmlNamespaceURI; - (NSString *)xmlLocalName; @end @interface NSString(NGScanning) /* this methods search for a string, while skipping quotes, eg: [@"abc '++' hello" rangeOfString:@"++" skipQuotes:@"\"'"]; would not return a result ! */ - (NSRange)rangeOfString:(NSString *)_s skipQuotes:(NSString *)_quotes escapedByChar:(unichar)_escape; - (NSRange)rangeOfString:(NSString *)_s skipQuotes:(NSString *)_quotes; @end @interface NSString(MailQuoting) - (NSString *)stringByApplyingMailQuoting; @end @interface NSString(HeaderCapitalization) - (NSString *) asCapitalizedHeader; @end #endif /* __NGExtensions_NSString_misc_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGBundleManager.h0000644000000000000000000001455515004363604022303 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGBundleManager_H__ #define __NGExtensions_NGBundleManager_H__ #import #import #import #include @class NSString, NSArray, NSMutableArray, NSDictionary, NSMutableSet; @class EOQualifier; /* NGBundleManager NGBundleManager is a class similar to a Java class loader. It searches for dynamically loadable bundles in a specified path set. The default bundle search path is: 1. bundles contained in the main-bundle 2. pathes specified by the 'NGBundlePath' user default 3. pathes specified by the 'NGBundlePath' environment variable Bundles managed by NGBundleManager can specify load-requirements, this is done via the 'bundle-info.plist' file contained at the root of the bundle directory. The file is a property list file and can specify required and provided classes. Example bundle-info.plist: { bundleHandler = "MyBundleManager"; provides = { classes = ( { name = MyClass; } ); }; requires = { bundleManagerVersion = 1; bundles = ( { name = Foundation; type = framework; } ); classes = ( { name = NSObject; exact-version = 1; } ); }; } */ NGExtensions_EXPORT NSString *NGBundleWasLoadedNotificationName; @class NGBundleManager; typedef BOOL (*NGBundleResourceSelector)(NSString *_resourceName, NSString *_resourceType, NSString *_path, NSDictionary *_resourceConfig, NGBundleManager *_bundleManager, void *_context); @interface NGBundleManager : NSObject { @private NSMutableArray *bundleSearchPaths; NSMapTable *pathToBundle; NSMapTable *pathToBundleInfo; NSMapTable *nameToBundle; /* bundles loaded by the manager (NSBundle->BundleManager) */ NSMapTable *loadedBundles; /* the following are maintained using NSBundleDidLoadNotification .. */ NSMapTable *classToBundle; NSMapTable *classNameToBundle; NSMapTable *categoryNameToBundle; // transient NSMutableSet *loadingBundles; } + (id)defaultBundleManager; /* accessors */ - (void)setBundleSearchPaths:(NSArray *)_paths; - (NSArray *)bundleSearchPaths; /* bundle access */ - (NSBundle *)bundleWithName:(NSString *)name type:(NSString *)_type; - (NSBundle *)bundleWithName:(NSString *)name; // type=='bundle' - (NSBundle *)bundleForClassNamed:(NSString *)aClassName; - (NSBundle *)bundleForClass:(Class)aClass; - (NSBundle *)bundleWithPath:(NSString *)path; /* dependencies */ /* returns the names of the bundles required by the bundle */ - (NSArray *)bundlesRequiredByBundle:(NSBundle *)_bundle; /* returns the names of the classes provided by the bundle */ - (NSArray *)classesProvidedByBundle:(NSBundle *)_bundle; /* returns the names of the classes required by the bundle */ - (NSArray *)classesRequiredByBundle:(NSBundle *)_bundle; /* loading */ - (id)loadBundle:(NSBundle *)_bundle; /* bundle manager object */ - (id)principalObjectOfBundle:(NSBundle *)_bundle; /* resources */ - (NSDictionary *)configForResource:(id)_resource ofType:(NSString *)_type providedByBundle:(NSBundle *)_bundle; - (NSBundle *)bundleProvidingResource:(id)_resourceName ofType:(NSString *)_resourceType; - (NSArray *)bundlesProvidingResource:(id)_resourceName ofType:(NSString *)_resourceType; - (NSBundle *)bundleProvidingResourceOfType:(NSString *)_resourceType matchingQualifier:(EOQualifier *)_qual; - (NSBundle *)bundlesProvidingResourcesOfType:(NSString *)_resourceType matchingQualifier:(EOQualifier *)_qual; /* This returns an array of NSDictionaries describing the provided resources. */ - (NSArray *)providedResourcesOfType:(NSString *)_resourceType; - (NSString *)pathForBundleProvidingResource:(id)_resourceName ofType:(NSString *)_type resourceSelector:(NGBundleResourceSelector)_selector context:(void *)_context; @end /* NGBundleManager */ @interface NSBundle(NGLanguageResourceExtensions) - (NSString *)pathForResource:(NSString *)_name ofType:(NSString *)_ext inDirectory:(NSString *)_directory languages:(NSArray *)_languages; - (NSString *)pathForResource:(NSString *)_name ofType:(NSString *)_ext languages:(NSArray *)_languages; @end /* NSBundle(NGLanguageResourceExtensions) */ @interface NSBundle(NGBundleManagerExtensions) /* Returns the object managing the bundle (might be the principal class) */ - (id)principalObject; - (NSArray *)providedResourcesOfType:(NSString *)_resourceType; /* Returns the name of the bundle */ - (NSString *)bundleName; /* Returns the type of the bundle */ - (NSString *)bundleType; /* Returns the names of the classes provided by the bundle */ - (NSArray *)providedClasses; /* Returns the names of the classes required by the bundle */ - (NSArray *)requiredClasses; /* Returns the names of other bundles required for loading this bundle */ - (NSArray *)requiredBundles; /* Return a NSDictionary with bundle-info configuration of the specified rsrc */ - (NSDictionary *)configForResource:(id)_resource ofType:(NSString *)_type; @end /* NSBundle(NGBundleManagerExtensions) */ @interface NSObject(BundleManager) - (id)initForBundle:(NSBundle *)_bundle bundleManager:(NGBundleManager *)_mng; /* This method is invoked if the bundle was successfully loaded. */ - (void)bundleManager:(NGBundleManager *)_manager didLoadBundle:(NSBundle *)_bundle; @end /* NSObject(BundleManager) */ @interface NGBundle : NSBundle @end #endif SOPE/sope-core/NGExtensions/NGExtensions/NGLogAppender.h0000644000000000000000000000477015004363604021775 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGLogAppender_H_ #define __NGExtensions_NGLogAppender_H_ /* NGLogAppender Abstract superclass for all log appenders. NGLogAppender honours the following user default keys: User Default key Function ---------------------------------------------------------------------------- NGLogDefaultAppenderClass The appender class to use if no class information was provided by the configuration. The fallback is "NGLogStderrAppender". The following keys in the configuration dictionary will be recognized: Key Function ---------------------------------------------------------------------------- "Class" The class to use for instance creation. If no class name is provided, the fallback path described above will be taken. "Formatter" Dictionary suitable as configuration provided to NGLogEventFormatters's factory method. Please see NGLogEventFormatteer.h for further explanation. */ #import #include @class NSDictionary, NGLogEvent, NGLogEventFormatter; @interface NGLogAppender : NSObject { NGLogEventFormatter *formatter; } /* factory method */ + (id)logAppenderFromConfig:(NSDictionary *)_config; /* designated initializer */ - (id)initWithConfig:(NSDictionary *)_config; /* subclass responsibility */ - (void)appendLogEvent:(NGLogEvent *)_event; - (NSString *)formattedEvent:(NGLogEvent *)_event; @end #endif /* __NGExtensions_NGLogAppender_H_ */ SOPE/sope-core/NGExtensions/NGExtensions/NGDirectoryEnumerator.h0000644000000000000000000000370115004363604023574 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGDirectoryEnumerator_H__ #define __NGDirectoryEnumerator_H__ #import #include /* A class which is compatible to NSDirectoryEnumerator, but works with any object conforming to the filemanager interface. */ @class NSString, NSMutableArray, NSFileManager, NSDictionary; @interface NGDirectoryEnumerator : NSEnumerator { id fileManager; NSMutableArray *enumStack; NSMutableArray *pathStack; NSString *currentFileName; NSString *currentFilePath; NSString *topPath; struct { BOOL isRecursive:1; BOOL isFollowing:1; } flags; } - (id)initWithFileManager:(id)_fm directoryPath:(NSString *)path recurseIntoSubdirectories:(BOOL)recurse followSymlinks:(BOOL)follow prefixFiles:(BOOL)prefix; - (id)initWithFileManager:(id)_fm; - (id)initWithFileManager:(id)_fm directoryPath:(NSString *)_path; - (id)fileManager; - (NSDictionary *)directoryAttributes; - (NSDictionary *)fileAttributes; - (void)skipDescendents; @end #endif /* __NGDirectoryEnumerator_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGMerging.h0000644000000000000000000000311615004363604021156 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGMerging_H__ #define __NGExtensions_NGMerging_H__ #import #import #import #import @interface NSObject(NGMerging) - (BOOL)canMergeWithObject:(id)_object; - (id)mergeWithObject:(id)_object zone:(NSZone *)_zone; - (id)mergeWithObject:(id)_object; @end /* dictionaries merge only with other dictionaries */ @interface NSDictionary(NGMerging) - (id)mergeWithDictionary:(NSDictionary *)_object zone:(NSZone *)_zone; @end /* arrays merge with any objects responding to -objectEnumerator */ @interface NSArray(NGMerging) - (id)mergeWithArray:(NSArray *)_object zone:(NSZone *)_zone; - (id)mergeWithEnumeration:(NSEnumerator *)_object zone:(NSZone *)_zone; @end #endif /* __NGExtensions_NGMerging_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGExtensionsDecls.h0000644000000000000000000000241415004363604022700 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGExtensionsDecls_H__ #define __NGExtensions_NGExtensionsDecls_H__ #if BUILD_libNGExtensions_DLL # define NGExtensions_EXPORT __declspec(dllexport) # define NGExtensions_DECLARE __declspec(dllexport) #elif libNGExtensions_ISDLL # define NGExtensions_EXPORT extern __declspec(dllimport) # define NGExtensions_DECLARE extern __declspec(dllimport) #else # define NGExtensions_EXPORT extern # define NGExtensions_DECLARE #endif #endif /* __NGExtensions_NGExtensionsDecls_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGExtensions.h0000644000000000000000000000534715004363604021735 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_H__ #define __NGExtensions_H__ #include #if defined(LIB_FOUNDATION_LIBRARY) # define NoZone nil #else # define NoZone NULL #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // kit class @interface NGExtensions : NSObject @end // linking .. #define LINK_NGExtensions \ void __link_NGExtensions(void) { \ [NGExtensions self]; \ __link_NGExtensions(); \ } #endif /* __NGExtensions_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSString+Encoding.h0000644000000000000000000000246015004363604022573 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSString_Encoding_H__ #define __NGExtensions_NSString_Encoding_H__ #import /* NSString(Encoding) TODO: handler is currently fixed to iconv, should allow a registry of handlers */ @interface NSString(Encoding) + (NSString *)stringWithData:(NSData *)_da usingEncodingNamed:(NSString *)_enc; - (NSData *)dataUsingEncodingNamed:(NSString *)_encoding; + (NSStringEncoding)stringEncodingForEncodingNamed:(NSString *)encoding; @end #endif /* __NGExtensions_NSString_Encoding_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/EOFetchSpecification+plist.h0000644000000000000000000000217415004363604024451 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOFetchSpecification_plist_h__ #define __EOFetchSpecification_plist_h__ #import @class NSDictionary, NSString; @interface EOFetchSpecification(plist) - (id)initWithDictionary:(NSDictionary *)_dictionary; - (id)initWithString:(NSString *)_string; - (id)initWithPropertyList:(id)_plist owner:(id)_owner; @end #endif SOPE/sope-core/NGExtensions/NGExtensions/NGResourceLocator.h0000644000000000000000000000737615004363604022715 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGResourceLocator_H__ #define __NGExtensions_NGResourceLocator_H__ #import /* NGResourceLocator This class can be used by libraries to lookup resources in either the GNUstep hierarchy or in FHS locations (/usr/local etc). The pathes given in are relative to the respective root, eg: "Library/Models" and "share/mytool/models". */ @class NSString, NSArray, NSFileManager, NSMutableDictionary; @interface NGResourceLocator : NSObject { NSString *gsSubPath; NSString *fhsSubPath; NSFileManager *fileManager; NSArray *searchPathes; NSMutableDictionary *nameToPathCache; struct { int cacheSearchPathes:1; int cachePathHits:1; int cachePathMisses:1; int reserved:29; } flags; } /* The 'GNUstepPath' is a string describing the required path. This * is the relative location of the path in a standard GNUstep * hierarchy when a standard GNUstep hierarchy is being used; but if * gnustep-base (which supports arbitrary filesystem layouts) is being * used, the path is heuristically mapped to the standard paths * accepted by NSSearchPathForDirectoriesInDomains using the following * logic: * * "Library/WebApplications" --> GSWebApplicationsDirectory * "Library/Libraries" --> GSLibrariesDirectory * "Tools" --> GSToolsDirectory * "Tools/Admin" --> GSAdminToolsDirectory * "Applications" --> GSApplicationsDirectory * "Applications/Admin" --> GSAdminApplicationsDirectory * "Library/xxx" --> NSLibraryDirectory/xxx * "yyy" --> NSLibraryDirectory/yyy * * In the last two cases 'xxx' and 'yyy' are arbitrary strings/paths * that don't match anything else. Eg, if you create an * NGResourceLocators to look up files in "Library/Resources" you will * get one that looks them up in NSLibraryDirectory/Resources (which * means a list of directories containing * GNUSTEP_USER_LIBRARY/Resources, GNUSTEP_LOCAL_LIBRARY/Resources, * GNUSTEP_NETWORK_LIBRARY/Resources, * GNUSTEP_SYSTEM_LIBRARY/Resources). */ + (id)resourceLocatorForGNUstepPath:(NSString *)_path fhsPath:(NSString *)_fhs; - (id)initWithGNUstepPath:(NSString *)_path fhsPath:(NSString *)_fhs; /* resource pathes */ /* It's not a good idea to access these directly if you want portable * code. More logical to use directly the 'operations' lookup methods * below which encapsulate all the internal filesystem details. */ - (NSArray *)gsRootPathes; /* GNUSTEP_PATHPREFIX_LIST or MacOSX */ - (NSArray *)fhsRootPathes; - (NSArray *)searchPathes; /* operations */ /* These are public and work across all types of filesystems, it's how you find resources. */ - (NSString *)lookupFileWithName:(NSString *)_name; - (NSString *)lookupFileWithName:(NSString *)_name extension:(NSString *)_ext; - (NSArray *)lookupAllFilesWithExtension:(NSString *)_ext doReturnFullPath:(BOOL)_withPath; /* End public */ @end #endif /* __NGExtensions_NGResourceLocator_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGPropertyListParser.h0000644000000000000000000000544515004363604023432 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGPropertyListParser_H__ #define __NGExtensions_NGPropertyListParser_H__ #import @class NSString, NSArray, NSDictionary, NSData; /* The property list format is: Strings: char's without specials: 'hello', but not 'hel lo' or quoted string: '"hello world !" Arrays: '(' ')' or '(' element ( ',' element )* ')' Dicts: '{' ( dictEntry )* '}' dictEntry = property '=' property ';' ; Data: '<' data '>', eg: '< AABB 88CC 77a7 11 >' */ NSString *NGParseStringFromBuffer(const unsigned char *_buffer, unsigned _len); NSArray *NGParseArrayFromBuffer(const unsigned char *_buffer, unsigned _len); NSDictionary *NGParseDictionaryFromBuffer(const unsigned char *_buffer, unsigned _len); NSString *NGParseStringFromData(NSData *_data); NSArray *NGParseArrayFromData(NSData *_data); NSDictionary *NGParseDictionaryFromData(NSData *_data); NSString *NGParseStringFromString(NSString *_str); NSArray *NGParseArrayFromString(NSString *_str); NSDictionary *NGParseDictionaryFromString(NSString *_str); id NGParsePropertyListFromBuffer(const unsigned char *_buffer, unsigned _len); id NGParsePropertyListFromData(NSData *_data); id NGParsePropertyListFromString(NSString *_string); id NGParsePropertyListFromFile(NSString *_path); NSDictionary *NGParseStringsFromBuffer(const unsigned char *_buffer, unsigned _len); NSDictionary *NGParseStringsFromData(NSData *_data); NSDictionary *NGParseStringsFromString(NSString *_string); NSDictionary *NGParseStringsFromFile(NSString *_path); #import #import @interface NSArray(NGPropertyListParser) + (id)skyArrayWithContentsOfFile:(NSString *)_path; - (id)skyInitWithContentsOfFile:(NSString *)_path; @end @interface NSDictionary(NGPropertyListParser) + (id)skyDictionaryWithContentsOfFile:(NSString *)_path; - (id)skyInitWithContentsOfFile:(NSString *)_path; @end #endif /* __NGExtensions_NGPropertyListParser_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/EOCompoundDataSource.h0000644000000000000000000000262715004363604023332 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_EOCompoundDataSource_H__ #define __NGExtensions_EOCompoundDataSource_H__ #import @class NSArray; @class EOQualifier; @interface EOCompoundDataSource : EODataSource { NSArray *sources; EOQualifier *auxiliaryQualifier; NSArray *sortOrderings; } - (id)initWithDataSources:(NSArray *)_ds; /* accessors */ - (void)setSources:(NSArray *)_sources; - (NSArray *)sources; - (void)setAuxiliaryQualifier:(EOQualifier *)_q; - (EOQualifier *)auxiliaryQualifier; - (void)setSortOrderings:(NSArray *)_o; - (NSArray *)sortOrderings; @end #endif /* __NGExtensions_EOCompoundDataSource_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSBundle+misc.h0000644000000000000000000000215415004363604021743 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSBundle_misc_H__ #define __NGExtensions_NSBundle_misc_H__ #import @interface NSBundle (misc) - (NSString*)pathForResource:(NSString*)name ofType:(NSString*)ext inDirectory:(NSString*)directory forLocalizations:(NSArray*)localizationNames; @end #endif /* __NGExtensions_NSBundle_misc_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSDictionary+misc.h0000644000000000000000000000217515004363604022642 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSDictionary_misc_H__ #define __NGExtensions_NSDictionary_misc_H__ #import @interface NSDictionary(misc) - (NSDictionary *)dictionaryByExchangingKeysAndValues; @end @interface NSMutableDictionary(misc) - (void)removeObjectsForKeysV:(id)_firstKey, ...; @end #endif /* __NGExtensions_NSDictionary_misc_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSNull+misc.h0000644000000000000000000000206715004363604021447 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NSNull_misc_H__ #define __NSNull_misc_H__ #import @interface NSNull(misc) - (BOOL)isNotNull; - (double)doubleValue; - (NSString *)stringValue; @end @interface NSObject(NSNullMisc) - (BOOL)isNotNull; - (BOOL)isNotEmpty; @end #endif /* __NSNull_misc_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/EOCacheDataSource.h0000644000000000000000000000262615004363604022550 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_EOCacheDataSource_H__ #define __NGExtensions_EOCacheDataSource_H__ #import #import @class NSTimer; @interface EOCacheDataSource : EODataSource { EODataSource *source; id cache; NSTimeInterval timeout; NSTimeInterval time; NSTimer *timer; BOOL _isFetching; } - (id)initWithDataSource:(EODataSource *)_ds; /* accessors */ - (void)setSource:(EODataSource *)_source; - (EODataSource *)source; - (void)setTimeout:(NSTimeInterval)_timeout; - (NSTimeInterval)timeout; - (void)clear; @end #endif /* __NGExtensions_EOCacheDataSource_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSFileManager+Extensions.h0000644000000000000000000000217115004363604024107 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NSFileManager_Extensions_H__ #define __NSFileManager_Extensions_H__ #import #include @interface NSFileManager(ExtendedFileManager) < NGFileManagerDataSources > - (BOOL)createDirectoriesAtPath:(NSString *)_p attributes:(NSDictionary *)_a; @end #endif /* __NSFileManager_Extensions_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSSet+enumerator.h0000644000000000000000000000261215004363604022512 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSSet_enumerator_H__ #define __NGExtensions_NSSet_enumerator_H__ #import @interface NSSet(enumerator) - (id)initWithObjectsFromEnumerator:(NSEnumerator *)_enumerator; - (NSArray *)mappedArrayUsingSelector:(SEL)_selector; - (NSArray *)mappedArrayUsingSelector:(SEL)_selector withObject:(id)_object; - (NSSet *)mappedSetUsingSelector:(SEL)_selector; - (NSSet *)mappedSetUsingSelector:(SEL)_selector withObject:(id)_object; @end @interface NSMutableSet(enumerator); - (id)initWithObjectsFromEnumerator:(NSEnumerator *)_enumerator; @end #endif /* __NGExtensions_NSSet_enumerator_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGRule.h0000644000000000000000000000441715004363604020502 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGRuleEngine_NGRule_H__ #define __NGRuleEngine_NGRule_H__ #import #import /* NGRule This class represents a rule inside the rule-model. A rule conceptually has: - a qualifier - aka lhs (the condition which must be true for the rule) - an action - aka rhs (the "thing" which is performed when the rule is triggered) - a priority - to select a rule if multiple ones match String Representation: qualifer => action [; priority] *true* => action Example: "(request.isXmlRpcRequest = YES) => dispatcher = XmlRpc ;0" */ @class EOQualifier; @interface NGRule : NSObject < EOKeyValueArchiving > { EOQualifier *qualifier; id action; int priority; } + (id)ruleWithQualifier:(EOQualifier *)_q action:(id)_action priority:(int)_p; + (id)ruleWithQualifier:(EOQualifier *)_q action:(id)_action; - (id)initWithQualifier:(EOQualifier *)_q action:(id)_action priority:(int)_p; - (id)initWithPropertyList:(id)_plist; - (id)initWithString:(NSString *)_s; /* accessors */ - (void)setQualifier:(EOQualifier *)_q; - (EOQualifier *)qualifier; - (void)setAction:(id)_action; - (id)action; - (void)setPriority:(int)_pri; - (int)priority; /* operations */ - (BOOL)isCandidateForKey:(NSString *)_key; - (id)fireInContext:(id)_ctx; /* representations */ - (NSString *)stringValue; @end @interface NSObject(RuleAction) - (id)fireInContext:(id)_ctx; @end #endif /* __NGRuleEngine_NGRule_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGHashMap.h0000644000000000000000000000563215004363604021114 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGHashMap_H__ #define __NGExtensions_NGHashMap_H__ #import #import @class NSArray, NSDictionary; @interface NGHashMap : NSObject < NSCopying, NSMutableCopying, NSCoding > { @protected NSMapTable *table; } + (id)hashMap; + (id)hashMapWithHashMap:(NGHashMap *)_hashMap; + (id)hashMapWithObjects:(NSArray *)_objects forKey:(id)_key; + (id)hashMapWithDictionary:(NSDictionary *)_dict; - (id)init; - (id)initWithCapacity:(NSUInteger)_size; - (id)initWithObjects:(NSArray *)_objects forKey:(id)_key; - (id)initWithHashMap:(NGHashMap *)_hashMap; - (id)initWithDictionary:(NSDictionary *)_dictionary; - (BOOL)isEqual:(id)anObject; - (BOOL)isEqualToHashMap:(NGHashMap *)_other; - (id)objectForKey:(id)_key; - (NSArray *)objectsForKey:(id)_key; - (id)objectAtIndex:(NSUInteger)_index forKey:(id)_key; - (NSArray *)allKeys; - (NSArray *)allObjects; - (NSEnumerator *)keyEnumerator; - (NSEnumerator *)objectEnumerator; - (NSEnumerator *)objectEnumeratorForKey:(id)_key; - (id)propertyList; - (NSString *)description; - (NSDictionary *)asDictionary; - (NSDictionary *)asDictionaryWithArraysForValues; - (NSUInteger)hash; - (NSUInteger)count; // returns the number of keys - (NSUInteger)countObjectsForKey:(id)_key; @end @interface NGMutableHashMap : NGHashMap { } + (id)hashMapWithCapacity:(NSUInteger)_numItems; - (id)init; - (void)insertObject:(id)_object atIndex:(NSUInteger)_index forKey:(id)_key; - (void)insertObjects:(NSArray *)_object atIndex:(NSUInteger)_index forKey:(id)_key; - (void)insertObjects:(id*)_objects count:(NSUInteger)_count atIndex:(NSUInteger)_index forKey:(id)_key; - (void)addObject:(id)_object forKey:(id)_key; - (void)addObjects:(NSArray *)_objects forKey:(id)_key; - (void)addObjects:(id*)_objects count:(NSUInteger)_count forKey:(id)_key; - (void)setObject:(id)_object forKey:(id)_key; - (void)setObjects:(NSArray *)_objects forKey:(id)_key; - (void)removeAllObjects; - (void)removeAllObjects:(id)_object forKey:(id)_key; - (void)removeAllObjectsForKey:(id)_key; - (void)removeAllObjectsForKeys:(NSArray *)_keyArray; @end #endif /* __NGExtensions_NGHashMap_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGLoggerManager.h0000644000000000000000000000533015004363604022300 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGLoggerManager_H_ #define __NGExtensions_NGLoggerManager_H_ /* NGLoggerManager Manages a set of loggers by associating logger instances with names. Thus clients will be given the same instances if accessing the manager with the same name/key. Also, NGLoggerManager offers conditional creation of loggers based on user default keys (and special values associated with these keys). NGLoggerManager honours the following user default keys: User Default key Function ---------------------------------------------------------------------------- LoggerConfig contains the configuration of the logger named . Depending on what method you used to retrieve the logger, is either the user default key, class name or another arbitrary name. The config found for that key is used to initialize the logger instance. NGLogDebugAllEnabled if set to "YES" will always return a logger when -loggerForDefaultKey: is called. */ #import @class NSString, NSMutableDictionary; @class NGLogger; @interface NGLoggerManager : NSObject { NSMutableDictionary *loggerMap; } + (id)defaultLoggerManager; /* Retrieves a logger conditional to the existence of the given default key. In order to stay backwards compatible to existing applications, a boolean value auf YES associated with this key sets the default log level of this logger to NGLogLevelDebug. If the requested default key is not set, *nil* is returned. */ - (NGLogger *)loggerForDefaultKey:(NSString *)_defaultKey; /* Retrieves a "named" logger with NGLogLevelAll. */ - (NGLogger *)loggerForFacilityNamed:(NSString *)_name; - (NGLogger *)loggerForClass:(Class)_clazz; @end #endif /* __NGExtensions_NGLoggerManager_H_ */ SOPE/sope-core/NGExtensions/NGExtensions/EOGroupingSet.h0000644000000000000000000000161415004363604022034 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _EOGroupingSet_h__ #define _EOGroupingSet_h__ #include #endif /* _EOGroupingSet_h__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSArray+enumerator.h0000644000000000000000000000336415004363604023042 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSArray_enumerator_H__ #define __NGExtensions_NSArray_enumerator_H__ #import @class NSSet; @interface NSArray(enumerator) - (id)initWithObjectsFromEnumerator:(NSEnumerator *)_enumerator; /* Returns an array contructed using this algorithm: for (i = 0; i < [self count]; i++) newArray[i] = [array[i] performSelector:_selector]; If the selector returns nil, NSNull is placed in the resulting array. */ - (NSArray *)mappedArrayUsingSelector:(SEL)_selector; - (NSArray *)mappedArrayUsingSelector:(SEL)_selector withObject:(id)_object; - (NSSet *)mappedSetUsingSelector:(SEL)_selector; - (NSSet *)mappedSetUsingSelector:(SEL)_selector withObject:(id)_object; #if !LIB_FOUNDATION_LIBRARY - (NSArray *)map:(SEL)_sel; - (NSArray *)map:(SEL)_sel with:(id)_arg; #endif @end @interface NSMutableArray(enumerator); - (id)initWithObjectsFromEnumerator:(NSEnumerator *)_enumerator; @end #endif /* __NGExtensions_NSArray_enumerator_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGLogSyslogAppender.h0000644000000000000000000000353215004363604023171 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGLogSyslogAppender_H_ #define __NGExtensions_NGLogSyslogAppender_H_ /* NGLogSyslogAppender An appender which writes to the system's syslog facility. Use the user default key "NGLogSyslogIdentifier" to set the syslog identifier. The syslog identifier is a string that will be prepended to every message. See your operating system's manpage on syslog for details. Note: syslog doesn't support user provided timestamps, thus this information provided by NGLogEvent is silently discarded. The following scheme is used to map NGLogLevels to syslog's levels: NGLogLevel syslog -------------------------- NGLogLevelDebug LOG_DEBUG NGLogLevelInfo LOG_INFO NGLogLevelWarn LOG_WARNING NGLogLevelError LOG_ERR NGLogLevelFatal LOG_ALERT */ #include @class NSString; @interface NGLogSyslogAppender : NGLogAppender { } + (id)sharedAppender; /* provide syslog identifier */ - (id)initWithIdentifier:(NSString *)_ident; @end #endif /* __NGExtensions_NGLogSyslogAppender_H_ */ SOPE/sope-core/NGExtensions/NGExtensions/NSException+misc.h0000644000000000000000000000741115004363604022471 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSException_misc_H__ #define __NGExtensions_NSException_misc_H__ #import #import /* Miscellaneous method additions to NSException the additions make it easier using exceptions in the Java way. In OpenStep exceptions are identified by their name, subclasses are mainly used when additional information needs to be stored. This works well as long as you do not use exceptions very much (as in the Foundation Kit) - if you do you soon wish to have a 'hierachy' of exceptions. This can be modelled - like in Java - using a subclass for each different kind of exception and then using the type of the exception for it's identification. This is supported by libFoundation using the TRY and CATCH macros. The methods below always use the class name as the exception name if the name isn't specified explicitly. */ @interface NSException(NGMiscellaneous) - (id)initWithReason:(NSString *)_reason; - (id)initWithReason:(NSString *)_reason userInfo:(id)_userInfo; - (id)initWithFormat:(NSString *)_format,...; @end @interface NSObject(NSExceptionNGMiscellaneous) - (BOOL)isException; - (BOOL)isExceptionOrNull; @end /* The following macros are for use of locks together with exception handling. A synchronized block is properly 'unlocked' even if an exception occures. It is used this way: SYNCHRONIZED(MyObject) { THROW(MyException..); } END_SYNCHRONIZED; Where MyObject must be an object that conforms to the NSObject and NSLocking protocol. This is much different to [MyObject lock]; { THROW(MyException..); } [MyObject unlock]; which leaves the lock locked when an exception happens. */ #if defined(DEBUG_SYNCHRONIZED) #define SYNCHRONIZED(__lock__) \ { \ id __syncLock__ = [__lock__ retain]; \ [__syncLock__ lock]; \ fprintf(stderr, "0x%08X locked in %s.\n", \ (unsigned)__syncLock__, __PRETTY_FUNCTION__); \ NS_DURING { #define END_SYNCHRONIZED \ } \ NS_HANDLER { \ fprintf(stderr, "0x%08X exceptional unlock in %s exception %s.\n", \ (unsigned)__syncLock__, __PRETTY_FUNCTION__,\ [[localException description] cString]); \ [__syncLock__ unlock]; \ [__syncLock__ release]; __syncLock__ = nil; \ [localException raise]; \ } \ NS_ENDHANDLER; \ fprintf(stderr, "0x%08X unlock in %s.\n", \ (unsigned)__syncLock__, __PRETTY_FUNCTION__); \ [__syncLock__ unlock]; \ [__syncLock__ release]; __syncLock__ = nil; \ } #else #define SYNCHRONIZED(__lock__) \ { \ id __syncLock__ = [__lock__ retain]; \ [__syncLock__ lock]; \ NS_DURING { #define END_SYNCHRONIZED \ } \ NS_HANDLER { \ [__syncLock__ unlock]; \ [__syncLock__ release]; \ [localException raise]; \ } \ NS_ENDHANDLER; \ [__syncLock__ unlock]; \ [__syncLock__ release]; \ } #endif #endif /* __NGExtensions_NSException_misc_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSData+misc.h0000644000000000000000000000205715004363604021405 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSData_misc_H__ #define __NGExtensions_NSData_misc_H__ #import @interface NSData(misc) - (BOOL)hasPrefix:(NSData *)_data; - (BOOL)hasPrefixBytes:(const void *)_bytes length:(unsigned)_len; @end #endif /* __NGExtensions_NSData_misc_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGBitSet.h0000644000000000000000000000461015004363604020760 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGBitSet_H__ #define __NGExtensions_NGBitSet_H__ #import #import @class NSArray, NSEnumerator; typedef unsigned int NGBitSetStorage; @protocol NGBitSet < NSObject > // state - (NSUInteger)count; // membership - (BOOL)isMember:(NSUInteger)_element; - (void)addMember:(NSUInteger)_element; - (void)addMembersInRange:(NSRange)_range; - (void)removeMember:(NSUInteger)_element; - (void)removeMembersInRange:(NSRange)_range; - (void)removeAllMembers; @end @interface NGBitSet : NSObject < NGBitSet, NSCopying, NSCoding > { @protected unsigned int universe; unsigned int count; NGBitSetStorage *storage; } + (id)bitSet; + (id)bitSetWithCapacity:(NSUInteger)_capacity; + (id)bitSetWithBitSet:(NGBitSet *)_set; - (id)init; - (id)initWithCapacity:(NSUInteger)_capacity; // designated initializer - (id)initWithBitSet:(NGBitSet *)_set; - (id)initWithNullTerminatedArray:(unsigned int *)_array; // state - (NSUInteger)capacity; // membership - (NSUInteger)firstMember; - (NSUInteger)lastMember; - (void)addMembersFromBitSet:(NGBitSet *)_set; // equality - (BOOL)isEqual:(id)_object; - (BOOL)isEqualToSet:(NGBitSet *)_set; // enumerator - (NSEnumerator *)objectEnumerator; // NSCopying - (id)copy; - (id)copyWithZone:(NSZone *)_zone; // NSCoding - (void)encodeWithCoder:(NSCoder *)_coder; - (id)initWithCoder:(NSCoder *)_coder; // description - (NSString *)description; - (NSArray *)toArray; @end NSString *stringValueForBitset(unsigned int _set, char _setC, char _unsetC, short _wide); #endif /* __NGExtensions_NGBitSet_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGLogLevel.h0000644000000000000000000000215115004363604021275 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGLogLevel_H_ #define __NGExtensions_NGLogLevel_H_ /* Currently defined log levels. */ typedef enum { NGLogLevelOff = 0, NGLogLevelFatal = 1, NGLogLevelError = 2, NGLogLevelWarn = 3, NGLogLevelInfo = 4, NGLogLevelDebug = 5, NGLogLevelAll = 6 } NGLogLevel; #endif /* __NGExtensions_NGLogLevel_H_ */ SOPE/sope-core/NGExtensions/NGExtensions/NSString+Escaping.h0000644000000000000000000000235215004363604022576 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSString_Escaping_H__ #define __NGExtensions_NSString_Escaping_H__ #import @protocol NGStringEscaping < NSObject > - (NSString *)stringByEscapingString:(NSString *)_s; @end @interface NSString (Escaping) - (NSString *)stringByApplyingCEscaping; - (NSString *)stringByEscapingCharactersFromSet:(NSCharacterSet *)_set usingStringEscaping:(id)_esc; @end #endif /* __NGExtensions_NSString_Escaping_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/FileObjectHolder.h0000644000000000000000000000310415004363604022502 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created by Helge Hess on Wed Apr 17 2002. #ifndef __testrunloop_FileObject__ #define __testrunloop_FileObject__ #import @class NSFileHandle, NSNotificationCenter; /* This class is used to implement Unix filedescriptor notification on the MacOSX Foundation library. */ @interface FileObjectHolder : NSObject { NSFileHandle *fileHandle; NSString *mode; id fileObject; int fd; int activities; BOOL waitActive; } - (id)initWithFileObject:(id)_obj activities:(int)_act mode:(NSString *)_mode; /* accessors */ - (NSFileHandle *)fileHandle; - (id)fileObject; - (int)fileDescriptor; - (int)activities; - (NSString *)mode; - (NSNotificationCenter *)notificationCenter; /* operations */ - (void)wait; - (void)stopWaiting; @end #endif /* __testrunloop_FileObject__ */ SOPE/sope-core/NGExtensions/NGExtensions/EOSortOrdering+plist.h0000644000000000000000000000214415004363604023335 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOSortOrdering_plist_h__ #define __EOSortOrdering_plist_h__ #import @class NSDictionary, NSString; @interface EOSortOrdering(plist) - (id)initWithDictionary:(NSDictionary *)_dictionary; - (id)initWithString:(NSString *)_string; - (id)initWithPropertyList:(id)_plist owner:(id)_owner; @end #endif SOPE/sope-core/NGExtensions/NGExtensions/NGFileManager.h0000644000000000000000000001314515004363604021743 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGFileManager_H__ #define __NGFileManager_H__ #import @class NSString, NSData; @class EODataSource, EOGlobalID; @protocol NGFileManager /* path operations */ - (NSString *)standardizePath:(NSString *)_path; - (NSString *)resolveSymlinksInPath:(NSString *)_path; - (NSString *)expandTildeInPath:(NSString *)_path; /* directory operations */ - (BOOL)changeCurrentDirectoryPath:(NSString *)_path; - (BOOL)createDirectoryAtPath:(NSString *)_path attributes:(NSDictionary *)_ats; - (NSString *)currentDirectoryPath; /* file operations */ - (BOOL)copyPath:(NSString *)_s toPath:(NSString *)_d handler:(id)_handler; - (BOOL)movePath:(NSString *)_s toPath:(NSString *)_d handler:(id)_handler; - (BOOL)linkPath:(NSString *)_s toPath:(NSString *)_d handler:(id)_handler; - (BOOL)removeFileAtPath:(NSString *)_path handler:(id)_handler; - (BOOL)createFileAtPath:(NSString *)_path contents:(NSData *)_contents attributes:(NSDictionary *)_attributes; /* getting and comparing file contents */ - (NSData *)contentsAtPath:(NSString *)_path; - (BOOL)contentsEqualAtPath:(NSString *)_path1 andPath:(NSString *)_path2; /* determining access to files */ - (BOOL)fileExistsAtPath:(NSString *)_path; - (BOOL)fileExistsAtPath:(NSString *)_path isDirectory:(BOOL*)_isDirectory; - (BOOL)isReadableFileAtPath:(NSString *)_path; - (BOOL)isWritableFileAtPath:(NSString *)_path; - (BOOL)isExecutableFileAtPath:(NSString *)_path; - (BOOL)isDeletableFileAtPath:(NSString *)_path; /* Getting and setting attributes */ - (NSDictionary *)fileAttributesAtPath:(NSString *)_p traverseLink:(BOOL)_flag; - (NSDictionary *)fileSystemAttributesAtPath:(NSString *)_p; - (BOOL)changeFileAttributes:(NSDictionary *)_attributes atPath:(NSString *)_p; /* discovering directory contents */ - (NSArray *)directoryContentsAtPath:(NSString *)_path; - (NSDirectoryEnumerator *)enumeratorAtPath:(NSString *)_path; - (NSArray *)subpathsAtPath:(NSString *)_path; /* symbolic-link operations */ - (BOOL)createSymbolicLinkAtPath:(NSString *)_p pathContent:(NSString *)_dpath; - (NSString *)pathContentOfSymbolicLinkAtPath:(NSString *)_path; /* feature check */ - (BOOL)supportsVersioningAtPath:(NSString *)_path; - (BOOL)supportsLockingAtPath:(NSString *)_path; - (BOOL)supportsFolderDataSourceAtPath:(NSString *)_path; - (BOOL)supportsFeature:(NSString *)_featureURI atPath:(NSString *)_path; /* writing */ - (BOOL)writeContents:(NSData *)_content atPath:(NSString *)_path; /* global-IDs */ - (EOGlobalID *)globalIDForPath:(NSString *)_path; - (NSString *)pathForGlobalID:(EOGlobalID *)_gid; /* trash */ - (BOOL)supportsTrashFolderAtPath:(NSString *)_path; - (NSString *)trashFolderForPath:(NSString *)_path; - (BOOL)trashFileAtPath:(NSString *)_path handler:(id)_handler; @end @protocol NGFileManagerVersioning < NGFileManager > /* versioning */ - (BOOL)checkoutFileAtPath:(NSString *)_path handler:(id)_handler; - (BOOL)releaseFileAtPath:(NSString *)_path handler:(id)_handler; - (BOOL)rejectFileAtPath:(NSString *)_path handler:(id)_handler; - (BOOL)checkoutFileAtPath:(NSString *)_path version:(NSString *)_version handler:(id)_handler; /* versioning data */ - (NSString *)lastVersionAtPath:(NSString *)_path; - (NSArray *)versionsAtPath:(NSString *)_path; - (NSData *)contentsAtPath:(NSString *)_path version:(NSString *)_version; - (NSDictionary *)fileAttributesAtPath:(NSString *)_path traverseLink:(BOOL)_followLink version:(NSString *)_version; @end @protocol NGFileManagerLocking < NGFileManager > - (BOOL)lockFileAtPath:(NSString *)_path handler:(id)_handler; - (BOOL)unlockFileAtPath:(NSString *)_path handler:(id)_handler; - (BOOL)isFileLockedAtPath:(NSString *)_path; /* access rights */ - (BOOL)isLockableFileAtPath:(NSString *)_path; - (BOOL)isUnlockableFileAtPath:(NSString *)_path; @end @protocol NGFileManagerDataSources < NGFileManager > /* datasources (work on folders) */ - (EODataSource *)dataSourceAtPath:(NSString *)_path; - (EODataSource *)dataSource; // works on current-directory-path @end /* features */ #define NGFileManagerFeature_DataSources \ @"http://www.skyrix.com/filemanager/datasources" #define NGFileManagerFeature_Locking \ @"http://www.skyrix.com/filemanager/locking" #define NGFileManagerFeature_Versioning \ @"http://www.skyrix.com/filemanager/versioning" /* abstract superclass for filemanagers ... */ @class NSString, NSURL; @interface NGFileManager : NSObject < NGFileManager > { @protected NSString *cwd; } /* paths */ /* This method removes all 'special' things: '.' '//' '..' */ - (NSString *)standardizePath:(NSString *)_path; /* this does return _path in NGFileManager ... */ - (NSString *)resolveSymlinksInPath:(NSString *)_path; /* this does return _path in NGFileManager ... */ - (NSString *)expandTildeInPath:(NSString *)_path; /* URLs */ - (NSURL *)urlForPath:(NSString *)_path; @end #endif /* __NGFileManager_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSString+Ext.h0000644000000000000000000000401515004363604021603 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSString_Ext_H__ #define __NGExtensions_NSString_Ext_H__ #import /* was specific to gstep-base and later removed, supported in libFoundation */ #if !LIB_FOUNDATION_LIBRARY @interface NSString(GSAdditions) #if !GNUSTEP - (NSString *)stringWithoutPrefix:(NSString *)_prefix; - (NSString *)stringWithoutSuffix:(NSString *)_suffix; - (NSString *)stringByReplacingString:(NSString *)_orignal withString:(NSString *)_replacement; - (NSString *)stringByTrimmingLeadSpaces; - (NSString *)stringByTrimmingTailSpaces; - (NSString *)stringByTrimmingSpaces; #endif /* !GNUSTEP */ /* the following are not available in gstep-base 1.6 ? */ - (NSString *)stringByTrimmingLeadWhiteSpaces; - (NSString *)stringByTrimmingTailWhiteSpaces; - (NSString *)stringByTrimmingWhiteSpaces; @end /* NSString(GSAdditions) */ #if !GNUSTEP @interface NSMutableString(GNUstepCompatibility) - (void)trimLeadSpaces; - (void)trimTailSpaces; - (void)trimSpaces; @end /* NSMutableString(GNUstepCompatibility) */ #endif /* !GNUSTEP */ #endif /* specific to libFoundation */ #if !LIB_FOUNDATION_LIBRARY @interface NSString(lfNSURLUtilities) - (BOOL)isAbsoluteURL; - (NSString *)urlScheme; @end #endif #endif /* __NGExtensions_NSString_Ext_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSURL+misc.h0000644000000000000000000000444215004363604021176 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSURL_misc_H__ #define __NGExtensions_NSURL_misc_H__ #import // required by gstep-base #import #import @class NSDictionary; @interface NSURL(misc) /* This method tries to construct the "shortest" path between the two URLs. If the URLs are not in the same namespace, -absoluteString is returned ... */ - (NSString *)stringValueRelativeToURL:(NSURL *)_base; /* This checks whether protocol, host, login match. That is, checks whether it's possible to build a relative URL to _url (whether self is in the same path namespace). */ - (BOOL)isInSameNamespaceWithURL:(NSURL *)_url; /* adding fragments and queries to a string ... */ - (NSString *)stringByAddingFragmentAndQueryToPath:(NSString *)_path; @end @interface NSString(URLPathProcessing) /* relative path processing (should never return an absolute path) */ /* eg: "/a/b/c.html" should resolve to: "c.html" Directories are a bit more difficult, eg: "/a/b/c/" is resolved to "../c/" */ - (NSString *)urlPathRelativeToSelf; /* this is the same like the absolute path, only without a leading "/" .. */ - (NSString *)urlPathRelativeToRoot; /* This can be used for URLs in the same namespace. It should never return an absolute path (it only does in error conditions). */ - (NSString *)urlPathRelativeToPath:(NSString *)_base; @end @interface NSURL (QueryComponents) - (NSDictionary *) queryComponents; @end #endif /* __NGExtensions_NSURL_misc_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSAutoreleasePool+misc.h0000644000000000000000000000240615004363604023635 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSAutoreleasePool_misc_H__ #define __NGExtensions_NSAutoreleasePool_misc_H__ #import #if defined(LIB_FOUNDATION_LIBRARY) @interface NSAutoreleasePool(misc) + (void)enableRetainRemove:(BOOL)enable; + (NSAutoreleasePool *)findReleasingPoolForObject:(id)_obj; + (BOOL)retainAutoreleasedObject:(id)_obj; - (BOOL)retainAutoreleasedObject:(id)_obj; @end #endif /* !LIB_FOUNDATION_LIBRARY */ #endif /* __NGExtensions_NSAutoreleasePool_misc_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/EODataSource+NGExtensions.h0000644000000000000000000000317515004363604024204 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_EODataSource_NGExtensions_H__ #define __NGExtensions_EODataSource_NGExtensions_H__ #import #include @class EOFetchSpecification; NGExtensions_EXPORT NSString *EODataSourceDidChangeNotification; /* If a fetchspecification without a qualifier is passed, the datasource should fetch all objects by default. If the EONoFetchWithEmptyQualifierHint value in the fspec hints-dictionary is YES, an emtpy array should be returned. */ NGExtensions_EXPORT NSString *EONoFetchWithEmptyQualifierHint; @interface EODataSource(NGExtensions) - (void)setFetchSpecification:(EOFetchSpecification *)_fetchSpec; - (EOFetchSpecification *)fetchSpecification; - (void)postDataSourceChangedNotification; - (void)updateObject:(id)_obj; @end #endif /* __NGExtensions_EODataSource_NGExtensions_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSObject+Values.h0000644000000000000000000000342415004363604022245 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSObject_Values_H__ #define __NGExtensions_NSObject_Values_H__ #import #import @protocol NGBaseTypeValues - (BOOL)boolValue; - (signed char)charValue; - (unsigned char)unsignedCharValue; - (signed short)shortValue; - (unsigned short)unsignedShortValue; - (signed int)intValue; - (unsigned int)unsignedIntValue; - (signed long)longValue; - (unsigned long)unsignedLongValue; - (signed long long)longLongValue; - (unsigned long long)unsignedLongLongValue; - (float)floatValue; @end /* The default basetype methods perform their operation on the string-representation of the object. -boolValue returns YES per default. (id != nil) */ @interface NSObject(NGValues) < NGBaseTypeValues > - (double)doubleValue; - (NSString *)stringValue; @end @interface NSString(NGValues) + (NSString *) stringWithUnsignedLongLong: (unsigned long long)value; - (BOOL)boolValue; - (NSString *)stringValue; @end #endif /* __NGExtensions_NSObject_Values_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSRunLoop+FileObjects.h0000644000000000000000000000315415004363604023367 0ustar rootroot/* Copyright (C) 2002-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created by Helge Hess on Mon Mar 11 2002. #ifndef __FoundationExt_NSRunLoop_FileObjects__ #define __FoundationExt_NSRunLoop_FileObjects__ #if !LIB_FOUNDATION_LIBRARY #import typedef enum { NSPosixNoActivity = 0, NSPosixReadableActivity = 1, NSPosixWritableActivity = 2, NSPosixExceptionalActivity = 4 } NSPosixFileActivities; extern NSString *NSFileObjectBecameActiveNotificationName; @interface NSRunLoop(FileObjects) /* Monitoring file objects */ - (void)addFileObject:(id)_fileObject activities:(NSUInteger)_activities forMode:(NSString *)_mode; - (void)removeFileObject:(id)_fileObject forMode:(NSString *)_mode; @end @interface NSObject(RunloopFileObject) - (BOOL)isOpen; - (int)fileDescriptor; @end #endif /* !LIB_FOUNDATION_LIBRARY */ #endif /* __FoundationExt_NSRunLoop_FileObjects__ */ SOPE/sope-core/NGExtensions/NGExtensions/EOFilterDataSource.h0000644000000000000000000000277015004363604022772 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_EOFilterDataSource_H__ #define __NGExtensions_EOFilterDataSource_H__ #import @class NSArray; @class EOQualifier; @interface EOFilterDataSource : EODataSource { EODataSource *source; EOQualifier *auxiliaryQualifier; NSArray *sortOrderings; NSArray *groupings; } - (id)initWithDataSource:(EODataSource *)_ds; /* accessors */ - (void)setSource:(EODataSource *)_source; - (EODataSource *)source; - (void)setAuxiliaryQualifier:(EOQualifier *)_q; - (EOQualifier *)auxiliaryQualifier; - (void)setSortOrderings:(NSArray *)_o; - (NSArray *)sortOrderings; - (void)setGroupings:(NSArray *)_groupings; - (NSArray *)groupings; @end #endif /* __NGExtensions_EOFilterDataSource_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/DOMNode+EOQualifier.h0000644000000000000000000000216715004363604022734 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __DOM_DOMNode_EOQualifier_H__ #define __DOM_DOMNode_EOQualifier_H__ #include @class NSArray; @class EOQualifier; @interface NGDOMNode(EOQualifier) - (NSArray *)childrenMatchingQualifier:(EOQualifier *)_qualifier; - (NSArray *)descendantsMatchingQualifier:(EOQualifier *)_qualifier; @end #endif /* __DOM_DOMNode_EOQualifier_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGFileFolderInfoDataSource.h0000644000000000000000000000337415004363604024376 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGFileInfoDataSource_H__ #define __NGFileInfoDataSource_H__ #import #import #include @class NSString; @class EOFetchSpecification; /* supported keys: NSFileName NSFilePath NSParentPath + all NSFileManager attributes returned by -fileAttributesAtPath:... supported fetch hints: NSTraverseLinks - bool */ NGExtensions_EXPORT NSString *NSFileName; NGExtensions_EXPORT NSString *NSFilePath; NGExtensions_EXPORT NSString *NSParentPath; NGExtensions_EXPORT NSString *NSTraverseLinks; @interface NGFileFolderInfoDataSource : EODataSource { NSString *folderPath; EOFetchSpecification *fspec; } - (id)initWithFolderPath:(NSString *)_path; /* accessors */ - (void)setFetchSpecification:(EOFetchSpecification *)_fspec; - (EOFetchSpecification *)fetchSpecification; /* operations */ - (NSArray *)fetchObjects; @end #endif /* __NGFileInfoDataSource_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/EOGrouping.h0000644000000000000000000000445615004363604021367 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _EOGrouping_h__ #define _EOGrouping_h__ #import @class NSString, NSArray, NSMutableArray; @class EOQualifier; @interface EOGrouping : NSObject { NSString *defaultName; NSArray *sortOrderings; } - (id)initWithDefaultName:(NSString *)_defaultName; - (NSString *)defaultName; - (void)setDefaultName:(NSString *)_defaultName; - (NSArray *)sortOrderings; - (void)setSortOrderings:(NSArray *)_sortOrderings; - (NSString *)groupNameForObject:(id)object; - (NSArray *)orderedGroupNames; @end @interface EOGroupingSet : EOGrouping { NSArray *groupings; } - (NSArray *)groupings; - (void)setGroupings:(NSArray *)_groupings; @end @interface EOKeyGrouping : EOGrouping { NSString *key; NSMutableArray *groupNames; /* ??? to be fixed */ } - (id)initWithKey:(NSString *)_key; - (NSString *)key; - (void)setKey:(NSString *)_key; @end @interface EOQualifierGrouping : EOGrouping { EOQualifier *qualifier; NSString *name; } - (id)initWithQualifier:(EOQualifier *)_qualifier name:(NSString *)_name; - (void)setName:(NSString *)_name; - (NSString *)name; - (void)setQualifier:(EOQualifier *)_qualifier; - (EOQualifier *)qualifier; @end #import @class NSDictionary; @interface NSArray(EOGrouping) - (NSDictionary *)arrayGroupedBy:(EOGrouping *)_grouping; @end #import extern NSString *EOGroupingHint; @interface EOFetchSpecification(Groupings) - (void)setGroupings:(NSArray *)_groupings; - (NSArray *)groupings; @end #endif /* _EOGrouping_h__ */ SOPE/sope-core/NGExtensions/NGExtensions/EOTrueQualifier.h0000644000000000000000000000244715004363604022354 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOExt_EOTrueQualifier_H__ #define __EOExt_EOTrueQualifier_H__ #import /* EOTrueQualifier This is an extremly simple qualifier which always evaluates to true ... (eg used in the rule-system) Note: the EOTrueQualifier may not map properly to a storage based qualifier, so you probably need to find a workaround to represent a generic 'true' in your database. */ @interface EOTrueQualifier : EOQualifier < EOQualifierEvaluation > { } @end #endif /* __EOExt_EOTrueQualifier_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGBase64Coding.h0000644000000000000000000000403315004363604021735 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGBase64Encoding_H__ #define __NGExtensions_NGBase64Encoding_H__ #import #import /* Base64 encoder/decoder Attention: these methods/function do _not_ generate a '\n' at the end of the end of encoding (after the '=' signs). The NSString and NSData have their own maximum line length, for strings it is currently 1024 bytes and for data's 72 chars. */ @interface NSString(Base64Coding) - (NSString *)stringByEncodingBase64; - (NSString *)stringByDecodingBase64; - (NSData *)dataByDecodingBase64; @end @interface NSData(Base64Coding) - (NSData *)dataByEncodingBase64; /* Note: inserts '\n' every 72 chars */ - (NSData *)dataByDecodingBase64; - (NSString *)stringByEncodingBase64; - (NSString *)stringByDecodingBase64; - (NSData *)dataByEncodingBase64WithLineLength:(unsigned)_lineLength; @end /* These function return the length of the resulting buffer or -1 on error */ int NGEncodeBase64(const void *_source, unsigned _len, void *_buffer, unsigned _bufferCapacity, int _maxLineWidth); int NGDecodeBase64(const void *_source, unsigned _len, void *_buffer, unsigned _bufferCapacity); #endif /* __NGExtensions_NGBase64Encoding_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGCharBuffers.h0000644000000000000000000001057315004363604021765 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGCharBuffers_H__ #define __NGExtensions_NGCharBuffers_H__ #include #include #import #import #import typedef struct { unsigned capacity; unsigned length; unsigned char increaseRatio; unsigned char *buffer; // zero terminated buffer } NGCharBuffer8Struct; typedef NGCharBuffer8Struct *NGCharBuffer8; static inline NGCharBuffer8 NGCharBuffer8_init(NGCharBuffer8 _str, unsigned _capacity) { _str->capacity = _capacity; _str->length = 0; _str->increaseRatio = 2; _str->buffer = NGMallocAtomic(_capacity); _str->buffer[0] = '\0'; return _str; } static inline void NGCharBuffer8_reset(NGCharBuffer8 _str) { if (_str) { _str->capacity = 0; _str->length = 0; _str->increaseRatio = 0; NGFree(_str->buffer); _str->buffer = NULL; } } static inline NGCharBuffer8 NGCharBuffer8_new(unsigned _capacity) { NGCharBuffer8 str = NULL; str = NGMalloc(sizeof(NGCharBuffer8Struct)); return NGCharBuffer8_init(str, _capacity); } static inline NGCharBuffer8 NGCharBuffer8_newWithCString(const char *_cstr) { NGCharBuffer8 str = NULL; str = NGMalloc(sizeof(NGCharBuffer8Struct)); str = NGCharBuffer8_init(str, strlen(_cstr) + 2); strcpy((char *)str->buffer, _cstr); return str; } static inline void NGCharBuffer8_dealloc(NGCharBuffer8 _str) { if (_str) { NGCharBuffer8_reset(_str); NGFree(_str); _str = NULL; } } static inline void NGCharBuffer8_checkCapacity(NGCharBuffer8 _str, unsigned _needed) { if (_str->capacity < (_str->length + _needed + 1)) { // increase size unsigned char *oldBuffer = _str->buffer; _str->capacity *= _str->increaseRatio; if (_str->capacity < (_str->length + _needed + 1)) _str->capacity += _needed + 1; _str->buffer = NGMallocAtomic(_str->capacity + 2); memcpy(_str->buffer, oldBuffer, (_str->length + 1)); NGFree(oldBuffer); oldBuffer = NULL; } } static inline void NGCharBuffer8_addChar(NGCharBuffer8 _str, unsigned char _c) { NGCharBuffer8_checkCapacity(_str, 1); _str->buffer[_str->length] = _c; (_str->length)++; _str->buffer[_str->length] = '\0'; } static inline void NGCharBuffer8_addCString(NGCharBuffer8 _str, char *_cstr) { unsigned len; if (_cstr == NULL) return; len = strlen(_cstr); NGCharBuffer8_checkCapacity(_str, len); strcat((char *)_str->buffer, _cstr); _str->length += len; } static inline void NGCharBuffer8_removeContents(NGCharBuffer8 _str) { _str->length = 0; _str->buffer[0] = '\0'; } static inline NSString *NGCharBuffer8_makeStringAndDealloc(NGCharBuffer8 _str){ NSString *str; if (_str == NULL) return nil; str = [NSString stringWithCString:(char *)_str->buffer length:_str->length]; NSCAssert3(strlen((char *)_str->buffer) == _str->length, @"length of cstring(%s) and the buffer do not match (%i vs %i)", _str->buffer, strlen((char *)_str->buffer), _str->length); NGCharBuffer8_dealloc(_str); _str = NULL; return str; } static inline void NGCharBuffer8_stripTrailingSpaces(NGCharBuffer8 _str) { if (_str == NULL) return; else if (_str->length == 0) return; else { while (_str->length > 0) { unsigned char c = _str->buffer[_str->length - 1]; if (isspace((int)c) || (c == '\n') || (c == '\r')) { (_str->length)--; } else { break; } } _str->buffer[_str->length] = '\0'; } } #endif /* __NGExtensions_NGCharBuffers_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NSDictionary+KVC.h0000644000000000000000000000230015004363604022320 0ustar rootroot/* Copyright (C) 2000-2008 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NSDictionary_KVC_H__ #define __NGExtensions_NSDictionary_KVC_H__ #import @interface NSDictionary(KVC) - (id)valueForUndefinedKey:(NSString *)key; - (id)handleQueryWithUnboundKey:(NSString *)key; - (void)setValue:(id)value forUndefinedKey:(NSString *)key; - (void)handleTakeValue:(id)value forUnboundKey:(NSString *)key; @end #endif /* __NGExtensions_NSDictionary_KVC_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGStringScanEnumerator.h0000644000000000000000000000360715004363604023710 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGStringScanEnumerator_H__ #define __NGExtensions_NGStringScanEnumerator_H__ #import #import /* NGStringScanEnumerator This class is used to scan (binary) NSData objects for printable strings, pretty much like the "strings" Unix program. Example: NSData *data = [NSData dataWithContentsOfMappedFile:@"/bin/ls"]; NSEnumerator *e; NSString *s; e = [data stringScanEnumerator]; while ((s = [e nextObject])) { if ([s hasPrefix:@"4"] && [s length] > 5) { NSLog(@"ls version: %@", s); break; } } */ @interface NGStringScanEnumerator : NSEnumerator { unsigned int curPos; NSData *data; unsigned int maxLength; } + (id)enumeratorWithData:(NSData *)_data maxLength:(unsigned int)_maxLength; @end /* StringEnumerator */ @interface NSData(NGStringScanEnumerator) /* scan strings with up to 256 chars length */ - (NSEnumerator *)stringScanEnumerator; - (NSEnumerator *)stringScanEnumeratorWithMaxStringLength:(unsigned int)_max; @end #endif /* __NGExtensions_NGStringScanEnumerator_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/EOKeyMapDataSource.h0000644000000000000000000000712215004363604022727 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_EOKeyMapDataSource_H__ #define __NGExtensions_EOKeyMapDataSource_H__ #import /* EOKeyMapDataSource This class allows you to remap the keys of a source datasource on the fly. It fully supports fetch enumerators. The class description of the datasource describes what keys the resulting objects should have (note that the fetchspec isn't checked for validaty on that). */ @class NSException, NSEnumerator, NSArray, NSClassDescription; @class NSMutableDictionary, NSDictionary; @class EOFetchSpecification, EOGlobalID; @interface EOKeyMapDataSource : EODataSource { EOFetchSpecification *fspec; EODataSource *source; NSClassDescription *classDescription; NSArray *entityKeys; NSArray *mappedKeys; id map; } - (id)initWithDataSource:(EODataSource *)_ds map:(id)_map; /* accessors */ - (void)setSource:(EODataSource *)_source; - (EODataSource *)source; - (void)setFetchSpecification:(EOFetchSpecification *)_fetchSpec; - (EOFetchSpecification *)fetchSpecification; - (NSException *)lastException; /* mappings (default implementations use the map) */ - (EOFetchSpecification *)mapFetchSpecification:(EOFetchSpecification *)_fs; - (void)setClassDescriptionForObjects:(NSClassDescription *)_cd; - (NSClassDescription *)classDescriptionForObjects; - (id)mapCreatedObject:(id)_object; - (id)mapObjectForUpdate:(id)_object; - (id)mapObjectForInsert:(id)_object; - (id)mapObjectForDelete:(id)_object; - (id)mapFetchedObject:(id)_object; - (id)mapFromSourceObject:(id)_object; - (id)mapToSourceObject:(id)_object; /* fetching */ - (Class)fetchEnumeratorClass; - (NSEnumerator *)fetchEnumerator; - (NSArray *)fetchObjects; - (void)clear; /* operations */ - (void)updateObject:(id)_obj; - (void)insertObject:(id)_obj; - (void)deleteObject:(id)_obj; - (id)createObject; @end #import @interface EOKeyMapDataSourceEnumerator : NSEnumerator { EOKeyMapDataSource *ds; NSEnumerator *source; } - (id)initWithKeyMapDataSource:(EOKeyMapDataSource *)_ds fetchEnumerator:(NSEnumerator *)_enum; @end @interface EOMappedObject : NSObject { id original; EOGlobalID *globalID; NSMutableDictionary *values; struct { BOOL didChange:1; int reserved:31; } flags; } - (id)initWithObject:(id)_object values:(NSDictionary *)_values; /* accessors */ - (id)mappedObject; - (EOGlobalID *)globalID; - (BOOL)isModified; - (void)willChange; - (void)applyChangesOnObject; /* mimic dictionary */ - (void)setObject:(id)_obj forKey:(id)_key; - (id)objectForKey:(id)_key; - (void)removeObjectForKey:(id)_key; - (NSEnumerator *)keyEnumerator; - (NSEnumerator *)objectEnumerator; /* KVC */ - (void)takeValue:(id)_value forKey:(NSString *)_key; - (id)valueForKey:(NSString *)_key; @end #endif /* __NGExtensions_EOKeyMapDataSource_H__ */ SOPE/sope-core/NGExtensions/NGExtensions/NGLogger.h0000644000000000000000000000662215004363604021012 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_NGLogger_H_ #define __NGExtensions_NGLogger_H_ /* NGLogger NGLogger has a minimum log level and passes messages to its appenders only if this minimum log level is satisfied - otherwise it silently drops these messages. NGLogger also offers a factory to instantiate loggers from configs stored in NSUserDefaults. NOTE: Except in rare circumstances, do not allocate loggers yourself! Always try to use the appropriate API of NGLoggerManager if possible. NGLogger honours the following user default keys: User Default key Function ---------------------------------------------------------------------------- NGLogDefaultLogLevel The log level to use as a fallback, if no log level is provided during initialization. The default is "INFO". The following keys in the configuration dictionary will be recognized: Key Function ---------------------------------------------------------------------------- "LogLevel" The log level to use for this logger. If no log level is provided, sets log level according to fallback described above. "Appenders" Array of dictionaries suitable as configuration provided to NGLogAppender's factory method. Please see NGLogAppender.h for further explanation. LoggerConfig example: WOHttpTransactionLoggerConfig = { "LogLevel" = "INFO"; "Appenders" = ( { "Class" = "NGLogStdoutAppender"; "Formatter" = { "Class" = "NGLogEventFormatter"; }; }, ); }; */ #import #include @class NSMutableArray, NSString, NSDictionary, NGLogAppender; @interface NGLogger : NSObject { NSMutableArray *appenders; @public NGLogLevel logLevel; } + (id)loggerWithConfigFromUserDefaults:(NSString *)_defaultName; - (id)initWithConfig:(NSDictionary *)_config; - (id)initWithLogLevel:(NGLogLevel)_level; /* accessors */ - (void)setLogLevel:(NGLogLevel)_level; - (NGLogLevel)logLevel; - (void)addAppender:(NGLogAppender *)_appender; - (void)removeAppender:(NGLogAppender *)_appender; /* logging */ - (void)logLevel:(NGLogLevel)_level message:(NSString *)_msg; /* conditions */ - (BOOL)isDebuggingEnabled; - (BOOL)isLogInfoEnabled; - (BOOL)isLogWarnEnabled; - (BOOL)isLogErrorEnabled; - (BOOL)isLogFatalEnabled; @end #endif /* __NGExtensions_NGLogger_H_ */ SOPE/sope-core/NGExtensions/NGExtensions/NGFileManagerURL.h0000644000000000000000000000277415004363604022334 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGFileManagerURL_H__ #define __NGFileManagerURL_H__ #if GNUSTEP_BASE_LIBRARY # import /* add GS_EXPORT .. */ # import /* add NSObject .. */ #endif #import #include /* A URL which works on NGFileManager's. The NSURLHandle should work, but the URL can't be serialized. */ @interface NGFileManagerURL : NSURL { /* do *NOT* cache in filemanager - retain cycle !!! */ id fileManager; NSString *path; } - (id)initWithPath:(NSString *)_path fileManager:(id)_fm; /* accessors */ - (id)fileManager; @end #endif /* __NGFileManagerURL_H__ */ SOPE/sope-core/NGExtensions/NGFileManager+JS.m0000644000000000000000000002303515004363604017673 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #include "NGFileManager.h" #include "NSFileManager+Extensions.h" #include "EOCacheDataSource.h" /* JavaScript Properties cwd - readonly - current working directory, string Methods bool cd(path) Object ls([path|paths]) bool mkdir(path[,path..]) bool rmdir(path[,path..]) bool rm(path[,path..]) bool trash(path[,path..]) bool cp(frompath[,frompath..], topath) bool mv(frompath[,frompath..], topath) bool ln(frompath, topath) bool exists(path[,path..]) bool isdir(path[,path..]) bool islink(path[,path..]) Object getDataSource([String path, [bool cache]]) */ @implementation NGFileManager(JSSupport) static NSNumber *boolYes = nil; static NSNumber *boolNo = nil; static void _ensureBools(void) { if (boolYes == nil) boolYes = [[NSNumber numberWithBool:YES] retain]; if (boolNo == nil) boolNo = [[NSNumber numberWithBool:NO] retain]; } /* properties */ - (id)_jsprop_cwd { return [self currentDirectoryPath]; } /* methods */ - (id)_jsfunc_cd:(NSArray *)_args { _ensureBools(); return [self changeCurrentDirectoryPath:[_args objectAtIndex:0]] ? boolYes : boolNo; } - (id)_jsfunc_ls:(NSArray *)_args { unsigned count; if ((count = [_args count]) == 0) { return [self directoryContentsAtPath:@"."]; } else if (count == 1) { return [self directoryContentsAtPath: [[_args objectAtIndex:0] stringValue]]; } else { NSMutableDictionary *md; unsigned i; md = [NSMutableDictionary dictionaryWithCapacity:count]; for (i = 0; i < count; i++) { NSString *path; NSArray *contents; path = [_args objectAtIndex:i]; contents = [self directoryContentsAtPath:path]; if (contents) [md setObject:contents forKey:path]; } return md; } } - (id)_jsfunc_mkdir:(NSArray *)_args { unsigned count; _ensureBools(); if ((count = [_args count]) == 0) { return boolNo; } else { unsigned i; for (i = 0; i < count; i++) { NSString *path; path = [_args objectAtIndex:i]; if (![self createDirectoryAtPath:path attributes:nil]) return boolNo; } return boolYes; } } - (id)_jsfunc_rmdir:(NSArray *)_args { unsigned count; _ensureBools(); if ((count = [_args count]) == 0) { return boolNo; } else { unsigned i; for (i = 0; i < count; i++) { NSString *path; BOOL isDir; path = [_args objectAtIndex:i]; if (![self fileExistsAtPath:path isDirectory:&isDir]) return boolNo; if (!isDir) /* not a directory ! */ return boolNo; if ([[self directoryContentsAtPath:path] count] > 0) /* directory has contents */ return boolNo; if (![self removeFileAtPath:path handler:nil]) /* remove failed */ return boolNo; } return boolYes; } } - (id)_jsfunc_rm:(NSArray *)_args { unsigned count; _ensureBools(); if ((count = [_args count]) == 0) { return boolNo; } else { unsigned i; for (i = 0; i < count; i++) { NSString *path; BOOL isDir; path = [_args objectAtIndex:i]; if (![self fileExistsAtPath:path isDirectory:&isDir]) return boolNo; if (isDir) { if ([[self directoryContentsAtPath:path] count] > 0) /* directory has contents */ return boolNo; } if (![self removeFileAtPath:path handler:nil]) /* remove failed */ return boolNo; } return boolYes; } } - (id)_jsfunc_trash:(NSArray *)_args { unsigned count; _ensureBools(); if ((count = [_args count]) == 0) { return boolNo; } else { unsigned i; for (i = 0; i < count; i++) { NSString *path; BOOL isDir; path = [_args objectAtIndex:i]; if (![self supportsTrashFolderAtPath:path]) return boolNo; if (![self fileExistsAtPath:path isDirectory:&isDir]) return boolNo; if (![self trashFileAtPath:path handler:nil]) /* remove failed */ return boolNo; } return boolYes; } } - (id)_jsfunc_mv:(NSArray *)_args { unsigned count; _ensureBools(); if ((count = [_args count]) == 0) return boolNo; else if (count == 1) /* missing target path */ return boolNo; else { NSString *destpath; unsigned i; BOOL isDir; destpath = [_args objectAtIndex:(count - 1)]; if (![self fileExistsAtPath:destpath isDirectory:&isDir]) isDir = NO; for (i = 0; i < (count - 1); i++) { NSString *path, *dpath = nil; path = [_args objectAtIndex:i]; dpath = isDir ? [dpath stringByAppendingPathComponent:[path lastPathComponent]] : destpath; if (![self movePath:path toPath:dpath handler:nil]) /* move failed */ return boolNo; } return boolYes; } } - (id)_jsfunc_cp:(NSArray *)_args { unsigned count; _ensureBools(); if ((count = [_args count]) == 0) return boolNo; else if (count == 1) /* missing target path */ return boolNo; else { NSString *destpath; unsigned i; BOOL isDir; destpath = [_args objectAtIndex:(count - 1)]; if (![self fileExistsAtPath:destpath isDirectory:&isDir]) isDir = NO; for (i = 0; i < (count - 1); i++) { NSString *path, *dpath = nil; path = [_args objectAtIndex:i]; dpath = isDir ? [dpath stringByAppendingPathComponent:[path lastPathComponent]] : destpath; if (![self copyPath:path toPath:dpath handler:nil]) /* copy failed */ return boolNo; } return boolYes; } } - (id)_jsfunc_ln:(NSArray *)_args { unsigned count; _ensureBools(); if ((count = [_args count]) == 0) return boolNo; else if (count == 1) /* missing target path */ return boolNo; else { NSString *srcpath; NSString *destpath; srcpath = [_args objectAtIndex:0]; destpath = [_args objectAtIndex:1]; if (![self createSymbolicLinkAtPath:destpath pathContent:srcpath]) return boolNo; return boolYes; } } - (id)_jsfunc_exists:(NSArray *)_args { unsigned count; _ensureBools(); if ((count = [_args count]) == 0) return boolYes; else { unsigned i; for (i = 0; i < count; i++) { NSString *path; path = [_args objectAtIndex:i]; if (![self fileExistsAtPath:path]) return boolNo; } return boolYes; } } - (id)_jsfunc_isdir:(NSArray *)_args { unsigned count; _ensureBools(); if ((count = [_args count]) == 0) { return boolYes; } else { unsigned i; for (i = 0; i < count; i++) { NSString *path; BOOL isDir; path = [_args objectAtIndex:i]; #if 0 NSLog(@"CHECK PATH: %@", path); #endif if (![self fileExistsAtPath:path isDirectory:&isDir]) { #if 0 NSLog(@" does not exist .."); #endif return boolNo; } if (!isDir) { #if 0 NSLog(@" not a directory .."); #endif return boolNo; } } #if 0 NSLog(@"%s: returning yes, %@ are directories", __PRETTY_FUNCTION__, _args); #endif return boolYes; } } - (id)_jsfunc_islink:(NSArray *)_args { unsigned count; _ensureBools(); if ((count = [_args count]) == 0) return boolYes; else { unsigned i; for (i = 0; i < count; i++) { NSString *path; BOOL isDir; NSDictionary *attrs; path = [_args objectAtIndex:i]; if (![self fileExistsAtPath:path isDirectory:&isDir]) return boolNo; if (isDir) return boolNo; if ((attrs = [self fileAttributesAtPath:path traverseLink:NO])==nil) return boolNo; if (![[attrs objectForKey:NSFileType] isEqualToString:NSFileTypeSymbolicLink]) return boolNo; } return boolYes; } } /* datasource */ - (id)_jsfunc_getDataSource:(NSArray *)_args { unsigned count; NSString *path = nil; BOOL lcache; id ds; _ensureBools(); lcache = NO; if ((count = [_args count]) == 0) { path = @"."; } else if (count == 1) { path = [[_args objectAtIndex:0] stringValue]; } else if (count == 2) { path = [[_args objectAtIndex:0] stringValue]; lcache = [[_args objectAtIndex:1] boolValue]; } if (![self supportsFolderDataSourceAtPath:path]) return nil; if ((ds = [(id)self dataSourceAtPath:path])==nil) return nil; if (lcache) ds = [[[EOCacheDataSource alloc] initWithDataSource:ds] autorelease]; return ds; } @end /* NGFileManager(JSSupport) */ SOPE/sope-core/NGExtensions/GNUmakefile0000644000000000000000000000736015004363604016663 0ustar rootroot# GNUstep makefile include ../../config.make include ../common.make ifneq ($(frameworks),yes) LIBRARY_NAME = libNGExtensions else FRAMEWORK_NAME = NGExtensions endif libNGExtensions_PCH_FILE = common.h libNGExtensions_DLL_DEF = libNGExtensions.def libNGExtensions_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION) libNGExtensions_INSTALL_DIR=$(SOPE_SYSLIBDIR) libNGExtensions_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION) libNGExtensions_HEADER_FILES_DIR = ./NGExtensions libNGExtensions_HEADER_FILES_INSTALL_DIR = /NGExtensions libNGExtensions_HEADER_FILES = \ NGExtensionsDecls.h \ NGExtensions.h \ AutoDefines.h \ IndexFunc.h \ NGBase64Coding.h \ NGBaseTypes.h \ NGBitSet.h \ NGBundleManager.h \ NGCharBuffers.h \ NGCustomFileManager.h \ NGDirectoryEnumerator.h \ NGFileFolderInfoDataSource.h \ NGFileManager.h \ NGFileManagerURL.h \ NGHashMap.h \ NGMemoryAllocation.h \ NGMerging.h \ NGQuotedPrintableCoding.h \ NGStack.h \ NGObjectMacros.h \ NGCalendarDateRange.h \ NGResourceLocator.h \ libNGExtensions_OBJC_FILES = \ NGExtensions.m \ NGBase64Coding.m \ NGBitSet.m \ NGBundleManager.m \ NGCustomFileManager.m \ NGDirectoryEnumerator.m \ NGFileFolderInfoDataSource.m \ NGFileManager.m \ NGFileManager+JS.m \ NGFileManagerURL.m \ NGHashMap.m \ NGMerging.m \ NGQuotedPrintableCoding.m \ NGStack.m \ NGCalendarDateRange.m \ NGResourceLocator.m \ ifeq ($(FOUNDATION_LIB), apple) libNGExtensions_OBJC_FILES += FileObjectHolder.m endif libNGExtensions_SUBPROJECTS = \ FdExt.subproj \ EOExt.subproj \ XmlExt.subproj \ NGRuleEngine.subproj \ NGLogging.subproj \ EOExt_HEADER_FILES = \ EOCacheDataSource.h \ EOCompoundDataSource.h \ EODataSource+NGExtensions.h \ EOFilterDataSource.h \ EOGrouping.h \ EOGroupingSet.h \ EOKeyGrouping.h \ EOKeyMapDataSource.h \ EOQualifier+CtxEval.h \ EOQualifierGrouping.h \ EOTrueQualifier.h \ EOQualifier+plist.h \ EOSortOrdering+plist.h \ EOFetchSpecification+plist.h \ FdExt_HEADER_FILES = \ NSArray+enumerator.h \ NSAutoreleasePool+misc.h \ NSBundle+misc.h \ NSCalendarDate+misc.h \ NSData+gzip.h \ NSData+misc.h \ NSDictionary+misc.h \ NSEnumerator+misc.h \ NSException+misc.h \ NSFileManager+Extensions.h \ NSNull+misc.h \ NSObject+Logs.h \ NSObject+Values.h \ NSProcessInfo+misc.h \ NSRunLoop+FileObjects.h \ NSSet+enumerator.h \ NSString+Ext.h \ NSString+Formatting.h \ NSString+Encoding.h \ NSString+Escaping.h \ NSString+misc.h \ NSURL+misc.h \ NGPropertyListParser.h \ XmlExt_HEADER_FILES = \ DOMNode+EOQualifier.h NGRuleEngine_HEADER_FILES = \ NGRuleEngine.h \ NGRule.h \ NGRuleAssignment.h \ NGRuleContext.h \ NGRuleModel.h \ NGLogging_HEADER_FILES = \ NGLogging.h \ NGLogLevel.h \ NGLogger.h \ NGLoggerManager.h \ NGLogEvent.h \ NGLogEventFormatter.h \ NGLogAppender.h \ NGLogFileHandleAppender.h \ NGLogSyslogAppender.h \ libNGExtensions_HEADER_FILES += \ $(FdExt_HEADER_FILES) \ $(EOExt_HEADER_FILES) \ $(XmlExt_HEADER_FILES) \ $(NGRuleEngine_HEADER_FILES) \ $(NGLogging_HEADER_FILES) # framework support NGExtensions_PCH_FILE = $(libNGExtensions_PCH_FILE) NGExtensions_HEADER_FILES_DIR = NGExtensions NGExtensions_HEADER_FILES = $(libNGExtensions_HEADER_FILES) NGExtensions_OBJC_FILES = $(libNGExtensions_OBJC_FILES) NGExtensions_SUBPROJECTS = $(libNGExtensions_SUBPROJECTS) # building -include GNUmakefile.preamble ifneq ($(FHS_INSTALL_ROOT),) GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include endif ifneq ($(frameworks),yes) include $(GNUSTEP_MAKEFILES)/library.make else include $(GNUSTEP_MAKEFILES)/framework.make endif -include GNUmakefile.postamble SOPE/sope-core/NGExtensions/SxCore-NGExtensions.graffle0000644000000000000000000012063415004363604021726 0ustar rootroot CanvasColor w 1.000000e+00 ColumnAlign 0 ColumnSpacing 5.400000e+01 GraphDocumentVersion 2 GraphicsList Bounds {{5.66667, 9.66667}, {176, 36}} Class ShapedGraphic FitText YES ID 1681 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-BoldOblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\b\fs48 \cf0 NGExtensions} Class Group Graphics Class Group Graphics Bounds {{531, 72}, {135, 18}} Class ShapedGraphic ID 1677 Shape RoundedRectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NSBundle} Bounds {{531, 108}, {135, 18}} Class ShapedGraphic ID 1678 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGBundleManager.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGBundle} Class LineGraphic Head ID 1678 ID 1679 Points {598.5, 90} {598.5, 108} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1677 ID 1676 Bounds {{531, 36}, {135, 18}} Class ShapedGraphic ID 1680 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGBundleManager.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGBundleManager} ID 1675 Class Group Graphics Bounds {{603, 504}, {63, 18}} Class ShapedGraphic ID 1669 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGBitSet.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGBitSet} Bounds {{522, 504}, {63, 18}} Class ShapedGraphic ID 1670 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGBitSet.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGBitSet} Bounds {{603, 468}, {63, 18}} Class ShapedGraphic ID 1671 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGStack.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGStack} Bounds {{522, 468}, {63, 18}} Class ShapedGraphic ID 1672 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGStack.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGStack} Class LineGraphic Head ID 1670 ID 1673 Points {603, 513} {585, 513} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1669 Class LineGraphic Head ID 1672 ID 1674 Points {603, 477} {585, 477} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1671 ID 1668 Bounds {{198, 279}, {144, 18}} Class ShapedGraphic ID 1667 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGFileManager} Bounds {{36, 324}, {144, 18}} Class ShapedGraphic ID 1666 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGCustomFileManager.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGCustomFileManager} Bounds {{36, 279}, {144, 18}} Class ShapedGraphic ID 1665 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGFileManager} Class LineGraphic Head ID 1665 ID 1664 Points {198, 288} {180, 288} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 1667 Class LineGraphic Head ID 1666 ID 1663 Points {108, 297} {108, 324} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1665 Class Group Graphics Bounds {{198, 243}, {126, 18}} Class ShapedGraphic ID 1661 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManagerURL.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGFileManagerURL} Bounds {{198, 207}, {126, 18}} Class ShapedGraphic ID 1662 Shape RoundedRectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NSURL} ID 1660 Bounds {{531, 180}, {135, 18}} Class ShapedGraphic ID 1659 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGByteBuffer.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGByteBuffer} Class Group Graphics Bounds {{99, 495}, {126, 18}} Class ShapedGraphic ID 1652 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/EOGroupingSet.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOGroupingSet} Bounds {{27, 468}, {126, 18}} Class ShapedGraphic ID 1653 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/EOQualifierGrouping.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOQualifierGrouping} Bounds {{99, 432}, {126, 18}} Class ShapedGraphic ID 1654 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/EOGrouping.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOGrouping} Bounds {{171, 468}, {126, 18}} Class ShapedGraphic ID 1655 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/EOKeyGrouping.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOKeyGrouping} Class LineGraphic Head ID 1652 ID 1656 Points {162, 450} {162, 495} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1654 Class LineGraphic Head ID 1653 ID 1657 Points {144, 450} {108, 468} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1654 Class LineGraphic Head ID 1655 ID 1658 Points {180, 450} {216, 468} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1654 ID 1651 Bounds {{531, 153}, {135, 18}} Class ShapedGraphic ID 1650 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGCharBuffer.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGCharBuffer} Class Group Graphics Bounds {{36, 243}, {144, 18}} Class ShapedGraphic ID 1648 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGDirectoryEnumerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGDirectoryEnumerator} Bounds {{36, 207}, {144, 18}} Class ShapedGraphic ID 1649 Shape RoundedRectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NSEnumerator} ID 1647 Bounds {{27, 99}, {171, 18}} Class ShapedGraphic ID 1646 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/EOCompoundDataSource.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOCompoundDataSource} Bounds {{117, 135}, {171, 18}} Class ShapedGraphic ID 1645 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/EOCacheDataSource.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOCacheDataSource} Bounds {{234, 99}, {171, 18}} Class ShapedGraphic ID 1644 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/EOFilterDataSource.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOFilterDataSource} Bounds {{126, 54}, {171, 18}} Class ShapedGraphic ID 1643 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EODataSource.h Shape RoundedRectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EODataSource} Class LineGraphic Head ID 1646 ID 1642 Points {191.7, 72} {132.3, 99} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1643 Class LineGraphic Head ID 1645 ID 1641 Points {210.5, 72} {203.5, 135} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1643 Class LineGraphic Head ID 1644 ID 1640 Points {233.1, 72} {297.9, 99} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1643 Bounds {{198, 324}, {171, 18}} Class ShapedGraphic ID 1639 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileFolderInfoDataSource.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGFileFolderInfoDataSource} Class LineGraphic Head ID 1639 ID 1638 Points {213.9, 72} {281.1, 324} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1643 Bounds {{531, 207}, {135, 18}} Class ShapedGraphic ID 1637 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGMD5Generator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMD5Generator} Bounds {{522, 441}, {144, 18}} Class ShapedGraphic ID 1636 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGStack.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGStackException} Class Group Graphics Bounds {{540, 315}, {126, 18}} Class ShapedGraphic ID 1634 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGCString.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMutableCString} Bounds {{540, 279}, {126, 18}} Class ShapedGraphic ID 1635 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGCString.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGCString} ID 1633 Bounds {{315, 441}, {162, 18}} Class ShapedGraphic ID 1632 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGCustomFileManager.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGCustomFileManagerInfo} Class Group Graphics Bounds {{522, 360}, {144, 18}} Class ShapedGraphic ID 1630 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGHashMap.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGHashMap} Bounds {{522, 396}, {144, 18}} Class ShapedGraphic ID 1631 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGHashMap.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMutableHashMap} ID 1629 Class LineGraphic Head ID 1661 ID 1628 Points {261, 225} {261, 243} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1662 Class LineGraphic Head ID 1648 ID 1627 Points {108, 225} {108, 243} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1649 Class LineGraphic Head ID 1634 ID 1626 Points {603, 297} {603, 315} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1635 Class LineGraphic Head ID 1631 ID 1625 Points {594, 378} {594, 396} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 1630 GridInfo HPages 1 ImageCounter 1 IsPalette NO Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo AutoAdjust YES HierarchicalOrientation 0 MagneticFieldCenter {0, 0} MagnetsEnabled YES PageBreakColor w 3.333333e-01 PageBreaks YES PageSetup BAt0eXBlZHN0cmVhbYED6IQBQISEhAtOU1ByaW50SW5mbwGEhAhOU09iamVjdACFkoSE hBNOU011dGFibGVEaWN0aW9uYXJ5AISEDE5TRGljdGlvbmFyeQCUhAFpEpKEhIQITlNT dHJpbmcBlIQBKxBOU0pvYkRpc3Bvc2l0aW9uhpKEmZkPTlNQcmludFNwb29sSm9ihpKE mZkOTlNCb3R0b21NYXJnaW6GkoSEhAhOU051bWJlcgCEhAdOU1ZhbHVlAJSEASqEhAFm nSSGkoSZmQtOU1BhcGVyTmFtZYaShJmZBkxldHRlcoaShJmZD05TUHJpbnRBbGxQYWdl c4aShJ2chIQBc54AhpKEmZkNTlNSaWdodE1hcmdpboaShJ2cn50khpKEmZkITlNDb3Bp ZXOGkoSdnISEAVOfAYaShJmZD05TU2NhbGluZ0ZhY3RvcoaShJ2chIQBZKABhpKEmZkL TlNGaXJzdFBhZ2WGkoSdnKmfAYaShJmZFE5TVmVydGljYWxQYWdpbmF0aW9uhpKEnZyk ngCGkoSZmRVOU0hvcml6b25hbFBhZ2luYXRpb26GkoSdnKSeAIaShJmZFk5TSG9yaXpv bnRhbGx5Q2VudGVyZWSGkoSdnKSeAYaShJmZDE5TTGVmdE1hcmdpboaShJ2cn50khpKE mZkNTlNPcmllbnRhdGlvboaShJ2cpJ4BhpKEmZkZTlNQcmludFJldmVyc2VPcmllbnRh dGlvboaSo5KEmZkKTlNMYXN0UGFnZYaShJ2chJeXgn////+GkoSZmQtOU1RvcE1hcmdp boaShJ2cn50khpKEmZkUTlNWZXJ0aWNhbGx5Q2VudGVyZWSGkrSShJmZC05TUGFwZXJT aXplhpKEnpyEhAx7X05TU2l6ZT1mZn2hgQMYgQJkhoaG RowAlign 0 RowSpacing 9.000000e+00 VPages 1 WindowInfo Frame {{104, 118}, {794, 751}} VisibleRegion {{-159, -179}, {1038.67, 898.667}} Zoom 0.75 SOPE/sope-core/NGExtensions/NGBundleManager.m0000644000000000000000000016121215004363604017715 0ustar rootroot/* Copyright (C) 2000-2006 SKYRIX Software AG Copyright (C) 2006 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGBundleManager.h" #include "common.h" #include #include #import #import #include #if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY # include #endif #if LIB_FOUNDATION_LIBRARY @interface NSBundle(UsedPrivates) + (BOOL)isFlattenedDirLayout; @end #endif #if NeXT_RUNTIME || APPLE_RUNTIME #include //OBJC_EXPORT void objc_setClassHandler(int (*)(const char *)); static BOOL debugClassHook = NO; static BOOL hookDoLookup = YES; static int _getClassHook(const char *className) { // Cocoa variant if (className == NULL) return 0; if (debugClassHook) printf("lookup class '%s'.\n", className); if (objc_lookUpClass(className)) return 1; if (hookDoLookup) { static NGBundleManager *manager = nil; NSBundle *bundle; NSString *cns; if (debugClassHook) printf("%s: look for class %s\n", __PRETTY_FUNCTION__, className); if (manager == nil) manager = [NGBundleManager defaultBundleManager]; cns = [[NSString alloc] initWithCString:className]; bundle = [manager bundleForClassNamed:cns]; [cns release]; cns = nil; if (bundle != nil) { if (debugClassHook) { NSLog(@"%s: found bundle %@", __PRETTY_FUNCTION__, [bundle bundlePath]); } if (![manager loadBundle:bundle]) { fprintf(stderr, "bundleManager couldn't load bundle for class '%s'.\n", className); } #if 0 else { Class c = objc_lookUpClass(className); NSLog(@"%s: loaded bundle %@ for className %s class %@", __PRETTY_FUNCTION__, bundle, className, c); } #endif } } return 1; } #endif NSString *NGBundleWasLoadedNotificationName = @"NGBundleWasLoadedNotification"; @interface NSBundle(NGBundleManagerPrivate) - (BOOL)_loadForBundleManager:(NGBundleManager *)_manager; @end @interface NGBundleManager(PrivateMethods) - (void)registerBundle:(NSBundle *)_bundle classes:(NSArray *)_classes categories:(NSArray *)_categories; - (NSString *)pathForBundleProvidingResource:(NSString *)_resourceName ofType:(NSString *)_type resourceSelector:(NGBundleResourceSelector)_selector context:(void *)_ctx; - (NSString *)makeBundleInfoPath:(NSString *)_path; @end static BOOL _selectClassByVersion(NSString *_resourceName, NSString *_resourceType, NSString *_path, NSDictionary *_resourceConfig, NGBundleManager *_bundleManager, void *_version) { id tmp; int classVersion; if (![_resourceType isEqualToString:@"classes"]) return NO; if (_version == NULL) return YES; if ([(id)_version intValue] == -1) return YES; if ((tmp = [_resourceConfig objectForKey:@"version"])) { classVersion = [tmp intValue]; if (classVersion < [(id)_version intValue]) { NSLog(@"WARNING: class version mismatch for class %@: " @"requested at least version %i, got version %i", _resourceName, [(id)_version intValue], classVersion); } } if ((tmp = [_resourceConfig objectForKey:@"exact-version"])) { classVersion = [tmp intValue]; if (classVersion != [(id)_version intValue]) { NSLog(@"WARNING: class version mismatch for class %@: " @"requested exact version %i, got version %i", _resourceName, [(id)_version intValue], classVersion); } } return YES; } @implementation NGBundleManager // THREAD static NGBundleManager *defaultManager = nil; static BOOL debugOn = NO; #if defined(__MINGW32__) static NSString *NGEnvVarPathSeparator = @";"; #else static NSString *NGEnvVarPathSeparator = @":"; #endif + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; debugOn = [ud boolForKey:@"NGBundleManagerDebugEnabled"]; } + (id)defaultBundleManager { if (defaultManager == nil) { defaultManager = [[NGBundleManager alloc] init]; } return defaultManager; } /* setup bundle search path */ - (void)_addMainBundlePathToPathArray:(NSMutableArray *)_paths { NSProcessInfo *pi; NSString *path; pi = [NSProcessInfo processInfo]; path = [[pi arguments] objectAtIndex:0]; path = [path stringByDeletingLastPathComponent]; if ([path length] > 0) { // TODO: to be correct this would need to read the bundle-info // NSExecutable?! /* The path is the complete path to the executable, including the processor, the OS and the library combo. Strip these directories from the main bundle's path. */ path = [[[path stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent]; [_paths addObject:path]; } } - (void)_addBundlePathDefaultToPathArray:(NSMutableArray *)_paths { NSUserDefaults *ud; id paths; if ((ud = [NSUserDefaults standardUserDefaults]) == nil) { // got this with gstep-base during the port, apparently it happens // if the bundle manager is created inside the setup process of // gstep-base (for whatever reason) NSLog(@"ERROR(NGBundleManager): got no system userdefaults object!"); #if DEBUG abort(); #endif } if ((paths = [ud arrayForKey:@"NGBundlePath"]) == nil) { if ((paths = [ud stringForKey:@"NGBundlePath"]) != nil) paths = [paths componentsSeparatedByString:NGEnvVarPathSeparator]; } if (paths != nil) [_paths addObjectsFromArray:paths]; else if (debugOn) NSLog(@"Note: NGBundlePath default is not configured."); } - (void)_addEnvironmentPathToPathArray:(NSMutableArray *)_paths { NSProcessInfo *pi; id paths; pi = [NSProcessInfo processInfo]; paths = [[pi environment] objectForKey:@"NGBundlePath"]; if (paths) paths = [paths componentsSeparatedByString:NGEnvVarPathSeparator]; if (paths) [_paths addObjectsFromArray:paths]; } - (void)_addGNUstepPathsToPathArray:(NSMutableArray *)_paths { /* Old code for old gstep-make and gstep-base. */ NSDictionary *env; NSString *p; unsigned i, count; id tmp; env = [[NSProcessInfo processInfo] environment]; if ((tmp = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"]) == nil) tmp = [env objectForKey:@"GNUSTEP_PATHLIST"]; tmp = [tmp componentsSeparatedByString:@":"]; for (i = 0, count = [tmp count]; i < count; i++) { p = [tmp objectAtIndex:i]; p = [p stringByAppendingPathComponent:@"Library"]; p = [p stringByAppendingPathComponent:@"Bundles"]; if ([self->bundleSearchPaths containsObject:p]) continue; if (p) [self->bundleSearchPaths addObject:p]; } /* New code for new gstep-make and gstep-base. */ tmp = NSStandardLibraryPaths(); { NSEnumerator *e = [tmp objectEnumerator]; while ((tmp = [e nextObject]) != nil) { tmp = [tmp stringByAppendingPathComponent:@"Bundles"]; if ([self->bundleSearchPaths containsObject:tmp]) continue; [self->bundleSearchPaths addObject:tmp]; } } } - (void)_setupBundleSearchPathes { /* setup bundle search path */ self->bundleSearchPaths = [[NSMutableArray alloc] initWithCapacity:16]; [self _addMainBundlePathToPathArray:self->bundleSearchPaths]; [self _addBundlePathDefaultToPathArray:self->bundleSearchPaths]; [self _addEnvironmentPathToPathArray:self->bundleSearchPaths]; [self _addGNUstepPathsToPathArray:self->bundleSearchPaths]; #if DEBUG && NeXT_Foundation_LIBRARY && 0 NSLog(@"%s: bundle search pathes:\n%@", __PRETTY_FUNCTION__, self->bundleSearchPaths); #endif } - (void)_registerLoadedBundles { NSEnumerator *currentBundles; NSBundle *loadedBundle; currentBundles = [[NSBundle allBundles] objectEnumerator]; while ((loadedBundle = [currentBundles nextObject]) != nil) [self registerBundle:loadedBundle classes:nil categories:nil]; } - (void)_registerForBundleLoadNotification { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_bundleDidLoadNotifcation:) name:@"NSBundleDidLoadNotification" object:nil]; } - (id)init { #if GNUSTEP_BASE_LIBRARY if ([NSUserDefaults standardUserDefaults] == nil) { /* called inside setup process, deny creation (HACK) */ [self release]; return nil; } #endif if ((self = [super init])) { self->classToBundle = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks, NSNonRetainedObjectMapValueCallBacks, 32); self->classNameToBundle = NSCreateMapTable(NSObjectMapKeyCallBacks, NSNonRetainedObjectMapValueCallBacks, 32); self->categoryNameToBundle = NSCreateMapTable(NSObjectMapKeyCallBacks, NSNonRetainedObjectMapValueCallBacks, 32); self->pathToBundle = NSCreateMapTable(NSObjectMapKeyCallBacks, NSNonRetainedObjectMapValueCallBacks, 32); self->pathToBundleInfo = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 32); self->nameToBundle = NSCreateMapTable(NSObjectMapKeyCallBacks, NSNonRetainedObjectMapValueCallBacks, 32); self->loadedBundles = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 32); [self _setupBundleSearchPathes]; [self _registerLoadedBundles]; [self _registerForBundleLoadNotification]; } return self; } - (void)dealloc { [self->loadingBundles release]; if (self->loadedBundles) NSFreeMapTable(self->loadedBundles); if (self->classToBundle) NSFreeMapTable(self->classToBundle); if (self->classNameToBundle) NSFreeMapTable(self->classNameToBundle); if (self->categoryNameToBundle) NSFreeMapTable(self->categoryNameToBundle); if (self->pathToBundle) NSFreeMapTable(self->pathToBundle); if (self->pathToBundleInfo) NSFreeMapTable(self->pathToBundleInfo); if (self->nameToBundle) NSFreeMapTable(self->nameToBundle); [self->bundleSearchPaths release]; [super dealloc]; } /* accessors */ - (void)setBundleSearchPaths:(NSArray *)_paths { ASSIGNCOPY(self->bundleSearchPaths, _paths); } - (NSArray *)bundleSearchPaths { return self->bundleSearchPaths; } /* registering bundles */ - (void)registerBundle:(NSBundle *)_bundle classes:(NSArray *)_classes categories:(NSArray *)_categories { NSEnumerator *e; id v; #if NeXT_RUNTIME || APPLE_RUNTIME v = [_bundle bundlePath]; if ([v hasSuffix:@"Libraries"] || [v hasSuffix:@"Tools"]) { if (debugOn) fprintf(stderr, "INVALID BUNDLE: %s\n", [[_bundle bundlePath] cString]); return; } #endif #if 0 NSLog(@"NGBundleManager: register loaded bundle %@", [_bundle bundlePath]); #endif e = [_classes objectEnumerator]; while ((v = [e nextObject]) != nil) { #if NeXT_RUNTIME || APPLE_RUNTIME hookDoLookup = NO; #endif NSMapInsert(self->classToBundle, NSClassFromString(v), _bundle); NSMapInsert(self->classNameToBundle, v, _bundle); #if NeXT_RUNTIME || APPLE_RUNTIME hookDoLookup = YES; #endif } e = [_categories objectEnumerator]; while ((v = [e nextObject]) != nil) NSMapInsert(self->categoryNameToBundle, v, _bundle); } /* bundle locator */ - (NSString *)pathForBundleWithName:(NSString *)_name type:(NSString *)_type { NSFileManager *fm = [NSFileManager defaultManager]; NSEnumerator *e; NSString *path; NSString *bundlePath; NSBundle *bundle; /* first check in table */ bundlePath = [_name stringByAppendingPathExtension:_type]; if ((bundle = NSMapGet(self->nameToBundle, bundlePath))) return [bundle bundlePath]; e = [self->bundleSearchPaths objectEnumerator]; while ((path = [e nextObject])) { BOOL isDir = NO; if ([fm fileExistsAtPath:path isDirectory:&isDir]) { if (!isDir) continue; if ([[path lastPathComponent] isEqualToString:bundlePath]) { // direct match (a bundle was specified in the path) return path; } else { NSString *tmp; tmp = [path stringByAppendingPathComponent:bundlePath]; if ([fm fileExistsAtPath:tmp isDirectory:&isDir]) { if (isDir) // found bundle return tmp; } } } } return nil; } /* getting bundles */ - (NSBundle *)bundleForClass:(Class)aClass { /* this method never loads a dynamic bundle (since the class is set up) */ NSBundle *bundle; if (aClass == Nil) return nil; bundle = NSMapGet(self->classToBundle, aClass); #if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY if (bundle == nil) { NSString *p; bundle = [NSBundle bundleForClass:aClass]; if (bundle == [NSBundle mainBundle]) bundle = nil; else { p = [bundle bundlePath]; if ([p hasSuffix:@"Libraries"]) { if (debugOn) { fprintf(stderr, "%s: Dylib bundle: 0x%p: %s\n", __PRETTY_FUNCTION__, bundle, [[bundle bundlePath] cString]); } bundle = nil; } else if ([p hasSuffix:@"Tools"]) { if (debugOn) { fprintf(stderr, "%s: Tool bundle: 0x%p: %s\n", __PRETTY_FUNCTION__, bundle, [[bundle bundlePath] cString]); } bundle = nil; } } } #endif if (bundle == nil) { /* if the class wasn't loaded from a bundle, it's *either* the main bundle or a bundle loaded before NGExtension was loaded !!! */ #if !LIB_FOUNDATION_LIBRARY && !GNUSTEP_BASE_LIBRARY // Note: incorrect behaviour if NGExtensions is dynamically loaded ! // TODO: can we do anything about this? Can we detect the situation and // print a log instead of the compile warning? // Note: the above refers to the situation when a framework is implicitly // loaded by loading a bundle (the framework is not linked against // the main tool) #endif bundle = [NSBundle mainBundle]; NSMapInsert(self->classToBundle, aClass, bundle); NSMapInsert(self->classNameToBundle, NSStringFromClass(aClass), bundle); } return bundle; } - (NSBundle *)bundleWithPath:(NSString *)path { NSBundle *bundle = nil; NSString *bn; path = [path stringByResolvingSymlinksInPath]; if (path == nil) return nil; if (debugOn) NSLog(@"find bundle for path: '%@'", path); bundle = NSMapGet(self->pathToBundle, path); if (bundle) { if (debugOn) NSLog(@" found: %@", bundle); return bundle; } if ((bundle = [(NGBundle *)[NGBundle alloc] initWithPath:path]) == nil) { [self errorWithFormat: @"could not create bundle for path: '%@'", path]; return nil; } bn = [[bundle bundleName] stringByAppendingPathExtension:[bundle bundleType]], NSMapInsert(self->pathToBundle, path, bundle); NSMapInsert(self->nameToBundle, bn, bundle); return bundle; } - (NSBundle *)bundleWithName:(NSString *)_name type:(NSString *)_type { NSBundle *bundle; NSString *bn; bn = [_name stringByAppendingPathExtension:_type]; bundle = NSMapGet(self->nameToBundle, bn); if (![bundle isNotNull]) { bundle = [self bundleWithPath: [self pathForBundleWithName:_name type:_type]]; } if (![bundle isNotNull]) /* NSNull is used to signal missing bundles */ return nil; if (![[bundle bundleType] isEqualToString:_type]) return nil; /* bundle matches */ return bundle; } - (NSBundle *)bundleWithName:(NSString *)_name { return [self bundleWithName:_name type:@"bundle"]; } - (NSBundle *)bundleForClassNamed:(NSString *)_className { NSString *path = nil; NSBundle *bundle = nil; if (_className == nil) return nil; /* first check in table */ if ((bundle = NSMapGet(self->classNameToBundle, _className)) != nil) return bundle; path = [self pathForBundleProvidingResource:_className ofType:@"classes" resourceSelector:_selectClassByVersion context:NULL /* version */]; if (path != nil) { path = [path stringByResolvingSymlinksInPath]; NSAssert(path, @"couldn't resolve symlinks in path .."); } if (path == nil) return nil; if ((bundle = [self bundleWithPath:path]) != nil) NSMapInsert(self->classNameToBundle, _className, bundle); return bundle; } // dependencies + (NSInteger)version { return 2; } - (NSArray *)bundlesRequiredByBundle:(NSBundle *)_bundle { [self doesNotRecognizeSelector:_cmd]; return nil; } - (NSArray *)classesProvidedByBundle:(NSBundle *)_bundle { return [[_bundle providedResourcesOfType:@"classes"] valueForKey:@"name"]; } - (NSArray *)classesRequiredByBundle:(NSBundle *)_bundle { [self doesNotRecognizeSelector:_cmd]; return nil; } /* initialization */ - (NSString *)makeBundleInfoPath:(NSString *)_path { #if (NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY) && !defined(GSWARN) return [[[_path stringByAppendingPathComponent:@"Contents"] stringByAppendingPathComponent:@"Resources"] stringByAppendingPathComponent:@"bundle-info.plist"]; #else return [_path stringByAppendingPathComponent:@"bundle-info.plist"]; #endif } - (id)_initializeLoadedBundle:(NSBundle *)_bundle info:(NSDictionary *)_bundleInfo { id handler; /* check whether a handler was specified */ if ((handler = [_bundleInfo objectForKey:@"bundleHandler"]) != nil) { [self debugWithFormat:@"lookup bundle handler %@ of bundle: %@", handler, _bundle]; if ((handler = NSClassFromString(handler)) == nil) { NSLog(@"ERROR: did not find handler class %@ of bundle %@.", [_bundleInfo objectForKey:@"bundleHandler"], [_bundle bundlePath]); handler = [_bundle principalClass]; } handler = [handler alloc]; if ([handler respondsToSelector:@selector(initForBundle:bundleManager:)]) handler = [handler initForBundle:_bundle bundleManager:self]; else handler = [handler init]; handler = [handler autorelease]; if (handler == nil) { NSLog(@"ERROR: could not instantiate handler class %@ of bundle %@.", [_bundleInfo objectForKey:@"bundleHandler"], [_bundle bundlePath]); handler = [_bundle principalClass]; } } else { [self debugWithFormat: @"no bundle handler, lookup principal class of bundle: %@", _bundle]; if ((handler = [_bundle principalClass]) == nil) { /* use NGBundle class as default bundle handler */ #if !(NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY) [self warnWithFormat:@"bundle has no principal class: %@", _bundle]; #endif handler = [NGBundle class]; } else [self debugWithFormat:@" => %@", handler]; } return handler; } /* loading */ - (NSDictionary *)_loadBundleInfoAtExistingPath:(NSString *)_path { NSDictionary *bundleInfo; id info; #if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY bundleInfo = NGParsePropertyListFromFile(_path); #else bundleInfo = [NSDictionary dictionaryWithContentsOfFile:_path]; #endif if (bundleInfo == nil) { NSLog(@"could not load bundle-info at path '%@' !", _path); return nil; } /* check required bundle manager version */ info = [bundleInfo objectForKey:@"requires"]; if ((info = [(NSDictionary *)info objectForKey:@"bundleManagerVersion"])) { if ([info intValue] > [[self class] version]) { /* bundle manager version does not match ... */ return nil; } } NSMapInsert(self->pathToBundleInfo, _path, bundleInfo); return bundleInfo; } - (NSBundle *)_locateBundleForClassInfo:(NSDictionary *)_classInfo { NSString *className; NSBundle *bundle; if (_classInfo == nil) return nil; if ((className = [_classInfo objectForKey:@"name"]) == nil) { NSLog(@"ERROR: missing classname in bundle-info.plist class section !"); return nil; } // TODO: do we need to check the runtime for already loaded classes? // Yes, I think so. But avoid recursions #if 0 #if APPLE_Foundation_LIBRARY || COCOA_Foundation_LIBRARY // TODO: HACK, see above. w/o this, we get issues. if ([className hasPrefix:@"NS"]) return nil; #endif #endif if ((bundle = [self bundleForClassNamed:className]) == nil) { #if 0 // class might be already loaded NSLog(@"ERROR: did not find class %@ required by bundle %@.", className, [_bundle bundlePath]); #endif } if (debugOn) NSLog(@"CLASS %@ => BUNDLE %@", className, bundle); return bundle; } - (NSArray *)_locateBundlesForClassInfos:(NSEnumerator *)_classInfos { NSMutableArray *requiredBundles; NSDictionary *i; requiredBundles = [NSMutableArray arrayWithCapacity:16]; while ((i = [_classInfos nextObject]) != nil) { NSBundle *bundle; if ((bundle = [self _locateBundleForClassInfo:i]) == nil) continue; [requiredBundles addObject:bundle]; } return requiredBundles; } - (BOOL)_preLoadBundle:(NSBundle *)_bundle info:(NSDictionary *)_bundleInfo { /* TODO: split up this huge method */ NSDictionary *requires; NSMutableArray *requiredBundles = nil; NSBundle *requiredBundle = nil; if (debugOn) NSLog(@"NGBundleManager: preload bundle: %@", _bundle); requires = [_bundleInfo objectForKey:@"requires"]; if (requires == nil) /* invalid bundle info specified */ return YES; /* load required bundles */ { NSEnumerator *e; NSDictionary *i; /* locate required bundles */ e = [[requires objectForKey:@"bundles"] objectEnumerator]; while ((i = [e nextObject]) != nil) { NSString *bundleName; if (![i respondsToSelector:@selector(objectForKey:)]) { NSLog(@"ERROR(%s): invalid bundle-info of bundle %@ !!!\n" @" requires-entry is not a dictionary: %@", __PRETTY_FUNCTION__, _bundle, i); continue; } if ((bundleName = [i objectForKey:@"name"])) { NSString *type; type = [i objectForKey:@"type"]; if (type == nil) type = @"bundle"; if ((requiredBundle = [self bundleWithName:bundleName type:type])) { if (requiredBundles == nil) requiredBundles = [NSMutableArray arrayWithCapacity:16]; [requiredBundles addObject:requiredBundle]; } else { NSLog(@"ERROR(NGBundleManager): did not find bundle '%@' (type=%@) " @"required by bundle %@.", bundleName, type, [_bundle bundlePath]); continue; } } else NSLog(@"ERROR: error in bundle-info.plist of bundle %@", _bundle); } } /* load located bundles */ { NSEnumerator *e; if (debugOn) { NSLog(@"NGBundleManager: preload required bundles: %@", requiredBundles); } e = [requiredBundles objectEnumerator]; while ((requiredBundle = [e nextObject]) != nil) { Class bundleMaster; if ((bundleMaster = [self loadBundle:requiredBundle]) == Nil) { NSLog(@"ERROR: could not load bundle %@ (%@) required by bundle %@.", [requiredBundle bundlePath], requiredBundle, [_bundle bundlePath]); continue; } } } /* load required classes */ { NSArray *bundles; NSArray *reqClasses; reqClasses = [requires objectForKey:@"classes"]; bundles = [self _locateBundlesForClassInfos:[reqClasses objectEnumerator]]; if (requiredBundles == nil) requiredBundles = [NSMutableArray arrayWithCapacity:16]; [requiredBundles addObjectsFromArray:bundles]; } /* load located bundles */ { NSEnumerator *e; e = [requiredBundles objectEnumerator]; while ((requiredBundle = [e nextObject]) != nil) { Class bundleMaster; if ((bundleMaster = [self loadBundle:requiredBundle]) == Nil) { NSLog(@"ERROR: could not load bundle %@ (%@) required by bundle %@.", [requiredBundle bundlePath], requiredBundle, [_bundle bundlePath]); continue; } } } /* check whether versions of classes match */ { NSEnumerator *e; NSDictionary *i; e = [[requires objectForKey:@"classes"] objectEnumerator]; while ((i = [e nextObject]) != nil) { NSString *className; Class clazz; if ((className = [i objectForKey:@"name"]) == nil) continue; if ((clazz = NSClassFromString(className)) == Nil) continue; if ([i objectForKey:@"exact-version"]) { NSInteger v; v = [[i objectForKey:@"exact-version"] integerValue]; if (v != [clazz version]) { NSLog(@"ERROR: required exact class match failed:\n" @" class: %@\n" @" required version: %"PRIiPTR"\n" @" loaded version: %"PRIiPTR"\n" @" bundle: %@", className, v, [clazz version], [_bundle bundlePath]); } } else if ([i objectForKey:@"version"]) { NSInteger v; v = [[i objectForKey:@"version"] intValue]; if (v > [clazz version]) { NSLog(@"ERROR: provided class does not match required version:\n" @" class: %@\n" @" least required version: %"PRIiPTR"\n" @" loaded version: %"PRIiPTR"\n" @" bundle: %@", className, v, [clazz version], [_bundle bundlePath]); } } } } return YES; } - (BOOL)_postLoadBundle:(NSBundle *)_bundle info:(NSDictionary *)_bundleInfo { return YES; } - (id)loadBundle:(NSBundle *)_bundle { NSString *path = nil; NSDictionary *bundleInfo = nil; id bundleManager = nil; #if DEBUG NSAssert(self->loadedBundles, @"missing loadedBundles hashmap .."); #endif if ((bundleManager = NSMapGet(self->loadedBundles, _bundle))) return bundleManager; if (_bundle == [NSBundle mainBundle]) return [NSBundle mainBundle]; if ([self->loadingBundles containsObject:_bundle]) // recursive call return nil; if (self->loadingBundles == nil) self->loadingBundles = [[NSMutableSet allocWithZone:[self zone]] init]; [self->loadingBundles addObject:_bundle]; path = [_bundle bundlePath]; path = [self makeBundleInfoPath:path]; if ((bundleInfo = NSMapGet(self->pathToBundleInfo, path)) == nil) { if ([[NSFileManager defaultManager] fileExistsAtPath:path]) bundleInfo = [self _loadBundleInfoAtExistingPath:path]; } if (![self _preLoadBundle:_bundle info:bundleInfo]) goto done; if (debugOn) NSLog(@"NGBundleManager: will load bundle: %@", _bundle); if (![_bundle _loadForBundleManager:self]) goto done; if (debugOn) NSLog(@"NGBundleManager: did load bundle: %@", _bundle); if (![self _postLoadBundle:_bundle info:bundleInfo]) goto done; if ((bundleManager = [self _initializeLoadedBundle:_bundle info:bundleInfo])) { NSMapInsert(self->loadedBundles, _bundle, bundleManager); if ([bundleManager respondsToSelector: @selector(bundleManager:didLoadBundle:)]) [bundleManager bundleManager:self didLoadBundle:_bundle]; } #if 0 else { NSLog(@"ERROR(%s): couldn't initialize loaded bundle '%@'", __PRETTY_FUNCTION__, [_bundle bundlePath]); } #endif done: [self->loadingBundles removeObject:_bundle]; if (bundleManager) { if (bundleInfo == nil) bundleInfo = [NSDictionary dictionary]; [[NSNotificationCenter defaultCenter] postNotificationName: NGBundleWasLoadedNotificationName object:_bundle userInfo:[NSDictionary dictionaryWithObjectsAndKeys: self, @"NGBundleManager", bundleManager, @"NGBundleHandler", bundleInfo, @"NGBundleInfo", nil]]; } return bundleManager; } // manager - (id)principalObjectOfBundle:(NSBundle *)_bundle { return (id)NSMapGet(self->loadedBundles, _bundle); } // resources static BOOL _doesInfoMatch(NSArray *keys, NSDictionary *dict, NSDictionary *info) { int i, count; for (i = 0, count = [keys count]; i < count; i++) { NSString *key; id kv, vv; key = [keys objectAtIndex:i]; vv = [info objectForKey:key]; if (vv == nil) { /* info has no matching key */ return NO; } kv = [dict objectForKey:key]; if (![kv isEqual:vv]) return NO; } return YES; } - (NSDictionary *)configForResource:(id)_resource ofType:(NSString *)_type providedByBundle:(NSBundle *)_bundle { NSDictionary *bundleInfo = nil; NSString *infoPath; NSEnumerator *providedResources; NSArray *rnKeys = nil; id info; if ([_resource respondsToSelector:@selector(objectForKey:)]) { rnKeys = [_resource allKeys]; } infoPath = [self makeBundleInfoPath:[_bundle bundlePath]]; /* check whether info is in cache */ if ((bundleInfo = NSMapGet(self->pathToBundleInfo, infoPath)) == nil) { if (![[NSFileManager defaultManager] fileExistsAtPath:infoPath]) /* no bundle-info.plist available .. */ return nil; /* load info */ bundleInfo = [self _loadBundleInfoAtExistingPath:infoPath]; } /* get provided resources config */ providedResources = [[(NSDictionary *)[bundleInfo objectForKey:@"provides"] objectForKey:_type] objectEnumerator]; if (providedResources == nil) return nil; /* scan provided resources */ while ((info = [providedResources nextObject])) { if (rnKeys) { if (!_doesInfoMatch(rnKeys, _resource, info)) continue; } else { NSString *name; name = [[(NSDictionary *)info objectForKey:@"name"] stringValue]; if (name == nil) continue; if (![name isEqualToString:_resource]) continue; } return info; } return nil; } - (void)_processInfoForProvidedResources:(NSDictionary *)info ofType:(NSString *)_type path:(NSString *)path resourceName:(NSString *)_resourceName resourceSelector:(NGBundleResourceSelector)_selector context:(void *)_context andAddToResultArray:(NSMutableArray *)result { NSEnumerator *providedResources = nil; if (info == nil) return; /* direct match (a bundle was specified in the path) */ providedResources = [[(NSDictionary *)[info objectForKey:@"provides"] objectForKey:_type] objectEnumerator]; info = nil; if (providedResources == nil) return; /* scan provide array */ while ((info = [providedResources nextObject])) { NSString *name; if ((name = [[info objectForKey:@"name"] stringValue]) == nil) continue; if (_resourceName) { if (![name isEqualToString:_resourceName]) continue; } if (_selector) { if (!_selector(_resourceName, _type, path, info, self, _context)) continue; } [result addObject:path]; } } - (NSArray *)pathsForBundlesProvidingResource:(NSString *)_resourceName ofType:(NSString *)_type resourceSelector:(NGBundleResourceSelector)_selector context:(void *)_context { /* TODO: split up method */ NSMutableArray *result = nil; NSFileManager *fm; NSEnumerator *e; NSString *path; if (debugOn) { NSLog(@"BM LOOKUP pathes (%"PRIuPTR" bundles loaded): %@ / %@", NSCountMapTable(self->loadedBundles), _resourceName, _type); } fm = [NSFileManager defaultManager]; result = [NSMutableArray arrayWithCapacity:64]; // TODO: look in loaded bundles /* check physical pathes */ e = [self->bundleSearchPaths objectEnumerator]; while ((path = [e nextObject]) != nil) { NSEnumerator *dir; BOOL isDir = NO; NSString *tmp, *bundleDirPath; id info = nil; if (![fm fileExistsAtPath:path isDirectory:&isDir]) continue; if (!isDir) continue; /* check whether an appropriate bundle is contained in 'path' */ dir = [[fm directoryContentsAtPath:path] objectEnumerator]; while ((bundleDirPath = [dir nextObject]) != nil) { NSDictionary *bundleInfo = nil; NSEnumerator *providedResources = nil; NSString *infoPath; id info; bundleDirPath = [path stringByAppendingPathComponent:bundleDirPath]; infoPath = [self makeBundleInfoPath:bundleDirPath]; // TODO: can we use _doesBundleInfo:path:providedResource:... ? if ((bundleInfo = NSMapGet(self->pathToBundleInfo, infoPath))==nil) { if (![fm fileExistsAtPath:infoPath]) continue; bundleInfo = [self _loadBundleInfoAtExistingPath:infoPath]; } providedResources = [[(NSDictionary *)[bundleInfo objectForKey:@"provides"] objectForKey:_type] objectEnumerator]; if (providedResources == nil) continue; /* scan 'provides' array */ while ((info = [providedResources nextObject])) { NSString *name; name = [[(NSDictionary *)info objectForKey:@"name"] stringValue]; if (name == nil) continue; if (_resourceName != nil) { if (![name isEqualToString:_resourceName]) continue; } if (_selector != NULL) { if (!_selector(name, _type, bundleDirPath, info, self, _context)) continue; } [result addObject:bundleDirPath]; break; } } /* check for direct match (NGBundlePath element is a bundle) */ tmp = [self makeBundleInfoPath:path]; if ((info = NSMapGet(self->pathToBundleInfo, tmp)) == nil) { if ([fm fileExistsAtPath:tmp]) info = [self _loadBundleInfoAtExistingPath:tmp]; } [self _processInfoForProvidedResources:info ofType:_type path:path resourceName:_resourceName resourceSelector:_selector context:_context andAddToResultArray:result]; } if ([result count] == 0) { [self logWithFormat: @"Note(%s): method does not search in loaded bundles for " @"resources of type '%@'", __PRETTY_FUNCTION__, _type]; } return [[result copy] autorelease]; } - (BOOL)_doesBundleInfo:(NSDictionary *)_bundleInfo path:(NSString *)_path provideResource:(id)_resourceName ofType:(NSString *)_type rnKeys:(NSArray *)_rnKeys resourceSelector:(NGBundleResourceSelector)_selector context:(void *)_context { NSEnumerator *providedResources; NSDictionary *info; providedResources = [[(NSDictionary *)[_bundleInfo objectForKey:@"provides"] objectForKey:_type] objectEnumerator]; if (providedResources == nil) return NO; /* scan provide array */ while ((info = [providedResources nextObject])) { if (_rnKeys != nil) { if (!_doesInfoMatch(_rnKeys, _resourceName, info)) continue; } else { NSString *name; name = [[(NSDictionary *)info objectForKey:@"name"] stringValue]; if (name == nil) continue; if (![name isEqualToString:_resourceName]) continue; } if (_selector != NULL) { if (!_selector(_resourceName, _type, _path, info, self, _context)) continue; } /* all conditions applied (found) */ return YES; } return NO; } - (NSString *)pathOfLoadedBundleProvidingResource:(id)_resourceName ofType:(NSString *)_type resourceSelector:(NGBundleResourceSelector)_selector context:(void *)_context { NSMapEnumerator menum; NSString *path; NSDictionary *bundleInfo; NSArray *rnKeys; rnKeys = ([_resourceName respondsToSelector:@selector(objectForKey:)]) ? [_resourceName allKeys] : (NSArray *)nil; menum = NSEnumerateMapTable(self->pathToBundleInfo); while (NSNextMapEnumeratorPair(&menum, (void *)&path, (void *)&bundleInfo)) { if (debugOn) { NSLog(@"check loaded bundle for resource %@: %@", _resourceName, path); } if ([self _doesBundleInfo:bundleInfo path:path provideResource:_resourceName ofType:_type rnKeys:rnKeys resourceSelector:_selector context:_context]) /* strip bundle-info.plist name */ return [path stringByDeletingLastPathComponent]; } return nil; } - (NSString *)pathForBundleProvidingResource:(id)_resourceName ofType:(NSString *)_type resourceSelector:(NGBundleResourceSelector)_selector context:(void *)_context { /* main path lookup method */ // TODO: this method seriously needs some refactoring NSFileManager *fm; NSEnumerator *e; NSString *path; NSArray *rnKeys = nil; if (debugOn) { NSLog(@"BM LOOKUP path (%"PRIuPTR" bundles loaded): %@ / %@", NSCountMapTable(self->loadedBundles), _resourceName, _type); } /* look in loaded bundles */ path = [self pathOfLoadedBundleProvidingResource:_resourceName ofType:_type resourceSelector:_selector context:_context]; if (path != nil) return path; /* look in filesystem */ if ([_resourceName respondsToSelector:@selector(objectForKey:)]) { rnKeys = [_resourceName allKeys]; } fm = [NSFileManager defaultManager]; e = [self->bundleSearchPaths objectEnumerator]; while ((path = [e nextObject]) != nil) { NSEnumerator *dir; BOOL isDir = NO; NSString *tmp; id info = nil; if (![fm fileExistsAtPath:path isDirectory:&isDir]) continue; if (!isDir) continue; /* check whether an appropriate bundle is contained in 'path' */ dir = [[fm directoryContentsAtPath:path] objectEnumerator]; while ((tmp = [dir nextObject]) != nil) { NSDictionary *bundleInfo = nil; NSString *infoPath; tmp = [path stringByAppendingPathComponent:tmp]; infoPath = [self makeBundleInfoPath:tmp]; if (debugOn) NSLog(@"check path path=%@ info=%@", tmp, infoPath); if ((bundleInfo = NSMapGet(self->pathToBundleInfo, infoPath)) == nil) { if (![fm fileExistsAtPath:infoPath]) continue; bundleInfo = [self _loadBundleInfoAtExistingPath:infoPath]; } if (debugOn) NSLog(@"found info for path=%@ info=%@: %@", tmp,infoPath,bundleInfo); if ([self _doesBundleInfo:bundleInfo path:tmp provideResource:_resourceName ofType:_type rnKeys:rnKeys resourceSelector:_selector context:_context]) return tmp; } /* check for direct match */ tmp = [self makeBundleInfoPath:path]; if ((info = NSMapGet(self->pathToBundleInfo, tmp)) == nil) { if ([fm fileExistsAtPath:tmp]) info = [self _loadBundleInfoAtExistingPath:tmp]; else if (debugOn) { NSLog(@"WARNING(%s): did not find direct path '%@'", __PRETTY_FUNCTION__, tmp); } } if (info != nil) { // direct match (a bundle was specified in the path) NSEnumerator *providedResources; NSDictionary *provides; provides = [(NSDictionary *)info objectForKey:@"provides"]; providedResources = [[provides objectForKey:_type] objectEnumerator]; info = nil; if (providedResources == nil) continue; // scan provide array while ((info = [providedResources nextObject])) { if (rnKeys) { if (!_doesInfoMatch(rnKeys, _resourceName, info)) continue; } else { NSString *name; name = [[(NSDictionary *)info objectForKey:@"name"] stringValue]; if (name == nil) continue; if (![name isEqualToString:_resourceName]) continue; } if (_selector) { if (!_selector(_resourceName, _type, tmp, info, self, _context)) continue; } /* all conditions applied */ return tmp; } } } return nil; } - (NSBundle *)bundleProvidingResource:(id)_name ofType:(NSString *)_type { NSString *bp; if (debugOn) NSLog(@"BM LOOKUP: %@ / %@", _name, _type); bp = [self pathForBundleProvidingResource:_name ofType:_type resourceSelector:NULL context:nil]; if ([bp length] == 0) { #if (NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY) && HEAVY_DEBUG NSLog(@"%s: found no resource '%@' of type '%@' ...", __PRETTY_FUNCTION__, _resourceName, _resourceType); #endif if (debugOn) NSLog(@" did not find: %@ / %@", _name, _type); return nil; } if (debugOn) NSLog(@" FOUND: %@", bp); return [self bundleWithPath:bp]; } - (NSArray *)bundlesProvidingResource:(id)_resourceName ofType:(NSString *)_type { NSArray *paths; NSMutableArray *bundles; int i, count; paths = [self pathsForBundlesProvidingResource:_resourceName ofType:_type resourceSelector:NULL context:nil]; count = [paths count]; if (paths == nil) return nil; if (count == 0) return paths; bundles = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) { NSBundle *bundle; if ((bundle = [self bundleWithPath:[paths objectAtIndex:i]])) [bundles addObject:bundle]; } return [[bundles copy] autorelease]; } - (NSArray *)providedResourcesOfType:(NSString *)_resourceType inBundle:(NSBundle *)_bundle { NSString *path; NSDictionary *bundleInfo; path = [self makeBundleInfoPath:[_bundle bundlePath]]; if (path == nil) return nil; /* retrieve bundle info dictionary */ if ((bundleInfo = NSMapGet(self->pathToBundleInfo, path)) == nil) bundleInfo = [self _loadBundleInfoAtExistingPath:path]; return [(NSDictionary *)[bundleInfo objectForKey:@"provides"] objectForKey:_resourceType]; } - (void)_addRegisteredProvidedResourcesOfType:(NSString *)_type toSet:(NSMutableSet *)_result { NSMapEnumerator menum; NSString *path; NSDictionary *bundleInfo; menum = NSEnumerateMapTable(self->pathToBundleInfo); while (NSNextMapEnumeratorPair(&menum, (void *)&path, (void *)&bundleInfo)) { NSArray *providedResources; if (debugOn) NSLog(@"check loaded bundle for resource types %@: %@", _type, path); providedResources = [(NSDictionary *)[bundleInfo objectForKey:@"provides"] objectForKey:_type]; if (providedResources == nil) continue; [_result addObjectsFromArray:providedResources]; } } - (NSArray *)providedResourcesOfType:(NSString *)_resourceType { NSMutableSet *result = nil; NSFileManager *fm = [NSFileManager defaultManager]; NSEnumerator *e; NSString *path; result = [NSMutableSet setWithCapacity:128]; /* scan loaded bundles */ [self _addRegisteredProvidedResourcesOfType:_resourceType toSet:result]; /* scan all bundle search paths */ e = [self->bundleSearchPaths objectEnumerator]; while ((path = [e nextObject]) != nil) { NSEnumerator *dir; BOOL isDir = NO; NSString *tmp; id info = nil; if (![fm fileExistsAtPath:path isDirectory:&isDir]) continue; if (!isDir) continue; /* check whether an appropriate bundle is contained in 'path' */ // TODO: move to own method dir = [[fm directoryContentsAtPath:path] objectEnumerator]; while ((tmp = [dir nextObject]) != nil) { NSDictionary *bundleInfo = nil; NSArray *providedResources = nil; NSString *infoPath; tmp = [path stringByAppendingPathComponent:tmp]; infoPath = [self makeBundleInfoPath:tmp]; #if 0 NSLog(@" info path: %@", tmp); #endif if ((bundleInfo = NSMapGet(self->pathToBundleInfo, infoPath)) == nil) { if (![fm fileExistsAtPath:infoPath]) continue; bundleInfo = [self _loadBundleInfoAtExistingPath:infoPath]; } providedResources = [(NSDictionary *)[bundleInfo objectForKey:@"provides"] objectForKey:_resourceType]; if (providedResources == nil) continue; [result addObjectsFromArray:providedResources]; } /* check for direct match */ tmp = [self makeBundleInfoPath:path]; if ((info = NSMapGet(self->pathToBundleInfo, tmp)) == nil) { if ([fm fileExistsAtPath:tmp]) info = [self _loadBundleInfoAtExistingPath:tmp]; } if (info != nil) { // direct match (a bundle was specified in the path) NSArray *providedResources; NSDictionary *provides; provides = [(NSDictionary *)info objectForKey:@"provides"]; providedResources = [provides objectForKey:_resourceType]; info = nil; if (providedResources == nil) continue; [result addObjectsFromArray:providedResources]; } } return [result allObjects]; } - (NSBundle *)bundleProvidingResourceOfType:(NSString *)_resourceType matchingQualifier:(EOQualifier *)_qual { NSFileManager *fm = [NSFileManager defaultManager]; NSEnumerator *e; NSString *path; /* foreach search path entry */ e = [self->bundleSearchPaths objectEnumerator]; while ((path = [e nextObject])) { BOOL isDir = NO; if ([fm fileExistsAtPath:path isDirectory:&isDir]) { NSString *tmp; id info = nil; if (!isDir) continue; /* check whether an appropriate bundle is contained in 'path' */ { NSEnumerator *dir; dir = [[fm directoryContentsAtPath:path] objectEnumerator]; while ((tmp = [dir nextObject])) { NSDictionary *bundleInfo; NSArray *providedResources; NSString *infoPath; tmp = [path stringByAppendingPathComponent:tmp]; infoPath = [self makeBundleInfoPath:tmp]; if ((bundleInfo=NSMapGet(self->pathToBundleInfo, infoPath)) == nil) { if (![fm fileExistsAtPath:infoPath]) continue; bundleInfo = [self _loadBundleInfoAtExistingPath:infoPath]; } bundleInfo = [bundleInfo objectForKey:@"provides"]; providedResources = [bundleInfo objectForKey:_resourceType]; bundleInfo = nil; if (providedResources == nil) continue; providedResources = [providedResources filteredArrayUsingQualifier:_qual]; if ([providedResources count] > 0) return [self bundleWithPath:tmp]; } } /* check for direct match */ tmp = [self makeBundleInfoPath:path]; if ((info = NSMapGet(self->pathToBundleInfo, tmp)) == nil) { if ([fm fileExistsAtPath:tmp]) info = [self _loadBundleInfoAtExistingPath:tmp]; } if (info) { // direct match (a bundle was specified in the path) NSArray *providedResources; NSDictionary *provides; provides = [(NSDictionary *)info objectForKey:@"provides"]; providedResources = [provides objectForKey:_resourceType]; info = nil; if (providedResources == nil) continue; providedResources = [providedResources filteredArrayUsingQualifier:_qual]; if ([providedResources count] > 0) return [self bundleWithPath:path]; } } } return nil; } - (NSBundle *)bundlesProvidingResourcesOfType:(NSString *)_resourceType matchingQualifier:(EOQualifier *)_qual { NSMutableArray *bundles = nil; NSFileManager *fm = [NSFileManager defaultManager]; NSEnumerator *e; NSString *path; bundles = [NSMutableArray arrayWithCapacity:128]; /* foreach search path entry */ e = [self->bundleSearchPaths objectEnumerator]; while ((path = [e nextObject])) { BOOL isDir = NO; if ([fm fileExistsAtPath:path isDirectory:&isDir]) { NSString *tmp; id info = nil; if (!isDir) continue; /* check whether an appropriate bundle is contained in 'path' */ { NSEnumerator *dir; dir = [[fm directoryContentsAtPath:path] objectEnumerator]; while ((tmp = [dir nextObject])) { NSDictionary *bundleInfo = nil; NSArray *providedResources = nil; NSString *infoPath; tmp = [path stringByAppendingPathComponent:tmp]; infoPath = [self makeBundleInfoPath:tmp]; if ((bundleInfo=NSMapGet(self->pathToBundleInfo, infoPath)) == nil) { if (![fm fileExistsAtPath:infoPath]) continue; bundleInfo = [self _loadBundleInfoAtExistingPath:infoPath]; } bundleInfo = [bundleInfo objectForKey:@"provides"]; providedResources = [bundleInfo objectForKey:_resourceType]; bundleInfo = nil; if (providedResources == nil) continue; providedResources = [providedResources filteredArrayUsingQualifier:_qual]; if ([providedResources count] > 0) [bundles addObject:[self bundleWithPath:tmp]]; } } /* check for direct match */ tmp = [self makeBundleInfoPath:path]; if ((info = NSMapGet(self->pathToBundleInfo, tmp)) == nil) { if ([fm fileExistsAtPath:tmp]) info = [self _loadBundleInfoAtExistingPath:tmp]; } if (info) { // direct match (a bundle was specified in the path) NSArray *providedResources; NSDictionary *provides; provides = [(NSDictionary *)info objectForKey:@"provides"]; providedResources = [provides objectForKey:_resourceType]; info = nil; if (providedResources == nil) continue; providedResources = [providedResources filteredArrayUsingQualifier:_qual]; if ([providedResources count] > 0) [bundles addObject:[self bundleWithPath:path]]; } } } return [[bundles copy] autorelease]; } /* notifications */ - (void)_bundleDidLoadNotifcation:(NSNotification *)_notification { NSDictionary *ui = [_notification userInfo]; #if 0 NSLog(@"bundle %@ did load with classes %@", [[_notification object] bundlePath], [ui objectForKey:@"NSLoadedClasses"]); #endif [self registerBundle:[_notification object] classes:[ui objectForKey:@"NSLoadedClasses"] categories:[ui objectForKey:@"NSLoadedCategories"]]; } /* debugging */ - (BOOL)isDebuggingEnabled { return debugOn; } @end /* NGBundleManager */ @implementation NSBundle(BundleManagerSupport) + (id)alloc { return [NGBundle alloc]; } + (id)allocWithZone:(NSZone *)zone { return [NGBundle allocWithZone:zone]; } #if !(NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY) //#warning remember, bundleForClass is not overridden ! #if 0 + (NSBundle *)bundleForClass:(Class)aClass { return [[NGBundleManager defaultBundleManager] bundleForClass:aClass]; } #endif + (NSBundle *)bundleWithPath:(NSString*)path { return [[NGBundleManager defaultBundleManager] bundleWithPath:path]; } #endif @end /* NSBundle(BundleManagerSupport) */ @implementation NSBundle(NGBundleManagerExtensions) - (id)principalObject { return [[NGBundleManager defaultBundleManager] principalObjectOfBundle:self]; } - (NSArray *)providedResourcesOfType:(NSString *)_resourceType { return [[NGBundleManager defaultBundleManager] providedResourcesOfType:_resourceType inBundle:self]; } - (NSString *)bundleName { return [[[self bundlePath] lastPathComponent] stringByDeletingPathExtension]; } - (NSString *)bundleType { return [[self bundlePath] pathExtension]; } - (NSArray *)providedClasses { return [[NGBundleManager defaultBundleManager] classesProvidedByBundle:self]; } - (NSArray *)requiredClasses { return [[NGBundleManager defaultBundleManager] classesRequiredByBundle:self]; } - (NSArray *)requiredBundles { return [[NGBundleManager defaultBundleManager] bundlesRequiredByBundle:self]; } - (NSDictionary *)configForResource:(id)_resource ofType:(NSString *)_type { return [[NGBundleManager defaultBundleManager] configForResource:_resource ofType:_type providedByBundle:self]; } /* loading */ - (BOOL)_loadForBundleManager:(NGBundleManager *)_manager { return [self load]; } @end /* NSBundle(NGBundleManagerExtensions) */ @implementation NSBundle(NGLanguageResourceExtensions) static BOOL debugLanguageLookup = NO; // locating resources - (NSString *)pathForResource:(NSString *)_name ofType:(NSString *)_ext inDirectory:(NSString *)_directory languages:(NSArray *)_languages { NSFileManager *fm; NSString *path = nil; int i, langCount; id (*objAtIdx)(id,SEL,int); if (debugLanguageLookup) { NSLog(@"LOOKUP(%s): %@ | %@ | %@ | %@", __PRETTY_FUNCTION__, _name, _ext, _directory, [_languages componentsJoinedByString:@","]); } path = [self bundlePath]; if ([_directory isNotNull]) { // TODO: should we change that? path = [path stringByAppendingPathComponent:_directory]; } else { #if (NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY) path = [path stringByAppendingPathComponent:@"Contents"]; #endif path = [path stringByAppendingPathComponent:@"Resources"]; } if (debugLanguageLookup) NSLog(@" BASE: %@", path); fm = [NSFileManager defaultManager]; if (![fm fileExistsAtPath:path]) return nil; if (_ext != nil) _name = [_name stringByAppendingPathExtension:_ext]; langCount = [_languages count]; objAtIdx = (langCount > 0) ? (void*)[_languages methodForSelector:@selector(objectAtIndex:)] : NULL; for (i = 0; i < langCount; i++) { NSString *language; NSString *lpath; language = objAtIdx ? objAtIdx(_languages, @selector(objectAtIndex:), i) : [_languages objectAtIndex:i]; language = [language stringByAppendingPathExtension:@"lproj"]; lpath = [path stringByAppendingPathComponent:language]; lpath = [lpath stringByAppendingPathComponent:_name]; if ([fm fileExistsAtPath:lpath]) return lpath; } if (debugLanguageLookup) NSLog(@" no language matched, check base: %@", path); /* now look into x.bundle/Resources/name.type */ if ([fm fileExistsAtPath:[path stringByAppendingPathComponent:_name]]) return [path stringByAppendingPathComponent:_name]; return nil; } - (NSString *)pathForResource:(NSString *)_name ofType:(NSString *)_ext languages:(NSArray *)_languages { NSString *path; path = [self pathForResource:_name ofType:_ext inDirectory:@"Resources" languages:_languages]; if (path) return path; path = [self pathForResource:_name ofType:_ext inDirectory:nil languages:_languages]; return path; } @end /* NSBundle(NGLanguageResourceExtensions) */ @implementation NGBundle + (id)alloc { return [self allocWithZone:NULL]; } + (id)allocWithZone:(NSZone*)zone { return NSAllocateObject(self, 0, zone); } - (id)initWithPath:(NSString *)__path { return [super initWithPath:__path]; } /* loading */ - (BOOL)_loadForBundleManager:(NGBundleManager *)_manager { return [super load]; } - (BOOL)load { NGBundleManager *bm; bm = [NGBundleManager defaultBundleManager]; return [bm loadBundle:self] ? YES : NO; } + (NSBundle *)bundleForClass:(Class)aClass { return [[NGBundleManager defaultBundleManager] bundleForClass:aClass]; } + (NSBundle *)bundleWithPath:(NSString*)path { return [[NGBundleManager defaultBundleManager] bundleWithPath:path]; } #if GNUSTEP_BASE_LIBRARY - (Class)principalClass { Class c; NSString *cname; if ((c = [super principalClass]) != Nil) return c; if ((cname = [[self infoDictionary] objectForKey:@"NSPrincipalClass"]) ==nil) return Nil; if ((c = NSClassFromString(cname)) != Nil) return c; NSLog(@"%s: did not find principal class named '%@' of bundle %@, dict: %@", __PRETTY_FUNCTION__, cname, self, [self infoDictionary]); return Nil; } /* description */ - (NSString *)description { char buffer[1024]; sprintf (buffer, "<%s %p fullPath: %s infoDictionary: %p loaded=%s>", (char*)class_getName([self class]), self, [[self bundlePath] cString], [self infoDictionary], [self isLoaded] ? "yes" : "no"); return [NSString stringWithCString:buffer]; } #endif @end /* NGBundle */ SOPE/sope-core/NGExtensions/ChangeLog0000644000000000000000000015367015004363604016371 0ustar rootroot2013-06-20 Jean Raby * NSObject+Logs.m (debugWithFormat:arguments:): check current logLevel value before calling [NGLogger logLevel:message:] This squelches debug message at lower log levels 2010-10-08 Wolfgang Sourdeau * NGBase64Coding.m (-[NSString dataByDecodingBase64]): free "dest" only when the decoding has failed, since the NSData object absorbs it anyway. 2010-10-07 Wolfgang Sourdeau * NGBase64Coding.m (-[NSString stringByEncodingBase64]): we treat the input string as utf8, which is a superset of ascii anyway, instead of using the default cstring encoding. Removed some useless calls to NSAssert. The result string is encoded in NSASCIIStringEncoding. In short, the output is now always a base64-encoded utf-8 string. (-[NSData stringByEncodingBase64]): same as the above. (-[NSString stringByDecodingBase64]): reverse of the above but assume the input string is in utf-8 and then in iso-latin-1, instead of the default cstring encoding. (-[NSData stringByDecodingBase64]): same as the above. 2010-08-11 Wolfgang Sourdeau * NGBase64Coding.m (-[NSString dataByDecodingBase64]): make use of -length rather than -[NSString lengthOfBytesUsingEncoding: NSISOLatin1StringEncoding] to avoid a crash within GNUstep. 2010-07-16 Wolfgang Sourdeau * NGBase64Coding.m (-dataByDecodingBase64) (-stringByDecodingBase64, -stringByEncodingBase64): make use of -[NSString lengthOfBytesUsingEncoding: NSISOLatin1StringEncoding] rather than -[... cStringLength] to avoid a crash within GNUstep. The latter is deprecated anyway... 2010-01-30 Wolfgang Sourdeau * NGRuleEngine.subproj/NGRuleModel.m (-candidateRulesForKey:): return an autoreleased array to avoid leaks. 2009-03-24 Wolfgang Sourdeau * NGQuotedPrintableCoding.m: encode '_' as '=5F', so that it is not decoded as a space (v4.7.203) 2009-03-24 Wolfgang Sourdeau * NGCalendarDateRange.m ([NGCalendarDateRange -dealloc]): release endDate and startDate. (v4.7.202) 2008-03-11 Helge Hess * FdExt.subproj/NSArray+enumerator.m: fixed for MacOS 10.5 (v4.7.201) 2008-02-21 Helge Hess * FdExt.subproj/NSString+Escaping.m: fixed a free() bug introduced in the unichar conversion of v4.7.197 (v4.7.200) 2008-02-21 Helge Hess * FdExt.subproj/NGPropertyListParser.m: fixed NSException not to use -setUserInfo: (v4.7.199) 2008-02-11 Helge Hess * EOExt.subproj/EOGlobalID+Ext.m: explicitly include NSString.h to please GNUstep (v4.7.198) 2008-02-09 Helge Hess * v4.7.197 * FdExt.subproj/NSString+misc.m: rewrote -bindingVariables and stringByReplacingVariablesWithBindings:stringForUnknownBindings: to use unichar (needs testing, might be buggy) * NGQuotedPrintableCoding.m: rewritten to use -dataUsingEncoding: methods instead of working on -cString buffers (Note: encoding selection is dubious) * FdExt.subproj/NSString+Escaping.m: rewrote -stringByApplyingCEscaping to work on unichars * added EOExt.subproj/EOGlobalID+Ext.m category to streamline KVC on non-lF environments 2007-12-03 Helge Hess * NGExtensions/NSString+Formatting.h: replaced usage of deprecated -getCString: method on MacOS 10.4 and later (v4.7.196) 2007-07-31 Marcus Mueller * FdExt.subproj/NSMethodSignature+misc.m: added warning and bogus implementation of -objCTypes for Leopard (v4.7.195) 2007-05-31 Helge Hess * FdExt.subproj/NSString+Encoding.m: added gnustep-base and libFoundation implementations for [NSString +stringEncodingForEncodingNamed:] (v4.7.194) 2007-05-28 Helge Hess * NGCalendarDateRange.m: return nil for undefined KVC keys (v4.7.193) 2007-04-17 Helge Hess * NGExtensions/NSString+Ext.h: expose a few GNUstep NSString extensions (v4.7.192) 2006-11-19 Helge Hess * v4.5.191 * NGRuleEngine.subproj/NGRuleContext.m: allow keypathes in rule values, not just keys * FdExt.subproj/NSString+misc.m: fixed a quote-skipping issue 2006-11-16 Helge Hess * EOExt.subproj/EOCacheDataSource.m: the NSTimer of the datasource does not retain the datasource anymore to avoid keeping them around w/o any other refers (fixes a buserror on MacOS) (v4.5.190) 2006-11-02 Helge Hess * NGQuotedPrintableCoding.m: added NSData method to decode QP as per RFC 2045: -dataByDecodingQuotedPrintableTransferEncoding, related to OGo bug #1753 (v4.5.189) 2006-07-24 Helge Hess * NGBundleManager.m: fixed a minor 64bit printing issue (v4.5.188) 2006-07-05 Helge Hess * NGResourceLocator.m: added FHS_INSTALL_ROOT to lookup path (v4.5.187) 2006-07-04 Helge Hess * NGBundleManager.m: added more debug logs which can be triggered using NGBundleManagerDebugEnabled (v4.5.186) * 64bit fixes (v4.5.185) 2006-07-03 Helge Hess * v4.5.184 * NGHashMap.m: improved memory management with exceptions * FdExt.subproj/NSSet+enumerator.m: code cleanups * use %p for pointer formats, fixed gcc 4.1 warnings 2006-05-16 Marcus Mueller * *.h, *m: changed EOControl related includes into imports to enable compilation against MulleEOF (v4.5.183) 2006-02-20 Helge Hess * NGBundleManager.m: minor code cleanups (v4.5.182) 2006-01-22 Helge Hess * FdExt.subproj/NGPropertyListParser.m (_skipComments): fixed a bug when parsing comments which contain stars (v4.5.181) 2005-12-13 Helge Hess * NGQuotedPrintableCoding.m (NGDecodeQuotedPrintable): properly decode underscore as 0x20 (as per RFC 2047 4.2) (v4.5.180) 2005-11-21 Helge Hess * NGExtensions/NSObject+Values.h: added NGBaseTypeValues protocol to be able to refer to the statically typed 'signed' set of basetypes (v4.5.179) 2005-11-17 Helge Hess * FdExt.subproj/NSObject+Values.m: explicitly mark signed values as such (most importantly char) (v4.5.178) * FdExt.subproj/NSCalendarDate+misc.m: include math.h to avoid a floor warning (v4.5.177) 2005-10-05 Helge Hess * FdExt.subproj/NSNull+misc.m: added -isNotEmpty to NSSet (v4.5.176) 2005-09-28 Helge Hess * FdExt.subproj/NSNull+misc.m: added -isNotEmpty to NSData (v4.5.175) 2005-09-14 Helge Hess * NGBundleManager.m: avoid an autorelease call in class lookup, added some lookup hacks for Tiger Foundation (v4.5.174) 2005-08-26 Helge Hess * added common.h files to support PCH compilation of subprojects (just include the parent common.h and are not required for Xcode builds) (v4.5.173) 2005-08-20 Helge Hess * EOExt.subproj: code cleanups, added a README.txt (v4.5.172) 2005-08-19 Helge Hess * added method to calculate a calendar matrix for a date representing a month (-calendarMatrixWithStartDayOfWeek:onlyCurrentMonth:), added a method to turn an English/German string into a day-of-a-week number (0=Sun-6=Sat) (v4.5.171) 2005-08-07 Helge Hess * NGExtensions.xcodeproj: moved NGRuleParser.h from source to header section 2005-08-04 Helge Hess * NGRuleEngine.subproj/NGRuleModel.m: added EOKeyValueArchiving, added method to load from such an archive, added -addRules: to add a set of rules (v4.5.170) 2005-08-04 Helge Hess * NGRuleEngine.subproj/NGRuleContext.m: added new method -allPossibleValuesForKey: to calculate all possible values for a given key, not just the first matching one (v4.5.169) 2005-08-04 Helge Hess * EOFilterDataSource.m, EOCompoundDataSource.m: code cleanups (v4.5.168) 2005-08-03 Helge Hess * added EOKeyValueArchiving support to NGRuleEngine objects (v4.5.167) 2005-07-22 Helge Hess * FdExt.subproj/NSException+misc.m: added -isException and -isExceptionOrNull methods to NSObject to check whether a given object is an exception (v4.5.166) 2005-07-20 Helge Hess * FdExt.subproj/NSNull+misc.m: fixed a stupid bug in -isNotEmpty (v4.5.165) * FdExt.subproj/NSNull+misc.m: added -isNotEmpty for NSArray and NSDictionary (return YES in case they have no elements) (v4.5.164) 2005-07-19 Helge Hess * FdExt.subproj/NSString+misc.m: use -valueForKeyPath: instead of -valueForKey: to retrieve string binding patterns (might give issues in case you had keys with dots inside before) (v4.5.163) 2005-07-18 Helge Hess * FdExt.subproj/NSNull+misc.m: added -isNotEmpty to all objects. Its similar to -isNotNull but also checks for strings composed of just spaces (v4.5.162) 2005-07-11 Helge Hess * NGResourceLocator.m: added -description, added method -lookupAllFilesWithExtension:doReturnFullPath: to discover all available files in a search hierarchy (v4.5.161) 2005-05-20 Helge Hess * moved NGStringScanEnumerator to Recycler (was not in makefile) 2005-05-03 Helge Hess * fixed gcc 4.0 warnings (v4.5.160) * XmlExt.subproj/DOMNode+EOQualifier.m: reworked for new DOM (v4.5.159) 2005-04-24 Helge Hess * fixed gcc 4.0 warnings (v4.5.158) 2005-04-04 Marcus Mueller * FdExt.subproj/NSObject+Logs.m: fixed previously broken implementation of -logger which now has an NSMapTable for class <-> logger lookup. (v4.5.157) 2005-03-17 Helge Hess * v4.5.156 * NGBundleManager.m: implemented -classesProvidedByBundle: * NGRuleEngine.subproj/NGRuleParser.m: fixed parsing of array and dictionary plist rule values 2005-03-07 Helge Hess * NGExtensions/NGObjectMacros.h: fixed ASSIGN, ASSIGNCOPY macros to avoid an unset LHS as requested by Stephane (v4.5.155) 2005-03-02 Marcus Mueller * NGCalendarDateRange.m: Bugfix for -containsDate: (v4.5.154) 2005-03-01 Helge Hess * NGBundleManager.m (-pathForResource:ofType:inDirectory:languages:): changed resource lookup to look in Contents/Resources or Resources depending on the Foundation library when no inDirectory: has been given (v4.5.153) 2005-02-23 Helge Hess * FdExt.subproj/NSNull+misc.m: added -hasPrefix: / -hasSuffix:, should fix OGo bug #1080 (v4.5.152) 2005-02-21 Helge Hess * FdExt.subproj/NSString+URLEscaping.m: changed to escape '+' chars in URLs - this is required since the same methods are used for forms which treat spaces as "+" (OGo bug #1260) (v4.5.151) 2005-02-17 Helge Hess * NGBundleManager.m: added some debugging code, minor code cleanups (v4.5.150) 2005-02-15 Helge Hess * NGObjCRuntime.m: fixed some issue with the last commit (v4.5.149) 2005-02-14 Helge Hess * NGObjCRuntime.m: decoupled some varargs processing (v4.5.148) 2005-02-14 Helge Hess * NGExtensions/NGCalendarDateRange.h: fixed header file for MacOSX (v4.5.147) 2005-02-14 Helge Hess * NGBase64Coding.m: added method -dataByEncodingBase64WithLineLength: to support the fix for OGo bug #1228 (v4.5.146) 2005-02-12 Marcus Mueller * NGCalendarDateRange.[hm]: new method -duration (v4.5.145) 2005-02-09 Marcus Mueller * FdExt.subproj/NSCalendarDate+misc.m: Julian number <-> date conversion methods (v4.5.144) 2005-02-09 Helge Hess * FdExt.subproj/NSString+misc.m: do not quote the last newline if the newline is the last char in the string (v4.5.143) 2005-02-08 Helge Hess * FdExt.subproj/NSString+misc.m: added new method -stringByApplyingMailQuoting for placing "> " in front of each line contained in the string (v4.5.142) 2005-01-09 Helge Hess * NGExtensions/AutoDefines.h, common.h: fixed defines on MacOSX (fixes OGo bug #912 (v4.5.141) 2004-12-16 Marcus Mueller * NGCalendarDateRange.[hm]: new convenience method -containsDateRange: (v4.5.140) 2004-12-14 Marcus Mueller * NGExtensions.xcode: minor fixes and updated 2004-12-05 Helge Hess * EOFilterDataSource.m, EOCacheDataSource.m: minor code cleanups (v4.5.139) 2004-11-24 Helge Hess * FdExt.subproj/NSObject+Logs.m: fixed debug logging to be compatible with existing code (v4.5.138) * NGBundleManager.m: subminor code cleanups (v4.5.137) 2004-11-19 Marcus Mueller * NGLogging: updated - API considered stable now. NOTE: "make distclean" is required this time. (v4.5.136) 2004-11-19 Helge Hess * v4.5.135 * FdExt.subproj/NSObject+Logs.m: fixed a bug in default logger creation (incorrect static variable) * NGLogging: fixed bug in console appender, increased speed, avoid different logger objects for each class 2004-11-18 Marcus Mueller * v4.5.134 * NGLogging: updated * NGExtensions/NSObject+Logs.h, FdExt.subproj/NSObject+Logs.m: changed existing implementation to use NGLogging by default. Added some more methods to support different log levels. Also added -logger and -debugLogger which are used to provide the default loggers for the desired purpose. * FdExt.subproj/NGBundleManager.m: fixed wrong include 2004-11-17 Helge Hess * NGBundleManager.m: fixed a bug in the bundle type check when the cached bundle is NSNull (v4.5.133) 2004-11-17 Marcus Mueller * NGLogging: updated (v4.5.132) * NGLogging: updated (v4.5.131) 2004-11-17 Matthew Joyce * NGBundleManager.m: check whether bundle is nil prior running a type check (v4.5.130) 2004-11-13 Helge Hess * NGBundleManager.m: some code cleanups (v4.5.129) 2004-11-12 Helge Hess * NGLogging: code cleanup (v4.5.128) 2004-11-12 Marcus Mueller * GNUmakefile: added NGLogging.subproj (v4.5.127) 2004-11-01 Helge Hess * branched 4.3 to 4.4 and 4.5 2004-10-21 Helge Hess * FdExt.subproj/NSString+URLEscaping.m: removed '&' as an URL safe char (v4.3.126) 2004-10-15 Marcus Mueller * FdExt.subproj/NSString+Escaping.m: minor code cleanups, removed a superfluous statement (v4.3.125) 2004-10-15 Helge Hess * FdExt.subproj/NSString+Escaping.m: minor code cleanups, removed a superflous if() condition (v4.3.124) 2004-10-14 Marcus Mueller * v4.3.123 * FdExt.subproj/NSString+Escaping.m, NGExtensions/NSString+Escaping.h: new category and protocol to do generic escaping. The category is Unicode safe and optimized for performance. * FdExt.subproj/NSString+misc.m, NGExtensions/NSString+misc.h: moved -stringByApplyingCEscaping to new NSString+Escaping. 2004-10-11 Matthew Joyce * FdExt.subproj/NSCalendarDate+misc.m: fixed -isAfternoon (all dates were reported as forenoon) (v4.3.122) 2004-10-08 Helge Hess * FdExt.subproj/NSString+URLEscaping.m: do not escape URL safe chars (fixes a WebDAV issue with Cadaver) (v4.3.121) 2004-10-04 Marcus Mueller * NGExtensions.xcode: updated to the current build version 2004-10-03 Helge Hess * FdExt.subproj/NSURL+misc.m: fixed URL processing in some edge case (v4.3.120) 2004-10-02 Helge Hess * NGQuotedPrintableCoding.m: minor code cleanups (v4.3.119) 2004-10-01 Helge Hess * FdExt.subproj/NSException+misc.m: check whether nil is being passed in as the exception format (v4.3.118) 2004-09-27 Helge Hess * NGBundleManager.m: removed a warning on MacOSX (v4.3.117) 2004-09-23 Marcus Mueller * NGExtensions.xcode: added NGResourceLocator class 2004-09-23 Helge Hess * added NGResourceLocator class (v4.2.116) * moved NGCString to Recycler (was not compiled since v4.2.93) 2004-09-21 Marcus Mueller * NGExtensions.xcode: Fixed dependencies to resemble the make process more closely. Our aim should be to stick to the make process as closely as possible, so we shouldn't introduce dependencies in non-toplevel projects. * NGExtensions.xcode: minor fix 2004-09-20 Marcus Mueller * v4.3.115 * NGExtensions/NSBundle+misc.h, FdExt.subproj/NSBundle+misc.m: new NSBundle method -pathForResource:ofType:inDirectory:forLocalizations: * NGExtensions/NGExtensions.h: added NSBundle+misc.h to the public headers 2004-09-06 Helge Hess * FdExt.subproj/NSFileManager+Extensions.m: added new method: -createDirectoriesAtPath:attributes: (comparable to mkdirs) (v4.3.114) * NGBundleManager.m: changed bundle resource lookup to check loaded bundles before scanning the NGBundlePath resources (is faster and fixes an issue with a bundle loaded but not in the search path) (v4.3.113) 2004-09-05 Helge Hess * v4.3.112 * NGBundleManager.m: code cleanups, added -setBundleSearchPaths: and -bundleSearchPaths to allow bundle path modifications from code * NGHashMap.m: removed libFoundation specific exception handling, the same exceptions are now thrown for all runtimes 2004-08-30 Helge Hess * NGBundleManager.m: fixed yet another bug in NGBundleManager path lookup (v4.3.111) 2004-08-29 Helge Hess * NGBundleManager.m: fixed an issue when running without GNUstep environment (v4.3.110) * v4.3.109 * NGBundleManager.m: look for bundles in GNUSTEP_PATHPREFIX_LIST and GNUSTEP_PATHLIST * added hack to install the project in FHS locations - the library, its headers, the tools and the resources will be installed in FHS_INSTALL_ROOT if specified (eg make FHS_INSTALL_ROOT=/usr/local) 2004-08-29 Marcus Mueller * NGExtensions.xcode: various fixes for project settings 2004-08-26 Helge Hess * FdExt.subproj/NSURL+misc.m: fixed some URL processing methods (v4.3.108) 2004-08-25 Marcus Mueller * NGCalendarDateRange.m: properly fixed intersectionDateRange: to not return pseudo-ranges. (v4.3.107) 2004-08-23 Marcus Mueller * v4.3.106 * NGCalendarDateRange.m: changed -containsDate: in a way that the range is treated as a half-open interval (including startDate, excluding endDate). * v4.3.105 * NGExtensions.xcode: new Xcode project * NGStringScanEnumerator.m: compile bugfix * NGExtensions-Info.plist: new version and bundle identifier 2004-08-20 Helge Hess * XmlExt.subproj/GNUmakefile: added include path for "inline" SOPE 4.3 compilation (v4.3.104) * moved to SOPE 4.3 (v4.3.103) 2004-08-16 Helge Hess * NGCalendarDateRange.m: added range category on NSArray, added some methods to daterange (v4.2.102) 2004-08-16 Marcus Mueller * added NGCalendarDateRange class (v4.2.101) 2004-07-26 Helge Hess * FdExt.subproj/NSObject+Values.m([NSString -unsignedCharValue]): added a specific implementation for NSString to support KVC bool operations (because BOOL values are represented as 'unsigned char' values at runtime, [self takeValue:@"YES" ...] coercion did fail for bool methods) (v4.2.100) 2004-07-22 Helge Hess * EOExt.subproj/EOKeyMapDataSource.m: fixed a gcc 3.4 warning (v4.2.99) 2004-07-14 Helge Hess * FdExt.subproj/NSString+Encoding.m: improved error logs in case an iconv buffer is too small (v4.2.98) 2004-06-27 Helge Hess * NGExtensions/FdExt.subproj/NGPropertyListParser.m: minor cleanups to log messages (v4.2.97) 2004-06-22 Helge Hess * v4.2.96 * FdExt.subproj/NSArray+enumerator.m: fixed a bug with array capacity initialization (used an uninitialized variable leading to a virtual memory exhausted on gstep-base) * FdExt.subproj/NGPropertyListParser.m (_makeException): be more tolerant about nil results in NSString creation (fixes an exception with gstep-base) 2004-06-17 Helge Hess * FdExt.subproj/NSURL+misc.m: add a hack to work around a bug in NSURL on Cocoa Foundation, added a lot of debug logs (v4.2.95) 2004-06-10 Helge Hess * NGObjCRuntime.m: fixed hack for dynamic class loading with gcc 3.4 (type signature of the privates changed or is more strictly checked) (v4.2.94) * v4.2.93 * GNUmakefile: removed NGCString from compilation * NGExtensions/NGExtensions.h: do not include NGCString.h 2004-06-09 Helge Hess * NGExtensions/GNUmakefile.preamble: added prebinding (v4.2.92) 2004-06-08 Helge Hess * FdExt.subproj: include NGPropertyListParser categories when compiling for libFoundation (v4.2.91) * v4.2.90 * GNUmakefile.preamble: fixed path to DOM library, added explicit dependency to SaxObjC for MacOSX * NGBundleManager.m: logging can now be enabled using the NGBundleManagerDebugEnabled default, some code cleanups 2004-06-07 Helge Hess * NGExtensions/NSString+misc.[hm]: improved, now works with any object which supports KVC (v4.2.89) 2004-06-07 Helge Hess * NGBundleManager.m: fixed gcc 3.4 warnings (v4.2.88) 2004-06-05 Stephane Corthesy * NGBundleManager.m(-bundleForClass:): added basic support for classes defined in frameworks (v4.2.87) 2004-06-03 Helge Hess * NGObjCRuntime.m: added a hack to make NGObjCRuntime.m compile with gcc 3.4.0 (v4.2.86) 2004-06-01 Marcus Mueller * NGExtensions/NSCalendarDate+misc.h, FdExt.subproj/NSCalendarDate+misc.m: new method -(BOOL)isInLeapYear, utilized by rewritten -(int)numberOfDaysInMonth. -(NSCalendarDate *)lastDayOfMonth uses -(int)numberOfDaysInMonth now instead of the other way round as before. -lastDayOfMonth turned out to be non-portable to gnustep-base, the new implementation works with all foundation and is far more time/memory efficient. (v4.2.85) 2004-05-17 Helge Hess * FdExt.subproj/NSNull+misc.m: added 'NSNullAbortOnMessage' default to enable abort()'s if a message is sent to NSNull (useful for debugging NSNull issues on MacOSX (v4.2.84) 2004-05-09 Helge Hess * NGObjCRuntime.m: fixed a bug in GNU runtime method addition, added a class enumerator for the GNU runtime (v4.2.83) * NGObjCRuntime.m: added an implementation of +addMethods for the Apple runtime (v4.2.82) 2004-05-05 Marcus Mueller * GNUmakefile.preamble: added support for building with GNUSTEP_BUILD_DIR environment variable set for recent gnustep-make package. (v4.2.81) 2004-05-04 Marcus Mueller * EOExt.subproj/EOSortOrdering+plist.m: fixed wrong mappings for case insensitive sortOrderings (v4.2.80) 2004-05-01 Marcus Mueller * v4.2.79 * EOExt.subproj/EOSortOrdering+plist.m: fixed wrong key argument to initWithKey:selector: in initWithDictionary:. * EOExt.subproj/EOFetchSpecification+plist.m: testing for respondsToSelector(objectEnumerator) matches dictionaries as well, resulting in improper behavior. Narrowed to testing for kind of NSArray now. 2004-05-01 Helge Hess * NGObjCRuntime.m: improved support for Apple runtime (v4.2.78) 2004-04-07 Jean-Alexis Montignies * NGHashMap: added because used in NGObjWeb -asDictionaryWithArraysForValues (v4.2.77) 2004-04-07 Helge Hess * NGExtensions/NSString+Encoding.h: exported +stringEncodingForEncodingNamed: on Cocoa (v4.2.76) 2004-04-01 Helge Hess * NGHashMap: some code cleanups, made the code a bit more fault tolerant (check for some NULL references, as suggest by Jean-Alexis Montignies), fixed missing class in header file (v4.2.75) 2004-03-24 Helge Hess * FdExt: added NSString+German category which contains some methods to deal with ASCII representations of German umlauts (useful for some searches) (v4.2.74) 2004-03-22 Helge Hess * v4.2.73 * FdExt.subproj/NSString+HTMLEscaping.m: added escaping for some missing umlauts * FdExt.subproj/NSObject+Values.m: minor speed optimization to NSString -boolValue 2004-03-15 Helge Hess * EOExt: moved in property list initializer methods from EOControl (to make them available for GDL2) 2004-03-14 Helge Hess * NGBundleManager.m: print an error log if we were unable to get the system NSUserDefaults object, as it currently happens with gstep-base, added a hack not to create the NGBundleManager if the NSUserDefaults object could not be retrieved (v4.2.71) 2004-03-13 Helge Hess * EOFilterDataSource: code cleanups, added -description method (v4.2.70) 2004-03-11 Helge Hess * NGBundleManager.m: disabled a debug log (v4.2.69) 2004-03-10 Donald Duck * NGBundleManager.m: print a warning if the NGBundlePath default is not configured (v4.2.68) 2004-03-08 Helge Hess * FdExt.subproj/NSException+misc.m: added a -copyWithZone: method, as used by the XML-RPC client (v4.2.67) 2004-03-01 Helge Hess * FdExt.subproj/NSException+misc.m: added a -setReason: implementation for gnustep-base - thanks to chunsj for pointing that out (v4.2.66) 2004-02-24 Helge Hess * FdExt.subproj/NSNull+misc.m: added -descriptionWithLocale: on MacOSX (v4.2.65) 2004-02-23 Helge Hess * FdExt.subproj/NSNull+misc.m: added -descriptionWithLocale: for Cocoa Foundation (v4.2.65) * FdExt.subproj/NSNull+misc.m: added various "ignore that" methods for MacOSX: -isEqualToString:, -characterAtIndex:, -descriptionWithLocale:indent:, added -respondsToSelector: (always returns YES on MacOSX) - Note: this is to be considered a workaround, we need to find out, why OGo calls such methods on NSString with Cocoa Foundation (v4.2.64) 2004-02-19 Helge Hess * FdExt.subproj/NSCalendarDate+misc.m, NSString+Ext.m: added KVC default handlers for Cocoa Foundation (avoids some exceptions, libFoundation is much more tolerant regarding missing KVC keys than Cocoa) (v4.2.63) 2004-02-13 Helge Hess * v4.2.62 * NGBundleManager.m: do not report missing resources on MacOSX (reduced debug level) * FdExt.subproj/NSArray+enumerator.m: added implementation of -map:... (to be considered deprecated ...) for the MacOSX port 2004-02-12 Helge Hess * NGBundleManager.m: disabled class-hook debugging on OSX (v4.2.61) 2004-02-10 Helge Hess * NGStack.m: fixed minor compilation warning on OSX (v4.2.60) 2004-02-08 Helge Hess * FdExt.subproj/NSString+Encoding.m: cleanups, use ucs-2-internal instead of ucs-2 on non-Linux platforms and detect platform byte ordering and use ucs-2le or ucs-2be depending on that - should fix OGo bugs #580 (does not fix #145) (v4.2.59) 2004-01-23 Helge Hess * FdExt.subproj/NSFileManager+Extensions.m: renamed category to ExtendedFileManagerImp to avoid gcc warnings (v4.2.58) 2003-12-28 Helge Hess * NGBundleManager.m: minor cleanups (v4.2.57) 2003-11-30 Helge Hess * FdExt.subproj/NSString+misc.m, FdExt.subproj/NSMethodSignature+misc.m: applied some minor patches for gstep-base provided by chunsj@embian.com (v4.2.56) 2003-11-20 Helge Hess * FdExt.subproj/NSString+URLEscaping.m: added UTF-8 URL escaping (v4.2.55) * v4.2.54 * NSString+URLEscaping.m: added default 'NGUseUTF8AsURLEncoding' to unescape URL strings as UTF-8 entities. This is usually the right thing to do for WebDAV servers like ZideStore. Note that encoding is still always done in ISO-Latin-1 (to be fixed) * FdExt.subproj/NSString+misc.m: moved the various string escaping implementations (URL, HTML and XML) into separate NSString categories 2003-11-09 Helge Hess * FdExt.subproj/NSString+Formatting.m: minor speed and MacOSX compatibility improvements (v4.2.53) 2003-10-27 Helge Hess * NGBase64Coding.m: bad day, fixed the new -dataByDecodingBase64 (v4.2.52) * NGBase64Coding.m: added -dataByDecodingBase64 to NSString, since a base64 string can (of course!) contain zero bytes. -stringByDecodingBase64 now returns nil if it encounteres such a situation (v4.2.51) * NGBase64Coding.m: fixed a major bug in the base64 encoding (which did not handle empty values properly!) (v4.2.50) 2003-10-15 Helge Hess * v4.2.49 * FdExt.subproj/NSException+misc.m: fixed ZNeK's setReason: implementation for gstep-make * moved NGPropertyListParser.h to NGExtensions and made it a public header 2003-10-13 Helge Hess * compile and link NGPropertyListParser in case we are not on libFoundation, compile and link FileObjectHolder on Cocoa (v4.2.48) 2003-10-11 Marcus Mueller * FdExt.subproj/NSException+misc.m: Provided implementation for setReason: (as needed with COCOA_Foundation_LIBRARY) and provided interface declaration in case of GNUSTEP_BASE_LIBRARY. (v4.2.47) 2003-09-07 Marcus Mueller * v4.2.46 * NGBundleManager.m, NGHashMap.m, NGObjCRuntime.m, NGStack.m, EOExt.subproj/EOQualifier+CtxEval.m, FdExt.subproj/NSNull+misc.m, FdExt.subproj/NSProcessInfo+misc.m, FdExt.subproj/NSString+misc.m: Fixed outdated references to FoundationExt and pointed to NGExtensions where appropriate. Also, added defines for NeXT_RUNTIME. * EOExt.subproj/EOKeyMapDataSource.m: Fixed problem with method not returning value when not void. 2003-09-06 Helge Hess * v4.2.45 * NGExtensions.h: do not include FoundationExt but NGObjectMacros.h instead * added NGObjectMacros.h which contains the RC macros * FdExt.subproj/NSString+Formatting.m: cache the NSString class object, use less autorelease, fixed a nil-parameter bug on MacOSX, added some hacks to implement unicode format scanning (v4.2.44) 2003-09-06 Marcus Mueller * v4.2.43 * GNUmakefile.preamble: added iconv to the list of necessary libraries on FreeBSD (4.x/5.x) * FdExt.subproj/NSString+Encoding.m: do not use iconv on Apple, instead use CoreFoundation's CFStringConvertIANACharSetNameToEncoding() 2003-07-18 Helge Hess * v4.2.42 * FdExt.subproj/NSData+gzip.m: removed dependency on zutil.h, patch provided by Filip Van Raemdonck * NGHashMap.m, NSNull+misc.m: fixed gstep-base compilation problems, patch provided by Filip Van Raemdonck Wed Jul 16 16:03:47 2003 Jan Reichmann * FdExt.subproj/NSString+Formatting.m: use ISERIES/USE_VA_LIST_PTR defines to handle va_list structures (v4.2.41) Wed Jul 16 15:00:16 2003 Jan Reichmann * FdExt.subproj/NSString+Formatting.m: fixed a bug regarding iSeries port, copy va_list structure before give it to a function and read one argument from the original va_list (v4.2.40) Tue Jul 15 21:09:26 2003 Jan Reichmann * FdExt.subproj/NSString+Formatting.m: replace *va_list function arguments with va_list (iSeries port) (v4.2.39) Mon Jul 14 18:21:55 2003 Jan Reichmann * NGBundleManager.m: cache bundle using name.extension instead of name only (v4.2.38) 2003-06-23 Helge Hess * NGFileManager.m: ignore empty strings during path standardization (reason for publisher bug 1778) (v4.2.37) 2003-06-06 Jan Reichmann * NSString+Encoding.m: added a category to encode/decode string from arbitary encoding formats using libiconv (v4.2.36) 2003-05-26 Helge Hess * updated MacOSX port, some smaller modification to compile without FoundationExt (exceptions, memory allocation, plist parsing) (v4.2.35) 2003-05-19 Helge Hess * v4.2.34 * NGRuleEngine.subproj/NGRuleContext.m: added a flag to enable debugging on a per-context base, added some logging * NGRuleEngine.subproj/NGRuleModel.m: during sorting of rules also consider how specific a qualifier is (by calling -count on the qualifier) * v4.2.33 * NGRuleEngine: fixed default priorities * NGRuleEngine/NGRuleParser: fixed bug in rule-model parsing, added a "reset" method to reset stored variables * NGRuleContext: added some constructors (v4.2.32) 2003-05-16 Helge Hess * NGRuleEngine: added parsing of rule-models (v4.2.31) * v4.2.30 * EOExt.subproj/NSArray+EOGrouping.m: fixed a bug introduced by clean ups in v4.2.26 * EOExt: added EOTrueQualifier (used in rule system for *true*) * added simple NGRule parser 2003-05-15 Helge Hess * FdExt.subproj/NSString+misc.m: added a new scanning method, -rangeOfString:skipQuotes:escapedByChar: for easier parsing of common quoted languages (v4.2.29) 2003-05-14 Helge Hess * moved headers to "NGExtensions" subdirectory (v4.2.28) * started to add NGRuleEngine, a KVC/EOQualifier based evaluation system (v4.2.27) * cleaned up source organization, created three subprojects, FdExt, EOExt and XmlExt for Foundation, EOControl and skyrix-xml additions (v4.2.26) 2003-04-09 GNUstep User * fixed unsigned/signed warnings for gcc 3.3 (v4.2.25) * NSProcessInfo+misc.m: small fix for gstep-base (use -stringByTrimmingSpaces instead of ..WhiteSpaces..) (v4.2.24) 2003-04-01 GNUstep User * NGObjCRuntime.m: added a hack for GNUstep Base with the incomplete FoundationExt library (v4.2.23) 2003-04-01 Helge Hess * added compilation support for GNUstep base (v4.2.22) 2003-03-14 Helge Hess * NSString+misc.m: do not encode umlaut entities in XML output (v4.2.21) 2003-03-09 Helge Hess * NGBase64Coding.m: added -stringByEncodingBase64 and -stringByDecodingBase64 to NSData (v4.2.20) Tue Mar 4 13:53:40 2003 Jan Reichmann * GNUmakefile, NGFileManager+JS.m: add JS functions (copied from NGJavaScript/Core+JS/NGFileManager+JS.m) (bug 712) (v4.2.19) Tue Feb 4 11:56:34 2003 * NGHashMap.m: disable throwing exception in objectForKey: if more than one object exsist, print out a warning only (bug 981) (v4.2.18) Fri Jan 17 16:43:13 2003 Martin Hoerning * NSCalendarDate+misc.m ([NSCalendarDate -dateByAddingYears:months:days:]): fixed month overflow (bug 871) (v4.2.17) 2003-01-10 Helge Hess * NGBundleManager.m: do not print a warning if the principal class of a bundle could not be found (since the bundle might have none ...) and use the NGBundle class as the default handler (v4.2.16) 2003-01-07 Helge Hess * v4.2.15 * changes for improved compilation on MacOSX, replaced RETAIN macros with methods * common.h: does not include anything from FoundationExt (required includes were moved to the .m files) Fri Dec 27 10:42:11 2002 Helge Hess * fixed Copyright headers in most files (v4.2.14) Mon Dec 23 15:34:51 2002 Helge Hess * NSObject+Logs.m: print a warning if DEBUG is disabled (v4.2.13) * NSFileManager+Extensions.m: correctly implement NGFileManager (some trash related fixes) 2002-11-25 Helge Hess * NSString+misc.m: added some methods for processing fully qualified XML names (v4.2.12) 2002-11-22 Helge Hess * EOKeyMapDataSource.m: finished EOKeyMapDataSource (v4.2.11) * EOKeyMapDataSource.m: started EOKeyMapDataSource (v4.2.10) * EOCacheDataSource.m: tiny code cleanups 2002-11-15 Helge Hess * NSURL+misc.m: fixed an index bug in URL string processing (v4.2.9) 2002-10-30 Helge Hess * NSDictionary+misc: added a method -dictionaryByExchangingKeysAndValues to reverse the mapping of a dictionary (v4.2.8) 2002-10-21 Helge Hess * NGStringScanEnumerator.m: properly clear data when being passed an empty NSData (v4.2.7) Thu Oct 17 16:18:49 2002 Helge Hess * added Bjoern's excellent NGStringScanEnumerator for scanning binaries for printable strings (useful for extracting version information of executables that have no --version support ..) (v4.2.6) 2002-09-30 Helge Hess * NSEnumerator+misc.m, NSProcessInfo+misc.m: removed some compilation warnings (v4.2.5) Fri Aug 30 11:40:59 2002 Jan Reichmann * NGQuotedPrintableCoding.m: (Suse Bug 18600) fixed 'Soft line Breaks'-Bug (v4.2.4) 2002-08-15 Helge Hess * NSFileManager+Extensions.m: added support for GlobalIDs, make relative pathes absolute before calling standarizePath (v4.2.3) 2002-07-12 Helge Hess * moved tools/tests to skyrix-core/samples 2002-05-31 Helge Hess * NGBundleManager.m: changed to work with gstep-base library 2002-05-23 Helge Hess * moved from Skyrix-dev-42 repository to skyrix-core (v4.2.2) Fri May 17 14:51:13 2002 Helge Hess * added NSData+gzip category from NGZlib Thu May 2 15:21:00 2002 Helge Hess * added NSURL+misc for handling relative NSURLs Thu May 2 13:38:11 2002 Helge Hess * made some modifications to support gstep-base Mon Apr 29 11:35:31 2002 Helge Hess * NSProcessInfo+misc.m: added convenience methods: -argumentsWithoutDefaults Tue Apr 16 13:13:05 2002 Helge Hess * NSString+misc.m: fixed bug with HTML escaping \n \r etc Tue Feb 12 21:04:16 2002 Helge Hess * NSObject+Values.m: the -stringValue of NSMutableString now returns an immutable copy * added DOM extensions Sat Feb 9 12:25:57 2002 Helge Hess * added object logging methods Wed Feb 6 11:54:04 2002 Helge Hess * NSProcessInfo+misc.m: added -temporaryFileName Mon Jan 7 15:33:41 2002 Helge Hess * NGBundleManager.m: use a set for resource lookup to avoid duplicates Mon Dec 17 15:19:23 2001 Helge Hess * NGFileManager.m: added -trashFileAtPath:handler: method Tue Nov 27 19:30:29 2001 Helge Hess * NGBundleManager: made NGBundle class public * NSProcessInfo+misc.m: speed optimized /proc processing ... Thu Nov 22 10:48:29 2001 Helge Hess * NSCalendarDate+misc.m: added method for calculation of easter Tue Nov 6 12:06:49 2001 Helge Hess * removed NGFileManager*Tools from Sascha, too many dependencies on SkyProject ... Tue Nov 6 12:00:11 2001 Helge Hess * added NGFileManager*Tools from Sascha Thu Oct 18 15:34:13 2001 Helge Hess * NSNull+misc.m: added forwarding code to catch unknown selectors Tue Oct 16 16:34:25 2001 Helge Hess * EOQualifier+CtxEval.m ([NSArray -filteredArrayUsingQualifier:context:]): return empty array instead of nil if no object matches Mon Oct 15 15:59:42 2001 Helge Hess * NSNull+misc.m: implemented KVC for NSNull ... Mon Oct 15 15:33:52 2001 Helge Hess * NSNull+misc.m: added -count,-length implementations to improve stability against typing bugs (calls get logged using NSLog) Tue Aug 28 11:32:06 2001 Helge Hess * NSString+misc.m: added Unicode support to HTML escaping * NSString+misc.h: added methods to do HTML escaping Mon Aug 20 17:59:49 2001 Helge Hess * EOCompoundDataSource.m: fixed bug: remove from notification center in -dealloc * EOFilterDataSource.m ([NSDictionary -flattenedArrayWithHint:andKeys:]): fixed allocation bug (missing -autorelease) Fri Aug 17 12:47:07 2001 Helge Hess * added NSProcessInfo+misc for querying the /proc filesystem Fri Aug 10 13:31:28 2001 Helge Hess * added NGFileManager class Thu Aug 9 13:49:30 2001 Helge Hess * NSString+misc.m (NGUnescapeUrlBuffer): added URL escaping/unescaping Tue Jul 31 11:27:46 2001 Martin Spindler * EOFilterDataSource.m: can handle groupings now Tue Jul 10 11:56:18 2001 Helge Hess * NSCalendarDate+misc.m(firstMondayAndLastWeekInYear:): do not dump core if passed NULL 2001-06-26 Helge Hess * removed NGNil, NGArchiver * moved to SkyDev41 Wed May 30 14:47:11 2001 Helge Hess * EOFilterDataSource.m: completed Thu May 10 11:23:57 2001 Helge Hess * NGBundleManager.m: improved error handling Mon Apr 30 10:44:02 2001 Helge Hess * EOCacheDataSource.m: added -description Thu Apr 19 11:58:57 2001 Jan Reichmann * EOCompoundDataSource.m: insert mh bugfix (return empty array instead of nil); fixed sources notification bug Tue Apr 10 13:15:38 2001 Helge Hess * NGFileManager.h: completed NGFileManager protocol Mon Mar 26 12:29:14 2001 Helge Hess * added NSNull+misc with -isNotNull Thu Mar 8 16:51:31 2001 Helge Hess * EOKeyGrouping.m: fixed bug with 'nil' in -addObject: Tue Feb 13 10:51:03 2001 Helge Hess * EOGrouping.m: added -setGroupings/-groupings to EOFetchSpecification Tue Feb 13 10:31:29 2001 Helge Hess * fixed bugs in grouping stuff Tue Feb 6 18:18:48 2001 Martin Spindler * NSArray+Grouping.[hm], EO*Grouping.[hm]: added Mon Jan 29 15:36:07 2001 Helge Hess * NSFileManager+Extensions.m: added trash-folder support Wed Jan 24 19:35:43 2001 Jan Reichmann * NSString+misc.[mh]: add FilePathVersioningMethods Wed Jan 24 19:35:00 2001 Jan Reichmann * NSFileManager+Extensions.h: add fileAttributesAtPath:traverseLink: version: Tue Jan 23 18:04:35 2001 Helge Hess * EOQualifier+CtxEval.m: fixed bug in parameter countin Thu Jan 18 17:04:07 2001 Helge Hess * NSFileManager+Extensions: changed feature-check methods Tue Jan 16 11:28:38 2001 Jan Reichmann * EOCacheDataSource.m: fixed timeout bug Mon Jan 15 14:24:45 2001 Helge Hess * NSFileManager+Extensions.h: added locking protocol Mon Jan 15 12:54:54 2001 Helge Hess * NSFileManager+Extensions.h: added methods for versioning Sun Jan 14 19:27:23 2001 Jan Reichmann * EOCacheDataSource.[mh]: improved timeout Fri Jan 12 18:29:33 2001 Jan Reichmann * EOCacheDataSource.[hm]: timeout Wed Jan 10 15:56:40 2001 Helge Hess * EODataSource+NGExtensions.m: added EONoFetchWithEmptyQualifierHint Wed Jan 3 15:36:40 2001 Jan Reichmann * EOCacheDataSource.m: fixed dealloc bug Thu Oct 26 20:00:41 2000 Jan Reichmann * EOQualifier+CtxEval.m: fixed log bug Thu Oct 19 14:31:48 2000 Helge Hess * NSString+misc.m: added changes of Jan Mon Oct 16 19:30:30 2000 Martin Spindler * EODataSource+NGExtensions.m: added Mon Oct 2 18:04:28 2000 Helge Hess * NSString+Formatting.m: added %ll specifier for long-long types Thu Aug 31 17:54:59 2000 Helge Hess * NSEnumerator+misc: added this new category/classes Fri Aug 18 15:09:14 2000 Helge Hess * NGBundleManager.m: cache bundle manager object Thu Aug 17 13:43:06 2000 Helge Hess * NGBundleManager.m: always search in $GSROOT/Library/Bundles Wed Jul 5 20:32:24 2000 Martin Hoerning * NSCalendarDate+misc.m: fixed -numberOfWeeksInYear Wed Jun 28 15:24:46 2000 Helge Hess * NSCalendarDate+misc.m: added -numberOfWeeksInYear Tue Jun 13 18:34:04 2000 Helge Hess * NGObjCRuntime.m, NSString+Formatting.m: doesn't use stack allocated buffers anymore Fri Jun 9 17:37:09 2000 Helge Hess * NGQuotedPrintableCoding.m: changed 'char' type to 'signed char' Wed May 31 16:33:53 2000 Helge Hess * NSCalendarDate+misc.h: added -firstDayOfMonth and -weekOfMonth Wed May 17 11:54:20 2000 Helge Hess * NSCalendarDate+misc.m: added -isForenoon and -isAfternoon Wed May 3 17:45:19 2000 Helge Hess * NSCalendarDate+misc.m: fixed mondays-of-year calculation to respect the DST timezones Wed May 3 17:14:32 2000 Helge Hess * NSCalendarDate+misc.m: added week-calculation methods Tue May 2 17:24:09 2000 Helge Hess * NGBundleManager.m ([NGBundleManager -providedResourcesOfType:inBundle:]): fixed bug, didn't qualify based on type Tue May 2 14:00:45 2000 Jan Reichmann * NSString+misc.m: fixed possible buffer overflow bug Tue May 2 13:24:40 2000 Jan Reichmann * NGHashMap.m: fixed RC-Bug in allObjects and _NGHashMapObjectEnumerator -nextObject Tue May 2 13:12:11 2000 Helge Hess * NGHashMap.m: added NSAssert's to check for a valid 'table' Fri Apr 28 19:00:52 2000 Helge Hess * NSString+misc.m: added placeholder replacement stuff, removed string debugging stuff Wed Apr 12 19:33:26 2000 Helge Hess * NSCalendarDate+misc.m: added -isToday method Tue Feb 29 17:12:15 2000 Helge Hess * MOF3 import Mon Feb 21 13:49:40 2000 Helge Hess * removed -cString calls 2000-02-17 * NSString+Formatting.m, NSBase64Coding.m, NGBundleManager.m, NSString+misc: removed a lot of 'cString' usage Thu Jan 20 18:44:27 2000 Helge Hess * added NGObjCRuntime category. Contains ObjC runtime manipulation stuff Mon Jan 10 12:44:10 2000 Helge Hess * NSCalendarDate+misc.m: added Y2K support method Mon Dec 6 19:15:27 1999 Helge Hess * NGBundleManager.m: added support for EOQualifier queries Thu Sep 16 18:14:39 1999 Helge Hess * removed NGTool.[hm], NGProxy.[hm], NGMainMacros.h Mon Jul 26 12:21:44 1999 Helge Hess * NGBundleManager.m: added -principalObject method Thu Jul 22 14:31:36 1999 Jan Reichmann * NGQuotedPrintableCoding.m: fixed NGEncodeQuotedPrintable Thu Jul 8 10:23:52 1999 Helge Hess * NGBundleManager.m: send notification if bundle did load Wed Jun 30 15:20:05 1999 Helge Hess * added NGBundleManager Fri Jun 25 19:58:14 1999 Helge Hess * NSString+Formatting.m: fixed bug (formatter looks for empty format) Tue Jun 15 10:38:05 1999 Helge Hess * added NGQuotedPrintableCoding categories Fri May 21 16:13:52 1999 Helge Hess * make it compile with gstep-base Fri May 21 13:19:10 1999 Helge Hess * changed OPENSTEP macro to WITH_OPENSTEP Tue Mar 16 12:43:03 1999 Helge Hess * common.h: added support for mingw32 Tue Jan 12 13:19:36 1999 Helge Hess * NGHashMap.m: added -asDictionary method Fri Jan 8 14:42:31 1999 Helge Hess * NSSet+enumerator.m: implemented mapping methods Thu Jan 7 16:14:55 1999 Helge Hess * NGBase64Coding.m: use +stringWithCStringNoCopy:... Wed Jan 6 18:54:50 1999 Helge Hess * NSString+Formatting.m: use Objective-C allocation functions * NGMemoryAllocation.h: use Objective-C allocation functions * NSAutoreleasePool+misc.m: content is ignored if Boehm GC is used Wed Dec 30 09:54:51 1998 Helge Hess * fixed exception creation, cleanups in NSAttributedString Mon Dec 28 09:51:24 1998 Helge Hess * replaced THROW with -raise * replaced TRY with NS_DURING * removed GNU regex library because of license issues Wed Dec 23 12:13:07 1998 Helge Hess * NSArray+enumerator.m: added methods to create sets using selector mapping Wed Dec 16 12:23:24 1998 Helge Hess * NSArray+enumerator.m: added methods to create arrays using selector mapping Fri Dec 11 18:58:35 1998 Helge Hess * NSCalendarDate+misc.m: added -hour:minute:second:, -hour:minute: Tue Dec 8 19:23:23 1998 Helge Hess * NSCalendarDate+misc.m: fixed -tomorrow, -yesterday which was broken * NSCalendarDate+misc.m: added various methods: -isDateOnSameDay, -isDateInSameWeek, -yesterday, -tomorrow * added NSCalendarDate+misc category Fri Nov 27 15:53:48 1998 Helge Hess * NGExtensions.h: added 'index()' function for WIN32 Thu Nov 26 13:48:35 1998 Helge Hess * NSException+misc.h: removed FINALLY from SYNCHRONIZED macros * GNUmakefile: added install capability Tue Nov 24 11:51:08 1998 Helge Hess * NSAutoreleasePool+misc.m: added category linking function * NGStack.m: fixed RC bug (elements were not released on dealloc) Mon Nov 23 10:37:55 1998 Helge Hess * NSString+misc.m: added string debugging methods (init replacements) which were in libFoundation-mof2 before * added NSAutoreleasePool+misc.[hm] Mon Nov 16 18:41:15 1998 Helge Hess * NGCharBuffers.h: fixed bug in initialization Fri Nov 13 10:44:03 1998 Helge Hess * NGExtensions.h: made NoZone a libFoundation specific * Makefile.preamble: added -Wno-protocol switch * NGTool.m: getpid() replaced for WIN32 Tue Nov 10 17:01:20 1998 Helge Hess * NGTool.m: signal handler sets itself again after signal is executed Fri Nov 6 11:07:03 1998 Helge Hess * NGArchiver.m: added proper Copyright information Thu Nov 5 08:28:07 1998 Helge Hess * NGArchiver.m: reformatted for inclusion in libFoundation Wed Oct 28 14:57:40 1998 Helge Hess * NGHashMap.m: added -initWithDictionary:, +hashMapWithDictionary: methods Thu Oct 22 14:07:32 1998 Helge Hess * added NSDictionary+misc category Tue Oct 20 19:34:33 1998 Helge Hess * added xor digests in MD5 generator 1998-10-19 Helge Hess * NSObject+Values.m: modified values method to use only intValue, floatValue and doubleValue. * NSException+misc.h: added synchronized macros * removed property list parser (now in libFoundation) 1998-10-15 Helge Hess * NGStack.m: made category on NSMutableArray to make it conform to stack protocol * added NSString+misc category. Contains a method to return a string escaped using C rules (newline becomes '\n', ..) 1998-10-11 Helge Hess * started Rhapsody support 1998-10-10 Helge Hess * NGBase64Coding.m: removed generation of newline at end of encoding, cleaned up, removed MAXLINE constant 1998-10-09 Helge Hess * reformatted NGArchiver.m * created ChangeLog SOPE/sope-core/NGExtensions/common.h0000644000000000000000000000624015004363604016246 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGExtensions_common_h__ #define __NGExtensions_common_h__ #include #import #import #include #if defined(WIN32) # include #elif defined(NeXT) || NeXT_Foundation_LIBRARY # include #else # include # include #endif #if !defined(WIN32) #include #endif #if GNU_RUNTIME #if __GNU_LIBOBJC__ >= 20100911 # include #else # import # import # import #endif #endif #if LIB_FOUNDATION_LIBRARY # include # import #endif #ifndef ASSIGN # define ASSIGN(object, value) \ ({id __object = (id)object; \ id __value = (id)value; \ if (__value != __object) { if (__value) [__value retain]; \ if (__object) [__object release]; \ object = __value;}}) #endif #ifndef ASSIGNCOPY # define ASSIGNCOPY(object, value) \ ({id __object = (id)object; \ id __value = (id)value; \ if (__value != __object) { if (__value) __value = [__value copy]; \ if (__object) [__object release]; \ object = __value;}}) #endif #if LIB_FOUNDATION_LIBRARY # define NoZone nil #else # define NoZone NULL #endif #include #include #include #include #include #ifndef __MINGW32__ #include #endif #if defined(WIN32) static inline const char *index(const char *str, char c) __attribute__((unused)); static const char *index(const char *str, char c) { while ((*str != '\0') && (*str != c)) str++; if (*str == '\0') return NULL; else return str; } #endif #if PROFILE # define BEGIN_PROFILE \ { NSTimeInterval __ti = [[NSDate date] timeIntervalSince1970]; # define END_PROFILE \ __ti = [[NSDate date] timeIntervalSince1970] - __ti;\ if (__ti > 0.05) \ printf("***PROF[%s]: %0.3fs\n", __PRETTY_FUNCTION__, __ti);\ else if (__ti > 0.005) \ printf("PROF[%s]: %0.3fs\n", __PRETTY_FUNCTION__, __ti);\ } # define PROFILE_CHECKPOINT(__key__) \ printf("---PROF[%s] CP %s: %0.3fs\n", __PRETTY_FUNCTION__, __key__,\ [[NSDate date] timeIntervalSince1970] - __ti) #else # define BEGIN_PROFILE { # define END_PROFILE } # define PROFILE_CHECKPOINT(__key__) #endif #endif SOPE/sope-core/NGExtensions/NGBitSet.m0000644000000000000000000002207415004363604016405 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "NGMemoryAllocation.h" #import "NGBitSet.h" #define NGStorageSize sizeof(NGBitSetStorage) #define NGBitsPerEntry (NGStorageSize * 8) #define NGByteSize (universe / 8) #define NGTestBit(_x) (((storage[ _x / NGBitsPerEntry ] & \ (1 << (_x % NGBitsPerEntry))) == 0) ? NO : YES) @interface NGConcreteBitSetEnumerator : NSEnumerator { @public unsigned int universe; unsigned int count; NGBitSetStorage *storage; unsigned int position; unsigned int found; } - (id)nextObject; @end @implementation NGBitSet + (id)bitSet { return [[[self alloc] init] autorelease]; } + (id)bitSetWithCapacity:(NSUInteger)_capacity { return [[[self alloc] initWithCapacity:_capacity] autorelease]; } + (id)bitSetWithBitSet:(NGBitSet *)_set { return [[[self alloc] initWithBitSet:_set] autorelease]; } - (id)initWithCapacity:(NSUInteger)_capacity { if ((self = [super init])) { self->universe = (_capacity / NGBitsPerEntry + 1) * NGBitsPerEntry; storage = NGMallocAtomic(NGByteSize); memset(storage, 0, NGByteSize); count = 0; } return self; } - (id)initWithBitSet:(NGBitSet *)_set { if ((self = [self initWithCapacity:NGBitsPerEntry])) { NSEnumerator *enumerator = [_set objectEnumerator]; id obj = nil; while ((obj = [enumerator nextObject])) [self addMember:[obj unsignedIntValue]]; enumerator = nil; } return self; } - (id)init { return [self initWithCapacity:NGBitsPerEntry]; } - (id)initWithNullTerminatedArray:(unsigned int *)_array { if ((self = [self initWithCapacity:NGBitsPerEntry])) { while (*_array) { [self addMember:*_array]; _array++; } } return self; } - (void)dealloc { if (self->storage) { NGFree(self->storage); self->storage = NULL; } [super dealloc]; } /* storage */ - (void)_expandToInclude:(NSUInteger)_element { unsigned int nu = (_element / NGBitsPerEntry + 1) * NGBitsPerEntry; if (nu > self->universe) { void *old = storage; storage = (NGBitSetStorage *)NGMallocAtomic(nu / 8); memset(storage, 0, nu / 8); if (old) { memcpy(storage, old, NGByteSize); NGFree(old); old = NULL; } self->universe = nu; } } /* accessors */ - (NSUInteger)capacity { return self->universe; } - (NSUInteger)count { return count; } /* membership */ - (BOOL)isMember:(NSUInteger)_element { return (_element >= self->universe) ? NO : NGTestBit(_element); } - (void)addMember:(NSUInteger)_element { register unsigned int subIdxPattern = 1 << (_element % NGBitsPerEntry); if (_element >= self->universe) [self _expandToInclude:_element]; if ((storage[ _element / NGBitsPerEntry ] & subIdxPattern) == 0) { storage[ _element / NGBitsPerEntry ] |= subIdxPattern; count++; } } - (void)addMembersInRange:(NSRange)_range { register unsigned int from = _range.location; register unsigned int to = from + _range.length - 1; if (to >= self->universe) [self _expandToInclude:to]; for (; from <= to; from++) { register unsigned int subIdxPattern = 1 << (from % NGBitsPerEntry); if ((storage[ from / NGBitsPerEntry ] & subIdxPattern) == 0) { storage[ from / NGBitsPerEntry ] |= subIdxPattern; count++; } } } - (void)addMembersFromBitSet:(NGBitSet *)_set { unsigned i; if ([_set capacity] > self->universe) [self _expandToInclude:[_set capacity]]; for (i = 0; i < [_set capacity]; i++) { if ([_set isMember:i]) { register unsigned int subIdxPattern = 1 << (i % NGBitsPerEntry); if ((storage[ i / NGBitsPerEntry ] & subIdxPattern) == 0) { storage[ i / NGBitsPerEntry ] |= subIdxPattern; count++; } } } } - (void)removeMember:(NSUInteger)_element { register unsigned int subIdxPattern = 1 << (_element % NGBitsPerEntry); if (_element >= self->universe) return; if ((storage[ _element / NGBitsPerEntry ] & subIdxPattern) != 0) { storage[ _element / NGBitsPerEntry ] -= subIdxPattern; count--; } } - (void)removeMembersInRange:(NSRange)_range { register unsigned int from = _range.location; register unsigned int to = from + _range.length - 1; if (from >= self->universe) return; if (to >= self->universe) to = self->universe - 1; for (; from <= to; from++) { register unsigned int subIdxPattern = 1 << (from % NGBitsPerEntry); if ((storage[ from / NGBitsPerEntry ] & subIdxPattern) != 0) { storage[ from / NGBitsPerEntry ] -= subIdxPattern; count--; } } } - (void)removeAllMembers { memset(storage, 0, NGByteSize); count = 0; } - (NSUInteger)firstMember { register unsigned int element; for (element = 0; element < self->universe; element++) { if (NGTestBit(element)) return element; } return NSNotFound; } - (NSUInteger)lastMember { register NSUInteger element; for (element = (self->universe - 1); element > 0; element--) { if (NGTestBit(element)) return element; } return NSNotFound; } /* equality */ - (BOOL)isEqual:(id)_object { if (self == _object) return YES; if ([self class] != [_object class]) return NO; return [self isEqualToSet:_object]; } - (BOOL)isEqualToSet:(NGBitSet *)_set { if (self == _set) return YES; if (count != [_set count]) return NO; { register unsigned int element; for (element = 0; element < self->universe; element++) { if (NGTestBit(element)) { if (![_set isMember:element]) return NO; } } return YES; } } /* enumerator */ - (NSEnumerator *)objectEnumerator { if (self->count == 0) return nil; else { NGConcreteBitSetEnumerator *en = [[NGConcreteBitSetEnumerator alloc] init]; en->universe = self->universe; en->count = self->count; en->storage = self->storage; return [en autorelease]; } } /* NSCopying */ - (id)copy { return [self copyWithZone:[self zone]]; } - (id)copyWithZone:(NSZone *)_zone { return [[NGBitSet alloc] initWithBitSet:self]; } /* NSCoding */ - (void)encodeWithCoder:(NSCoder *)_coder { unsigned int element; register unsigned int found; [_coder encodeValueOfObjCType:@encode(NSUInteger) at:&count]; for (element = 0, found = 0; (element < self->universe) && (found < count); element++) { if (NGTestBit(element)) { [_coder encodeValueOfObjCType:@encode(NSUInteger) at:&element]; found++; } } } - (id)initWithCoder:(NSCoder *)_coder { if ((self = [super init])) { unsigned int nc; register unsigned int cnt; self->universe = NGBitsPerEntry; storage = NGMallocAtomic(NGByteSize); memset(storage, 0, NGByteSize); [_coder decodeValueOfObjCType:@encode(NSUInteger) at:&nc]; for (cnt = 0; cnt < nc; cnt++) { unsigned int member; [_coder decodeValueOfObjCType:@encode(NSUInteger) at:&member]; [self addMember:member]; } } return self; } /* description */ - (NSString *)description { return [NSString stringWithFormat: @"", self, self->universe, self->count, [[self toArray] description]]; } - (NSArray *)toArray { NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:count + 1]; register unsigned int element, found; for (element = 0, found = 0; (element < self->universe) && (found < self->count); element++) { if (NGTestBit(element)) { [result addObject:[NSNumber numberWithUnsignedInt:element]]; found++; } } return [[[result autorelease] copy] autorelease]; } @end /* NGBitSet */ @implementation NGConcreteBitSetEnumerator - (id)nextObject { if (self->found == self->count) return nil; if (self->position >= self->universe) return nil; while (!NGTestBit(self->position)) self->position++; self->found++; self->position++; return [NSNumber numberWithUnsignedInt:(self->position - 1)]; } @end /* NGConcreteBitSetEnumerator */ NSString *stringValueForBitset(unsigned int _set, char _setC, char _unsetC, short _wide) { char buf[_wide + 1]; register short pos; for (pos = 0; pos < _wide; pos++) { register unsigned int v = (1 << pos); buf[(int)pos] = ((v & _set) == v) ? _setC : _unsetC; } buf[_wide] = '\0'; return [NSString stringWithCString:buf]; } void __link_NGExtensions_NGBitSet() { __link_NGExtensions_NGBitSet(); } SOPE/sope-core/NGExtensions/NGCalendarDateRange.m0000644000000000000000000002000015004363604020462 0ustar rootroot/* Copyright (C) 2004-2007 Marcus Mueller Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGCalendarDateRange.h" #include #include #include "common.h" @implementation NGCalendarDateRange + (id)calendarDateRangeWithStartDate:(NSCalendarDate *)start endDate:(NSCalendarDate *)end { return [[[self alloc] initWithStartDate:start endDate:end] autorelease]; } - (id)initWithStartDate:(NSCalendarDate *)start endDate:(NSCalendarDate *)end { NSAssert(start != nil, @"startDate MUST NOT be nil!"); NSAssert(end != nil, @"endDate MUST NOT be nil!"); if ((self = [super init])) { if ([start compare:end] == NSOrderedAscending) { self->startDate = [start copy]; self->endDate = [end copy]; } else { self->startDate = [end copy]; self->endDate = [start copy]; } } return self; } - (void)dealloc { [self->startDate release]; [self->endDate release]; [super dealloc]; } /* NSCopying */ - (id)copyWithZone:(NSZone *)zone { /* object is immutable */ return [self retain]; } /* accessors */ - (NSCalendarDate *)startDate { return self->startDate; } - (NSCalendarDate *)endDate { return self->endDate; } - (NGCalendarDateRange *)intersectionDateRange:(NGCalendarDateRange *)other { NSCalendarDate *b, *c, *d; if ([self compare:other] == NSOrderedAscending) { b = self->endDate; c = [other startDate]; d = [other endDate]; } else { b = [other endDate]; c = self->startDate; d = self->endDate; } // [a;b[ ?< [c;d[ if ([b compare:c] == NSOrderedAscending) return nil; // no intersection // b ?< d if ([b compare:d] == NSOrderedAscending) { // c !< b && b !< d -> [c;b[ if([c compare:b] == NSOrderedSame) return nil; // no real range, thus return nil! else return [NGCalendarDateRange calendarDateRangeWithStartDate:c endDate:b]; } // if([c compare:d] == NSOrderedSame) // return nil; // no real range, thus return nil! // b !> d -> [c;d[ return [NGCalendarDateRange calendarDateRangeWithStartDate:c endDate:d]; } - (BOOL)doesIntersectWithDateRange:(NGCalendarDateRange *)_other { // TODO: improve if (_other == nil) return NO; return [self intersectionDateRange:_other] != nil ? YES : NO; } - (NGCalendarDateRange *)unionDateRange:(NGCalendarDateRange *)other { NSCalendarDate *a, *b, *d; if ([self compare:other] == NSOrderedAscending) { a = self->startDate; b = self->endDate; d = [other endDate]; } else { a = [other startDate]; b = [other endDate]; d = self->endDate; } if ([b compare:d] == NSOrderedAscending) return [NGCalendarDateRange calendarDateRangeWithStartDate:a endDate:d]; return [NGCalendarDateRange calendarDateRangeWithStartDate:a endDate:b]; } - (BOOL)containsDate:(NSCalendarDate *)_date { NSComparisonResult result; result = [self->startDate compare:_date]; if (!((result == NSOrderedSame) || (result == NSOrderedAscending))) return NO; result = [self->endDate compare:_date]; if (result == NSOrderedAscending) return NO; return YES; } - (BOOL)containsDateRange:(NGCalendarDateRange *)_range { NSComparisonResult result; result = [self->startDate compare:[_range startDate]]; if (!((result == NSOrderedSame) || (result == NSOrderedAscending))) return NO; result = [self->endDate compare:[_range endDate]]; if (result == NSOrderedAscending) return NO; return YES; } - (NSTimeInterval)duration { return [self->endDate timeIntervalSinceDate:self->startDate]; } /* comparison */ - (BOOL)isEqual:(id)other { if (other == nil) return NO; if (other == self) return YES; if ([other isKindOfClass: object_getClass(self)] == NO) return NO; return ([self->startDate isEqual:[other startDate]] && [self->endDate isEqual:[other endDate]]) ? YES : NO; } - (NSUInteger)hash { return [self->startDate hash] ^ [self->endDate hash]; } - (NSComparisonResult)compare:(NGCalendarDateRange *)other { return [self->startDate compare:[other startDate]]; } /* KVC */ - (id)valueForUndefinedKey:(NSString *)_key { /* eg this is used in OGo on 'dateId' to probe for event objects */ return nil; } /* description */ - (NSString *)description { NSMutableString *description; description = [NSMutableString stringWithCapacity:64]; [description appendFormat:@"<%@[0x%p]: startDate:%@ endDate: ", NSStringFromClass(object_getClass(self)), self, self->startDate]; if ([self->startDate isEqual:self->endDate]) [description appendString:@"== startDate"]; else [description appendFormat:@"%@", self->endDate]; [description appendString:@">"]; return description; } @end /* NGCalendarDateRange */ @implementation NSArray(NGCalendarDateRanges) - (NSArray *)arrayByCreatingDateRangesFromObjectsWithStartDateKey:(NSString *)s andEndDateKey:(NSString *)e { NSMutableArray *ma; NSUInteger i, count; count = [self count]; ma = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) { NGCalendarDateRange *daterange; NSCalendarDate *start, *end; id object; object = [self objectAtIndex:i]; start = [object valueForKey:s]; end = [object valueForKey:e]; /* skip invalid data */ if (![start isNotNull]) continue; if (![end isNotNull]) continue; daterange = [[NGCalendarDateRange alloc] initWithStartDate:start endDate:end]; if (daterange) [ma addObject:daterange]; [daterange release]; } return ma; } - (BOOL)dateRangeArrayContainsDate:(NSCalendarDate *)_date { NSUInteger i, count; if (_date == nil) return NO; if ((count = [self count]) == 0) return NO; for (i = 0; i < count; i++) { if ([[self objectAtIndex:i] containsDate:_date]) return YES; } return NO; } - (NSUInteger)indexOfFirstIntersectingDateRange:(NGCalendarDateRange *)_range { NSUInteger i, count; if (_range == nil) return NO; if ((count = [self count]) == 0) return NSNotFound; for (i = 0; i < count; i++) { if ([[self objectAtIndex:i] doesIntersectWithDateRange:_range]) return i; } return NSNotFound; } - (NSArray *)arrayByCompactingContainedDateRanges { // TODO: this is a candidate for unit testing ... // TODO: pretty "slow" algorithm, improve NSMutableArray *ma; NSUInteger i, count; count = [self count]; if (count < 2) return [[self copy] autorelease]; ma = [NSMutableArray arrayWithCapacity:count]; [ma addObject:[self objectAtIndex:0]]; /* add first range */ for (i = 1; i < count; i++) { NGCalendarDateRange *rangeToAdd; NGCalendarDateRange *availRange; NGCalendarDateRange *newRange; NSUInteger idx; rangeToAdd = [self objectAtIndex:i]; idx = [ma indexOfFirstIntersectingDateRange:rangeToAdd]; if (idx == NSNotFound) { /* range not yet covered in array */ [ma addObject:rangeToAdd]; continue; } /* union old range and replace the entry */ availRange = [ma objectAtIndex:idx]; newRange = [availRange unionDateRange:rangeToAdd]; [ma replaceObjectAtIndex:idx withObject:newRange]; } /* Note: we might want to join ranges up to some "closeness" (eg 1s)? */ return [ma sortedArrayUsingSelector:@selector(compare:)]; } @end /* NSArray(NGCalendarDateRanges) */ SOPE/sope-core/NGExtensions/NGMerging.m0000644000000000000000000001267415004363604016610 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMerging.h" #include "common.h" #import #import static NSString *NGCannotMergeWithObjectException = @"NGCannotMergeWithObjectException"; @implementation NSObject(NGMerging) - (BOOL)canMergeWithObject:(id)_object { return ((_object == nil) || (_object == self)) ? YES : NO; } - (id)_makeMergeCopyWithZone:(NSZone *)_zone { return [(id)self copyWithZone:_zone]; } - (id)mergeWithObject:(id)_object zone:(NSZone *)_zone { if ((_object == nil) || (_object == self)) return [self _makeMergeCopyWithZone:_zone]; [NSException raise:NGCannotMergeWithObjectException format:@"cannot merge objects of class %@ and %@", NSStringFromClass([self class]), NSStringFromClass([_object class])]; return nil; } - (id)mergeWithObject:(id)_object { return [self mergeWithObject:_object zone:NULL]; } @end @implementation NSDictionary(NGMerging) - (BOOL)canMergeWithObject:(id)_object { if ((self == _object) || (_object == nil)) return YES; if ([_object isKindOfClass:[NSDictionary class]]) return YES; return NO; } - (id)_makeMergeCopyWithZone:(NSZone *)_zone { return [self retain]; } - (id)mergeWithDictionary:(NSDictionary *)_object zone:(NSZone *)_zone { NSMutableDictionary *result; NSArray *aKeys, *bKeys; int i, count; if ((self == _object) || (_object == nil)) return [self _makeMergeCopyWithZone:_zone]; aKeys = [self allKeys]; bKeys = [_object allKeys]; result = [NSMutableDictionary dictionary]; /* merge all keys of a */ for (i = 0, count = [aKeys count]; i < count; i++) { id key; id av, bv; key = [aKeys objectAtIndex:i]; av = [self objectForKey:key]; bv = [_object objectForKey:key]; if (bv == nil) { /* key is only in a */ [result setObject:av forKey:key]; } else { /* key is in both - need to merge */ if ([av canMergeWithObject:bv]) { av = [av mergeWithObject:bv zone:_zone]; [result setObject:av forKey:key]; } else // if objects cannot be merged, av wins [result setObject:av forKey:key]; } } /* add remaining keys in b */ for (i = 0, count = [bKeys count]; i < count; i++) { id key; key = [bKeys objectAtIndex:i]; if ([result objectForKey:key]) // already merged key .. continue; [result setObject:[_object objectForKey:key] forKey:key]; } return result; } - (id)mergeWithObject:(id)_object zone:(NSZone *)_zone { if ((self == _object) || (_object == nil)) return [self _makeMergeCopyWithZone:_zone]; if ([_object isKindOfClass:[NSDictionary class]]) return [self mergeWithDictionary:_object zone:_zone]; [NSException raise:NGCannotMergeWithObjectException format:@"cannot merge %@ with %@", NSStringFromClass([self class]), NSStringFromClass([_object class])]; return nil; } @end @implementation NSMutableDictionary(NGMerging) - (id)_makeMergeCopyWithZone:(NSZone *)_zone { return [self copyWithZone:_zone]; } @end @implementation NSArray(NGMerging) - (BOOL)canMergeWithObject:(id)_object { if ((self == _object) || (_object == nil)) return YES; if ([_object respondsToSelector:@selector(objectEnumerator)]) return YES; return NO; } - (id)_makeMergeCopyWithZone:(NSZone *)_zone { return [self retain]; } - (id)mergeWithEnumeration:(NSEnumerator *)_object zone:(NSZone *)_zone { NSMutableArray *result; id value; if (_object == nil) return [self _makeMergeCopyWithZone:_zone]; /* make copy of self */ result = [[self mutableCopyWithZone:_zone] autorelease]; /* add other elements */ while ((value = [_object nextObject])) [result addObject:value]; return result; } - (id)mergeWithArray:(NSArray *)_object zone:(NSZone *)_zone { if (_object == nil) return [self _makeMergeCopyWithZone:_zone]; return [self arrayByAddingObjectsFromArray:_object]; } - (id)mergeWithObject:(id)_object zone:(NSZone *)_zone { if (_object == nil) return [self _makeMergeCopyWithZone:_zone]; if ([_object respondsToSelector:@selector(objectEnumerator)]) return [self mergeWithEnumeration:[_object objectEnumerator] zone:_zone]; [NSException raise:NGCannotMergeWithObjectException format:@"cannot merge %@ with %@", NSStringFromClass([self class]), NSStringFromClass([_object class])]; return nil; } @end @implementation NSMutableArray(NGMerging) - (id)_makeMergeCopyWithZone:(NSZone *)_zone { return [self copyWithZone:_zone]; } @end // for static linking void __link_NGExtensions_NGMerging(void) { __link_NGExtensions_NGMerging(); } SOPE/sope-core/NGExtensions/COPYING0000644000000000000000000006130315004363604015641 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-core/NGExtensions/fhs.make0000644000000000000000000000175515004363604016232 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) FHS_INCLUDE_DIR=$(FHS_INSTALL_ROOT)/include/ FHS_BIN_DIR=$(FHS_INSTALL_ROOT)/bin/ ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib64/ else FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib/ endif fhs-header-dirs :: $(MKDIRS) $(FHS_INCLUDE_DIR)$(libNGExtensions_HEADER_FILES_INSTALL_DIR) move-headers-to-fhs :: fhs-header-dirs @echo "moving headers to $(FHS_INCLUDE_DIR) .." mv $(GNUSTEP_HEADERS)$(libNGExtensions_HEADER_FILES_INSTALL_DIR)/*.h \ $(FHS_INCLUDE_DIR)$(libNGExtensions_HEADER_FILES_INSTALL_DIR)/ NONFHS_LIBDIR="$(GNUSTEP_LIBRARIES)/$(GNUSTEP_TARGET_LDIR)/" NONFHS_LIBNAME="$(LIBRARY_NAME)$(LIBRARY_NAME_SUFFIX)$(SHARED_LIBEXT)" move-libs-to-fhs :: @echo "moving libs to $(FHS_LIB_DIR) .." mv $(NONFHS_LIBDIR)/$(NONFHS_LIBNAME)* $(FHS_LIB_DIR)/ move-to-fhs :: move-headers-to-fhs move-libs-to-fhs after-install :: move-to-fhs endif SOPE/sope-core/NGExtensions/NGBase64Coding.m0000644000000000000000000003346015004363604017364 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGBase64Coding.h" #include "common.h" #import #import #import static inline BOOL isbase64(char a) { if (('A' <= a) && (a <= 'Z')) return YES; if (('a' <= a) && (a <= 'z')) return YES; if (('0' <= a) && (a <= '9')) return YES; if ((a == '+') || (a == '/')) return YES; return NO; } static inline int encode_base64(const char *_src, size_t _srcLen, char *_dest, size_t _destSize, size_t *_destLen, int _maxLineWidth); static inline int decode_base64(const char *_src, size_t _srcLen, char *_dest, size_t _destSize, size_t *_destLen); @implementation NSString(Base64Coding) static Class StringClass = Nil; static int NSStringMaxLineWidth = 1024; - (NSString *)stringByEncodingBase64 { unsigned len; size_t destSize; size_t destLength = -1; const char *src; char *dest; NSString *result; src = [self UTF8String]; len = strlen (src); if (len > 0) { destSize = ((len + 2) * 4) / 3; // 3:4 conversion ratio destSize += destSize / NSStringMaxLineWidth + 2; // space for '\n' and '\0' destSize += 64; dest = malloc (destSize + 4); NSAssert(dest, @"invalid buffer .."); if (encode_base64 (src, len, dest, destSize, &destLength, NSStringMaxLineWidth) == 0) { // base64 must *always* be transported as ascii result = [[NSString alloc] initWithBytesNoCopy:dest length:destLength encoding:NSASCIIStringEncoding freeWhenDone:YES]; [result autorelease]; } else { free(dest); result = nil; } } else result = @""; return result; } - (NSString *)stringByDecodingBase64 { unsigned len; size_t destSize; size_t destLength = -1; const char *src; char *dest; NSString *result; if (StringClass == Nil) StringClass = [NSString class]; src = [self UTF8String]; len = strlen (src); if (len > 0) { destSize = ((len * 3 ) / 4) + 4; dest = malloc (destSize + 1); NSAssert(dest, @"invalid buffer .."); if (decode_base64(src, len, dest, destSize, &destLength) == 0) { NSAssert (destLength < destSize, @"buffer overflow"); if (*dest == '\0' && destLength > 0) { [self errorWithFormat: @"(%s): could not decode '%@' as string (contains \\0 bytes)!", __PRETTY_FUNCTION__, self]; abort(); // not executed past this point result = nil; } else { result = [[StringClass alloc] initWithBytes:dest length:destLength encoding:NSUTF8StringEncoding]; // we fallback on latin 1 if (!result) result = [[StringClass alloc] initWithBytes:dest length:destLength encoding:NSISOLatin1StringEncoding]; free(dest); [result autorelease]; } } else { free(dest); result = nil; } } else result = @""; return result; } - (NSData *)dataByDecodingBase64 { unsigned len; size_t destSize; size_t destLength = -1; const char *src; char *dest; NSData *result; if (StringClass == Nil) StringClass = [NSString class]; src = [self UTF8String]; len = strlen(src); if (len > 0) { destSize = ((len * 3) / 4) + 4; dest = malloc(destSize + 1); NSAssert(dest, @"invalid buffer .."); if (decode_base64(src, len, dest, destSize, &destLength) == 0) { NSAssert (destLength < destSize, @"buffer overflow"); result = [NSData dataWithBytesNoCopy:dest length:destLength]; } else { free(dest); result = nil; } } else result = [NSData data]; return result; } @end /* NSString(Base64Coding) */ @implementation NSData(Base64Coding) // TODO: explain that size (which RFC specifies that?) static int NSDataMaxLineWidth = 72; - (NSData *)dataByEncodingBase64WithLineLength:(unsigned)_lineLength { unsigned len; size_t destSize; size_t destLength = -1; char *dest; if ((len = [self length]) == 0) return [NSData data]; destSize = ((len + 2) * 4) / 3; // 3:4 conversion ratio destSize += destSize / _lineLength + 2; // space for newlines and '\0' destSize += 64; dest = malloc(destSize + 4); NSAssert(dest, @"invalid buffer .."); if (encode_base64([self bytes], len, dest, destSize, &destLength, _lineLength) == 0) { NSAssert (destLength < destSize, @"buffer overflow"); return [NSData dataWithBytesNoCopy:dest length:destLength]; } if (dest != NULL) free((void *)dest); return nil; } - (NSData *)dataByEncodingBase64 { return [self dataByEncodingBase64WithLineLength:NSDataMaxLineWidth]; } - (NSData *)dataByDecodingBase64 { unsigned len; size_t destSize; size_t destLength = -1; char *dest; if ((len = [self length]) == 0) return [NSData data]; destSize = (len / 4 + 1) * 3 + 1; dest = malloc(destSize + 4); NSAssert(dest, @"invalid buffer .."); if (decode_base64([self bytes], len, dest, destSize, &destLength) == 0) { NSAssert (destLength < destSize, @"buffer overflow"); return [NSData dataWithBytesNoCopy:dest length:destLength]; } if (dest) free(dest); return nil; } - (NSString *)stringByEncodingBase64 { NSData *data; NSString *result; data = [self dataByEncodingBase64]; if (data) { // base64 must *always* be transported as ascii result = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; [result autorelease]; } else result = nil; return result; } - (NSString *)stringByDecodingBase64 { NSData *data; NSString *result; data = [self dataByDecodingBase64]; if (data) { result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; if (!result) result = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding]; [result autorelease]; } else result = nil; return result; } @end /* NSData(Base64Coding) */ // functions int NGEncodeBase64(const void *_source, unsigned _len, void *_buffer, unsigned _bufferCapacity, int _maxLineWidth) { size_t len; if ((_source == NULL) || (_buffer == NULL) || (_bufferCapacity == 0)) return -1; { // check whether buffer is big enough size_t outSize; outSize = ((_len + 2) * 4) / 3; // 3:4 conversion ratio outSize += (outSize / _maxLineWidth) + 2; // Space for newlines and NUL if (_bufferCapacity < outSize) return -1; } if (encode_base64(_source, _len, _buffer, _bufferCapacity, &len, _maxLineWidth) == 0) { return len; } else return -1; } int NGDecodeBase64(const void *_source, unsigned _len, void *_buffer, unsigned _bufferCapacity) { size_t len; if ((_source == NULL) || (_buffer == NULL) || (_bufferCapacity == 0)) return -1; if (((_len / 4 + 1) * 3 + 1) > _bufferCapacity) return -1; if (decode_base64(_source, _len, _buffer, _bufferCapacity, &len) == 0) return len; else return -1; } // private implementation static char base64tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz0123456789+/"; static char base64idx[128] = { '\377','\377','\377','\377','\377','\377','\377','\377', '\377','\377','\377','\377','\377','\377','\377','\377', '\377','\377','\377','\377','\377','\377','\377','\377', '\377','\377','\377','\377','\377','\377','\377','\377', '\377','\377','\377','\377','\377','\377','\377','\377', '\377','\377','\377', 62,'\377','\377','\377', 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,'\377','\377','\377','\377','\377','\377', '\377', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,'\377','\377','\377','\377','\377', '\377', 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,'\377','\377','\377','\377','\377' }; static inline int encode_base64(const char *_src, size_t _srcLen, char *_dest, size_t _destSize, size_t *_destLen, int _maxLineWidth) { size_t inLen = _srcLen; char *out = _dest; size_t inPos = 0; size_t outPos = 0; int c1, c2, c3; unsigned i; // Get three characters at a time and encode them. for (i = 0; i < inLen / 3; ++i) { c1 = _src[inPos++] & 0xFF; c2 = _src[inPos++] & 0xFF; c3 = _src[inPos++] & 0xFF; out[outPos++] = base64tab[(c1 & 0xFC) >> 2]; out[outPos++] = base64tab[((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4)]; out[outPos++] = base64tab[((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6)]; out[outPos++] = base64tab[c3 & 0x3F]; if ((outPos + 1) % (_maxLineWidth + 1) == 0) out[outPos++] = '\n'; } // Encode the remaining one or two characters. switch (inLen % 3) { case 1: c1 = _src[inPos] & 0xFF; out[outPos++] = base64tab[(c1 & 0xFC) >> 2]; out[outPos++] = base64tab[((c1 & 0x03) << 4)]; out[outPos++] = '='; out[outPos++] = '='; break; case 2: c1 = _src[inPos++] & 0xFF; c2 = _src[inPos] & 0xFF; out[outPos++] = base64tab[(c1 & 0xFC) >> 2]; out[outPos++] = base64tab[((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4)]; out[outPos++] = base64tab[((c2 & 0x0F) << 2)]; out[outPos++] = '='; break; } out[outPos] = 0; *_destLen = outPos; return 0; } static inline int decode_base64(const char *_src, size_t inLen, char *out, size_t _destSize, size_t *_destLen) { BOOL isErr = NO; BOOL isEndSeen = NO; register int b1, b2, b3; register int a1, a2, a3, a4; register size_t inPos = 0; register size_t outPos = 0; /* Get four input chars at a time and decode them. Ignore white space * chars (CR, LF, SP, HT). If '=' is encountered, terminate input. If * a char other than white space, base64 char, or '=' is encountered, * flag an input error, but otherwise ignore the char. */ while (inPos < inLen) { a1 = a2 = a3 = a4 = 0; // get byte 1 while (inPos < inLen) { a1 = _src[inPos++] & 0xFF; if (isbase64(a1)) break; else if (a1 == '=') { isEndSeen = YES; break; } else if (a1 != '\r' && a1 != '\n' && a1 != ' ' && a1 != '\t') { isErr = YES; } } // get byte 2 while (inPos < inLen) { a2 = _src[inPos++] & 0xFF; if (isbase64(a2)) break; else if (a2 == '=') { isEndSeen = YES; break; } else if (a2 != '\r' && a2 != '\n' && a2 != ' ' && a2 != '\t') { isErr = YES; } } // get byte 3 while (inPos < inLen) { a3 = _src[inPos++] & 0xFF; if (isbase64(a3)) break; else if (a3 == '=') { isEndSeen = YES; break; } else if (a3 != '\r' && a3 != '\n' && a3 != ' ' && a3 != '\t') { isErr = YES; } } // get byte 4 while (inPos < inLen) { a4 = _src[inPos++] & 0xFF; if (isbase64(a4)) break; else if (a4 == '=') { isEndSeen = YES; break; } else if (a4 != '\r' && a4 != '\n' && a4 != ' ' && a4 != '\t') { isErr = YES; } } // complete chunk if (isbase64(a1) && isbase64(a2) && isbase64(a3) && isbase64(a4)) { a1 = base64idx[a1] & 0xFF; a2 = base64idx[a2] & 0xFF; a3 = base64idx[a3] & 0xFF; a4 = base64idx[a4] & 0xFF; b1 = ((a1 << 2) & 0xFC) | ((a2 >> 4) & 0x03); b2 = ((a2 << 4) & 0xF0) | ((a3 >> 2) & 0x0F); b3 = ((a3 << 6) & 0xC0) | ( a4 & 0x3F); out[outPos++] = (char)b1; out[outPos++] = (char)b2; out[outPos++] = (char)b3; } // 3-chunk else if (isbase64(a1) && isbase64(a2) && isbase64(a3) && a4 == '=') { a1 = base64idx[a1] & 0xFF; a2 = base64idx[a2] & 0xFF; a3 = base64idx[a3] & 0xFF; b1 = ((a1 << 2) & 0xFC) | ((a2 >> 4) & 0x03); b2 = ((a2 << 4) & 0xF0) | ((a3 >> 2) & 0x0F); out[outPos++] = (char)b1; out[outPos++] = (char)b2; break; } // 2-chunk else if (isbase64(a1) && isbase64(a2) && a3 == '=' && a4 == '=') { a1 = base64idx[a1] & 0xFF; a2 = base64idx[a2] & 0xFF; b1 = ((a1 << 2) & 0xFC) | ((a2 >> 4) & 0x03); out[outPos++] = (char)b1; break; } // invalid state else { break; } if (isEndSeen) break; } *_destLen = outPos; return (isErr) ? -1 : 0; } // for static linking void __link_NGBase64Coding(void) { __link_NGBase64Coding(); } SOPE/sope-core/NGExtensions/NGExtensions.m0000644000000000000000000000360015004363604017344 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGExtensions.h" #include "NGBase64Coding.h" #include "NGBaseTypes.h" #include "NGBitSet.h" #include "NGHashMap.h" #include "NGMemoryAllocation.h" #include "NGStack.h" #include "NGBundleManager.h" #include "NGQuotedPrintableCoding.h" #include "NSArray+enumerator.h" #include "NSData+misc.h" #include "NSException+misc.h" #include "NSObject+Values.h" #include "NSSet+enumerator.h" #include "NSString+Formatting.h" #include "NSString+misc.h" #include "NSDictionary+misc.h" #include "NSCalendarDate+misc.h" @implementation NGExtensions /* statically link Objective-C categories */ extern void __link_NSProcessInfo_misc(void); extern void __link_NSCalendarDate_misc(void); extern void __link_EODataSource_NGExtensions(void); extern void __link_NSString_Formatting(void); extern void __link_NGBase64Coding(void); extern void __link_NGExtensions_NSObjectValues(void); - (void)_staticLinkClasses { __link_NSProcessInfo_misc(); __link_NSCalendarDate_misc(); __link_EODataSource_NGExtensions(); __link_NSString_Formatting(); __link_NGBase64Coding(); __link_NGExtensions_NSObjectValues(); } @end /* NGExtensions */ SOPE/sope-core/NGExtensions/NGDirectoryEnumerator.m0000644000000000000000000001755315004363604021227 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGDirectoryEnumerator.h" #import #include "common.h" @interface NGDirectoryEnumerator(PrivateMethods) - (void)recurseIntoDirectory:(NSString *)_path relativeName:(NSString *)_name; - (void)backtrack; - (void)findNextFile; @end @interface NGDirEntry : NSObject { @public id fileManager; NSString *path; NSEnumerator *e; } - (id)initWithFileManager:(id)_fm path:(NSString *)_path; - (NSString *)readdir; @end @implementation NGDirectoryEnumerator - (id)initWithFileManager:(id)_fm directoryPath:(NSString *)_path recurseIntoSubdirectories:(BOOL)_recurse followSymlinks:(BOOL)_follow prefixFiles:(BOOL)_prefix { self->fileManager = _fm ? [_fm retain] : (id)[[NSFileManager defaultManager] retain]; self->pathStack = [[NSMutableArray alloc] init]; self->enumStack = [[NSMutableArray alloc] init]; self->flags.isRecursive = _recurse; self->flags.isFollowing = _follow; self->topPath = [_path copy]; [self recurseIntoDirectory:_path relativeName:@""]; return self; } - (id)initWithDirectoryPath:(NSString *)_path recurseIntoSubdirectories:(BOOL)_recurse followSymlinks:(BOOL)_follow prefixFiles:(BOOL)_prefix { return [self initWithFileManager:nil directoryPath:_path recurseIntoSubdirectories:_recurse followSymlinks:_follow prefixFiles:_prefix]; } - (id)initWithFileManager:(id)_fm { return [self initWithFileManager:_fm directoryPath:@"/" recurseIntoSubdirectories:YES followSymlinks:NO prefixFiles:YES]; } - (id)initWithFileManager:(id)_fm directoryPath:(NSString *)_path { return [self initWithFileManager:_fm directoryPath:_path recurseIntoSubdirectories:YES followSymlinks:NO prefixFiles:YES]; } - (void)dealloc { while ([self->pathStack count]) [self backtrack]; [self->pathStack release]; [self->enumStack release]; [self->currentFileName release]; [self->currentFilePath release]; [self->topPath release]; [super dealloc]; } /* accessors */ - (id)fileManager { return self->fileManager; } /* operations */ - (NSDictionary *)directoryAttributes { return [self->fileManager fileAttributesAtPath:self->topPath traverseLink:self->flags.isFollowing]; } - (NSDictionary *)fileAttributes { return [self->fileManager fileAttributesAtPath:self->currentFilePath traverseLink:self->flags.isFollowing]; } - (void)skipDescendents { if ([self->pathStack count]) [self backtrack]; } /* enumerator */ - (id)nextObject { [self findNextFile]; return self->currentFileName; } /* internals */ - (void)recurseIntoDirectory:(NSString *)_path relativeName:(NSString *)name { /* recurses into directory `path' - pushes relative path (relative to root of search) on pathStack - pushes system dir enumerator on enumPath */ NGDirEntry *dir; //NSLog(@"RECURSE INTO: %@", _path); dir = [[NGDirEntry alloc] initWithFileManager:self->fileManager path:_path]; if (dir) { [pathStack addObject:name]; [enumStack addObject:dir]; } } - (void)backtrack { /* backtracks enumeration to the previous dir - pops current dir relative path from pathStack - pops system dir enumerator from enumStack - sets currentFile* to nil */ //NSLog(@"BACKTRACK: %@", [self->pathStack lastObject]); [self->enumStack removeLastObject]; [self->pathStack removeLastObject]; [self->currentFileName release]; self->currentFileName = nil; [self->currentFilePath release]; self->currentFilePath = nil; } - (void)findNextFile { /* finds the next file according to the top enumerator - if there is a next file it is put in currentFile - if the current file is a directory and if isRecursive calls recurseIntoDirectory:currentFile - if the current file is a symlink to a directory and if isRecursive and isFollowing calls recurseIntoDirectory:currentFile - if at end of current directory pops stack and attempts to find the next entry in the parent - sets currentFile to nil if there are no more files to enumerate */ NGDirEntry *dir; [self->currentFileName release]; self->currentFileName = nil; [self->currentFilePath release]; self->currentFilePath = nil; while ([self->pathStack count]) { NSString *dname; NSString *dtype; dir = [enumStack lastObject]; if ((dname = [dir readdir]) == nil) { /* If we reached the end of this directory, go back to the upper one */ [self backtrack]; continue; } /* Skip "." and ".." directory entries */ if ([dname isEqualToString:@"."]) continue; if ([dname isEqualToString:@".."]) continue; /* Name of current file */ self->currentFileName = [[[pathStack lastObject] stringByAppendingPathComponent:dname] copy]; /* Full path of current file */ self->currentFilePath = [[self->topPath stringByAppendingPathComponent:self->currentFileName] copy]; dtype = [[self->fileManager fileAttributesAtPath:self->currentFilePath traverseLink:self->flags.isFollowing] objectForKey:NSFileType]; // do not follow links if (!flags.isFollowing) { if ([dtype isEqualToString:NSFileTypeSymbolicLink]) /* if link then return it as link */ break; } /* Follow links - check for directory */ if ([dtype isEqualToString:NSFileTypeDirectory] && self->flags.isRecursive) { [self recurseIntoDirectory:self->currentFilePath relativeName:self->currentFileName]; } break; } } - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<%@[0x%p]: ", NSStringFromClass([self class]), self]; [ms appendFormat:@" dir='%@'", self->topPath]; [ms appendFormat:@" cname='%@'", self->currentFileName]; [ms appendFormat:@" cpath='%@'", self->currentFilePath]; [ms appendString:@">"]; return ms; } @end /* NGDirectoryEnumerator */ @implementation NGDirEntry - (id)initWithFileManager:(id)_fm path:(NSString *)_p{ self->fileManager = [_fm retain]; self->path = [_p copy]; return self; } - (void)dealloc { [self->e release]; [self->path release]; [self->fileManager release]; [super dealloc]; } /* operations */ - (NSString *)readdir { NSString *s; if (self->e == nil) { self->e = [[[self->fileManager directoryContentsAtPath:self->path] sortedArrayUsingSelector: @selector(compare:)] objectEnumerator]; self->e = [self->e retain]; } s = [self->e nextObject]; // [self logWithFormat:@"readdir: %@", s]; return s; } @end /* NGDirEntry */ SOPE/sope-core/NGExtensions/EOExt.subproj/0000755000000000000000000000000015004363604017252 5ustar rootrootSOPE/sope-core/NGExtensions/EOExt.subproj/EOSortOrdering+plist.m0000644000000000000000000000677415004363604023442 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "common.h" @implementation EOSortOrdering(plist) /*" Initialize a sort-ordering with information contained in the dictionary. The following keys are recognized: "key" is required and specifies the key to be sorted on, "selector" is optional and specifies the sort selector as a string. The default for "selector" is EOCompareAscending and the following "special" values are recognized: "compareAscending", "compareDescending", "compareCaseInsensitiveAscending", "compareCaseInsensitiveDescending". "*/ - (id)initWithDictionary:(NSDictionary *)_dict { NSString *k = nil; SEL sel = EOCompareAscending; NSString *tmp; if (_dict == nil) { [self release]; return nil; } k = [_dict objectForKey:@"key"]; if ([k length] == 0) { NSLog(@"%s: invalid key %@ (dict=%@)", __PRETTY_FUNCTION__, k, _dict); [self release]; return nil; } if ((tmp = [[_dict objectForKey:@"selector"] stringValue])) { if ([tmp isEqualToString:@"compareAscending"]) sel = EOCompareAscending; else if ([tmp isEqualToString:@"compareDescending"]) sel = EOCompareDescending; else if ([tmp isEqualToString:@"compareCaseInsensitiveAscending"]) sel = EOCompareCaseInsensitiveAscending; else if ([tmp isEqualToString:@"compareCaseInsensitiveDescending"]) sel = EOCompareCaseInsensitiveDescending; else sel = NSSelectorFromString(tmp); } return [self initWithKey:k selector:sel]; } /*" Initialize/parse a sort-ordering from a string. Usually the string is taken as the key of the ordering and the sorting EOCompareAscending. This can be modified by adding ".reverse" to the key, eg "name.reverse" sorts on the "name" key using EOCompareDescending. "*/ - (id)initWithString:(NSString *)_string { SEL sel; NSString *k; NSRange r; if ([_string length] == 0) { [self release]; return nil; } r = [_string rangeOfString:@".reverse"]; if (r.length == 0) { k = _string; sel = EOCompareAscending; } else { k = [_string substringToIndex:r.location]; sel = EOCompareDescending; } return [self initWithKey:k selector:sel]; } - (id)initWithPropertyList:(id)_plist owner:(id)_owner { if (_plist == nil) { [self release]; return nil; } if ([_plist isKindOfClass:[NSDictionary class]]) return [self initWithDictionary:_plist]; if ([_plist isKindOfClass:[NSString class]]) return [self initWithString:_plist]; if ([_plist isKindOfClass:[self class]]) { [self release]; return [_plist copy]; } [self release]; return nil; } - (id)initWithPropertyList:(id)_plist { return [self initWithPropertyList:_plist owner:nil]; } @end /* EOSortOrdering(plist) */ SOPE/sope-core/NGExtensions/EOExt.subproj/EOKeyMapDataSource.m0000644000000000000000000002526015004363604023022 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOKeyMapDataSource.h" #include "NSArray+enumerator.h" #include "EODataSource+NGExtensions.h" #include "NSNull+misc.h" #import #include "common.h" #include @interface EOKeyMapDataSource(Private) - (void)_registerForSource:(id)_source; - (void)_removeObserverForSource:(id)_source; - (void)_sourceChanged; @end @implementation EOKeyMapDataSource - (id)initWithDataSource:(EODataSource *)_ds map:(id)_map { if ((self = [super init])) { self->source = [_ds retain]; self->map = [_map retain]; [self _registerForSource:self->source]; } return self; } - (id)initWithDataSource:(EODataSource *)_ds { return [self initWithDataSource:_ds map:nil]; } - (id)init { return [self initWithDataSource:nil map:nil]; } - (void)dealloc { [self _removeObserverForSource:self->source]; [self->classDescription release]; [self->entityKeys release]; [self->mappedKeys release]; [self->map release]; [self->fspec release]; [self->source release]; [super dealloc]; } /* mapping */ - (EOFetchSpecification *)mapFetchSpecification:(EOFetchSpecification *)_fs { return [_fs fetchSpecificationByApplyingKeyMap:self->map]; } - (id)mapFromSourceObject:(id)_object { id values; if (_object == nil) return nil; if (self->mappedKeys == nil) { /* no need to rewrite keys, only taking a subset */ values = [_object valuesForKeys:self->entityKeys]; } else { unsigned i, count; count = [self->entityKeys count]; values = [NSMutableDictionary dictionaryWithCapacity:count]; for (i = 0; i < count; i++) { NSString *key, *newKey; id value; key = [self->mappedKeys objectAtIndex:i]; newKey = [self->entityKeys objectAtIndex:i]; value = [_object valueForKey:key]; if (value) [(NSMutableDictionary *)values setObject:value forKey:newKey]; } } return [[[EOMappedObject alloc] initWithObject:_object values:values] autorelease]; } - (id)mapToSourceObject:(id)_object { // TODO if (_object == nil) return nil; if ([_object isKindOfClass:[EOMappedObject class]]) { id obj; if ((obj = [_object mappedObject]) == nil) { NSLog(@"don't know how to back-map objects: %@", _object); return nil; } if ([obj isModified]) { if (self->map) { NSLog(@"%s: don't know how to back-map modified object: %@", __PRETTY_FUNCTION__, _object); #if NeXT_Foundation_LIBRARY [self doesNotRecognizeSelector:_cmd]; return nil; // keep compiler happy #else return [self notImplemented:_cmd]; #endif } [obj applyChangesOnObject]; } return obj; } else { NSLog(@"don't know how to back-map objects of class %@", [_object class]); #if NeXT_Foundation_LIBRARY [self doesNotRecognizeSelector:_cmd]; #else return [self notImplemented:_cmd]; #endif } return nil; // keep compiler happy } - (id)mapCreatedObject:(id)_object { return [self mapFromSourceObject:_object]; } - (id)mapObjectForUpdate:(id)_object { return [self mapToSourceObject:_object]; } - (id)mapObjectForInsert:(id)_object { return [self mapToSourceObject:_object]; } - (id)mapObjectForDelete:(id)_object { return [self mapToSourceObject:_object]; } - (id)mapFetchedObject:(id)_object { return [self mapFromSourceObject:_object]; } - (void)setClassDescriptionForObjects:(NSClassDescription *)_cd { ASSIGN(self->classDescription, _cd); /* setup array of keys to map */ [self->entityKeys release]; self->entityKeys = nil; [self->mappedKeys release]; self->mappedKeys = nil; if (_cd != nil) { NSMutableArray *ma; NSArray *tmp; unsigned i, count; ma = [[NSMutableArray alloc] initWithCapacity:16]; /* first, collect keys we need */ if ((tmp = [_cd attributeKeys]) != nil) [ma addObjectsFromArray:tmp]; if ((tmp = [_cd toOneRelationshipKeys]) != nil) [ma addObjectsFromArray:tmp]; if ((tmp = [_cd toManyRelationshipKeys]) != nil) [ma addObjectsFromArray:tmp]; self->entityKeys = [ma copy]; /* next, map those keys to the source-schema */ if (self->map != nil) { [ma removeAllObjects]; for (i = 0, count = [entityKeys count]; i < count; i++) { NSString *mappedKey, *key; key = [entityKeys objectAtIndex:i]; mappedKey = [self->map valueForKey:key]; [ma addObject:mappedKey ? mappedKey : key]; } self->mappedKeys = [ma copy]; } [ma release]; } } - (NSClassDescription *)classDescriptionForObjects { return self->classDescription; } /* accessors */ - (void)setSource:(EODataSource *)_source { NSAssert(self->fspec == nil, @"only allowed as long as no spec is set !"); [self _removeObserverForSource:self->source]; ASSIGN(self->source, _source); [self _registerForSource:self->source]; [self postDataSourceChangedNotification]; } - (EODataSource *)source { return self->source; } - (void)setFetchSpecification:(EOFetchSpecification *)_fetchSpec { EOFetchSpecification *mappedSpec; if ([_fetchSpec isEqual:self->fspec]) return; /* This saves the spec in the datasource and saves a mapped spec in the source datasource. */ ASSIGN(self->fspec, _fetchSpec); mappedSpec = [self mapFetchSpecification:self->fspec]; [self->source setFetchSpecification:mappedSpec]; [self postDataSourceChangedNotification]; } - (EOFetchSpecification *)fetchSpecification { return self->fspec; } - (NSException *)lastException { if ([self->source respondsToSelector:@selector(lastException)]) return [(id)self->source lastException]; return nil; } /* fetch operations */ - (Class)fetchEnumeratorClass { return [EOKeyMapDataSourceEnumerator class]; } - (NSEnumerator *)fetchEnumerator { NSEnumerator *e; if ((e = [self->source fetchEnumerator]) == nil) return nil; e = [[[self fetchEnumeratorClass] alloc] initWithKeyMapDataSource:self fetchEnumerator:e]; return [e autorelease]; } - (NSArray *)fetchObjects { NSAutoreleasePool *pool; NSArray *a; pool = [[NSAutoreleasePool alloc] init]; a = [[NSArray alloc] initWithObjectsFromEnumerator:[self fetchEnumerator]]; [pool release]; return [a autorelease]; } /* modifications */ - (void)insertObject:(id)_obj { [self->source insertObject:[self mapObjectForInsert:_obj]]; } - (void)deleteObject:(id)_obj { [self->source deleteObject:[self mapObjectForDelete:_obj]]; } - (id)createObject { return [self mapCreatedObject:[self->source createObject]]; } - (void)updateObject:(id)_obj { [self->source updateObject:[self mapObjectForUpdate:_obj]]; } - (void)clear { if ([self->source respondsToSelector:@selector(clear)]) [(id)self->source clear]; } /* description */ - (NSString *)description { NSString *fmt; fmt = [NSString stringWithFormat:@"<%@[0x%p]: source=%@ map=%@>", NSStringFromClass([self class]), self, self->source, self->map]; return fmt; } /* private */ - (void)_registerForSource:(id)_source { static NSNotificationCenter *nc = nil; if (_source != nil) { if (nc == nil) nc = [[NSNotificationCenter defaultCenter] retain]; [nc addObserver:self selector:@selector(_sourceChanged) name:EODataSourceDidChangeNotification object:_source]; } } - (void)_removeObserverForSource:(id)_source { static NSNotificationCenter *nc = nil; if (_source != nil) { if (nc == nil) nc = [NSNotificationCenter defaultCenter]; [nc removeObserver:self name:EODataSourceDidChangeNotification object:_source]; } } - (void)_sourceChanged { [self postDataSourceChangedNotification]; } @end /* EOKeyMapDataSource */ @implementation EOKeyMapDataSourceEnumerator - (id)initWithKeyMapDataSource:(EOKeyMapDataSource *)_ds fetchEnumerator:(NSEnumerator *)_enum { if ((self = [super init])) { self->ds = [_ds retain]; self->source = [_enum retain]; } return self; } - (void)dealloc { [self->ds release]; [self->source release]; [super dealloc]; } /* fetching */ - (void)fetchDone { } - (id)nextObject { id object; if ((object = [self->source nextObject]) == nil) { [self fetchDone]; return nil; } return [self->ds mapFetchedObject:object]; } @end /* EOKeyMapDataSourceEnumerator */ @implementation EOMappedObject - (id)initWithObject:(id)_object values:(NSDictionary *)_values { if ((self = [super init])) { self->original = [_object retain]; self->values = [_values mutableCopy]; } return self; } - (void)dealloc { [self->original release]; [self->globalID release]; [self->values release]; [super dealloc]; } /* accessors */ - (id)mappedObject { return self->original; } - (EOGlobalID *)globalID { if (self->globalID == nil) { if ([self->original respondsToSelector:@selector(globalID)]) self->globalID = [[self->original globalID] retain]; } return self->globalID; } - (BOOL)isModified { return self->flags.didChange ? YES : NO; } - (void)willChange { self->flags.didChange = 1; } - (void)applyChangesOnObject { if (!self->flags.didChange) [self->original takeValuesFromDictionary:self->values]; } /* mimic dictionary */ - (void)setObject:(id)_obj forKey:(id)_key { [self willChange]; [self->values setObject:_obj forKey:_key]; } - (id)objectForKey:(id)_key { return [self->values objectForKey:_key]; } - (void)removeObjectForKey:(id)_key { [self willChange]; [self->values removeObjectForKey:_key]; } - (NSEnumerator *)keyEnumerator { return [self->values keyEnumerator]; } - (NSEnumerator *)objectEnumerator { return [self->values objectEnumerator]; } - (NSDictionary *)asDictionary { return self->values; } /* KVC */ - (void)takeValue:(id)_value forKey:(NSString *)_key { [self willChange]; if ([_value isNotNull]) [self->values setObject:_value forKey:_key]; else [self->values removeObjectForKey:_key]; } - (id)valueForKey:(NSString *)_key { return [self->values objectForKey:_key]; } @end /* EOMappedObject */ SOPE/sope-core/NGExtensions/EOExt.subproj/EOFetchSpecification+plist.m0000644000000000000000000000767215004363604024551 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #import #include "common.h" @implementation EOFetchSpecification(plist) - (id)initWithDictionary:(NSDictionary *)_dictionary { if ((self = [self init]) != nil) { id tmp; // TODO: add groupings if ((tmp = [_dictionary objectForKey:@"qualifier"]) != nil) { if ([tmp isKindOfClass:[NSDictionary class]]) tmp = [EOQualifier qualifierToMatchAllValues:tmp]; else tmp = [EOQualifier qualifierWithQualifierFormat:tmp]; [self setQualifier:tmp]; } if ((tmp = [_dictionary objectForKey:@"sortOrderings"]) != nil) { NSArray *sos = nil; EOSortOrdering *so; if ([tmp isKindOfClass:[NSArray class]]) { NSMutableArray *result = nil; NSEnumerator *objEnum; id obj; objEnum = [tmp objectEnumerator]; result = [NSMutableArray arrayWithCapacity:8]; while ((obj = [objEnum nextObject])) { so = [[EOSortOrdering alloc] initWithPropertyList:obj owner:nil]; [so autorelease]; if (so) [result addObject:so]; } sos = [[NSArray alloc] initWithArray:result]; } else { so = [[[EOSortOrdering alloc] initWithPropertyList:tmp owner:nil] autorelease]; if (so != nil) sos = [[NSArray alloc] initWithObjects:&so count:1]; } if (sos != nil) [self setSortOrderings:sos]; [sos release]; } if ((tmp = [_dictionary objectForKey:@"fetchLimit"]) != nil) { if ([tmp respondsToSelector:@selector(intValue)]) [self setFetchLimit:[tmp intValue]]; else NSLog(@"%s: invalid fetchLimit key !", __PRETTY_FUNCTION__); } if ((tmp = [_dictionary objectForKey:@"hints"])) { if ([tmp isKindOfClass:[NSDictionary class]]) [self setHints:tmp]; else NSLog(@"%s: invalid hints key !", __PRETTY_FUNCTION__); } if ([[self hints] objectForKey:@"addDocumentsAsObserver"] == nil) { NSMutableDictionary *hnts; hnts = [[NSMutableDictionary alloc] initWithDictionary:[self hints]]; [hnts setObject:[NSNumber numberWithBool:NO] forKey:@"addDocumentsAsObserver"]; [self setHints:hnts]; [hnts release]; } } return self; } - (id)initWithString:(NSString *)_string { EOQualifier *q; q = [EOQualifier qualifierWithQualifierFormat:_string]; return [self initWithEntityName:nil qualifier:q sortOrderings:nil usesDistinct:NO isDeep:NO hints:nil]; } - (id)initWithPropertyList:(id)_plist owner:(id)_owner { if ([_plist isKindOfClass:[NSDictionary class]]) return [self initWithDictionary:_plist]; if ([_plist isKindOfClass:[NSString class]]) return [self initWithString:_plist]; if ([_plist isKindOfClass:[self class]]) { [self release]; return [_plist copy]; } [self release]; return nil; } - (id)initWithPropertyList:(id)_plist { return [self initWithPropertyList:_plist owner:nil]; } @end /* EOFetchSpecification(plist) */ SOPE/sope-core/NGExtensions/EOExt.subproj/EOQualifier+CtxEval.m0000644000000000000000000001473315004363604023147 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOQualifier+CtxEval.h" #import #import #include "common.h" #if LIB_FOUNDATION_LIBRARY # import # import # import #elif GNUSTEP_BASE_LIBRARY #if __GNU_LIBOBJC__ >= 20100911 # import #else # import #endif #else # import #endif static inline int countSelArgs(SEL _sel) { register const char *selName; if ((selName = sel_getName(_sel))) { register int count; for (count = 0; *selName; selName++) { if (*selName == ':') count++; } return count + 2; } else return -1; } @implementation EOQualifier(ContextEvaluation) - (BOOL)evaluateWithObject:(id)_object context:(id)_context { [self doesNotRecognizeSelector:_cmd]; /* subclass */ return NO; } @end /* EOQualifier(ContextEvaluation) */ @implementation NSArray(ContextEvaluation) - (NSArray *)filteredArrayUsingQualifier:(EOQualifier *)_qualifier context:(id)_context { NSMutableArray *a = nil; unsigned i, count; for (i = 0, count = [self count]; i < count; i++) { id o; o = [self objectAtIndex:i]; if ([_qualifier evaluateWithObject:o context:_context]) { if (a == nil) a = [NSMutableArray arrayWithCapacity:count]; [a addObject:o]; } } return a ? [[a copy] autorelease] : [NSArray array]; } @end /* NSArray(ContextEvaluation) */ @implementation EOAndQualifier(ContextEvaluation) - (BOOL)evaluateWithObject:(id)_object context:(id)_context { unsigned i; IMP objAtIdx; NSArray *qs; qs = [self qualifiers]; objAtIdx = [qs methodForSelector:@selector(objectAtIndex:)]; for (i = 0; i < [qs count]; i++) { EOQualifier *q; q = objAtIdx(qs, @selector(objectAtIndex:), i); if (![q evaluateWithObject:_object context:_context]) return NO; } return YES; } @end /* EOAndQualifier(ContextEvaluation) */ @implementation EOOrQualifier(ContextEvaluation) - (BOOL)evaluateWithObject:(id)_object context:(id)_context { unsigned i; IMP objAtIdx; NSArray *qs; qs = [self qualifiers]; objAtIdx = [qs methodForSelector:@selector(objectAtIndex:)]; for (i = 0; i < [qs count]; i++) { EOQualifier *q; q = objAtIdx(qs, @selector(objectAtIndex:), i); if ([q evaluateWithObject:_object context:_context]) return YES; } return NO; } @end /* EOOrQualifier(ContextEvaluation) */ @implementation EONotQualifier(ContextEvaluation) - (BOOL)evaluateWithObject:(id)_object context:(id)_context { return [[self qualifier] evaluateWithObject:_object context:_context] ? NO : YES; } @end /* EONotQualifier(ContextEvaluation) */ @implementation EOKeyValueQualifier(ContextEvaluation) - (BOOL)evaluateWithObject:(id)_object context:(id)_context { static EONull *null = nil; id lv, rv; union { IMP m; BOOL (*unary)(id, SEL); BOOL (*binary)(id, SEL, id); BOOL (*ctx)(id, SEL, id, id); } m; SEL op; op = [self selector]; lv = [_object valueForKeyPath:[self key]]; rv = [self value]; if (null == nil) null = [EONull null]; if (lv == nil) lv = null; if (rv == nil) rv = null; if ((m.m = [lv methodForSelector:op]) == NULL) { /* no such operator method ! */ [lv doesNotRecognizeSelector:op]; return NO; } switch (countSelArgs(op)) { case 0: case 1: NSLog(@"%s: called with invalid selector %@", __PRETTY_FUNCTION__, NSStringFromSelector(op)); return NO; case 2: return m.unary(lv, op); case 3: return m.binary(lv, op, rv); default: return m.ctx(lv, op, rv, _context); } } @end /* EOKeyValueQualifier(ContextEvaluation) */ @implementation EOKeyComparisonQualifier(ContextEvaluation) - (BOOL)evaluateWithObject:(id)_object context:(id)_context { static EONull *null = nil; id lv, rv; union { IMP m; BOOL (*unary)(id, SEL); BOOL (*binary)(id, SEL, id); BOOL (*ctx)(id, SEL, id, id); } m; SEL op; lv = [_object valueForKeyPath:[self leftKey]]; rv = [_object valueForKeyPath:[self rightKey]]; if (null == nil) null = [EONull null]; if (lv == nil) lv = null; if (rv == nil) rv = null; op = [self selector]; if ((m.m = (void *)[lv methodForSelector:op]) == NULL) { /* no such operator method ! */ [lv doesNotRecognizeSelector:op]; return NO; } switch (countSelArgs(op)) { case 0: case 1: NSLog(@"%s: called with invalid selector %@", __PRETTY_FUNCTION__, NSStringFromSelector(op)); return NO; case 2: return m.unary(lv, op); case 3: return m.binary(lv, op, rv); default: return m.ctx(lv, op, rv, _context); } } @end /* EOKeyComparisonQualifier(ContextEvaluation) */ @implementation NSObject(ImplementedQualifierComparisons2) - (BOOL)isEqualTo:(id)_object inContext:(id)_context { return [self isEqualTo:_object]; } - (BOOL)isNotEqualTo:(id)_object inContext:(id)_context { return [self isNotEqualTo:_object]; } - (BOOL)isLessThan:(id)_object inContext:(id)_context { return [self isLessThan:_object]; } - (BOOL)isGreaterThan:(id)_object inContext:(id)_context { return [self isGreaterThan:_object]; } - (BOOL)isLessThanOrEqualTo:(id)_object inContext:(id)_context { return [self isLessThanOrEqualTo:_object]; } - (BOOL)isGreaterThanOrEqualTo:(id)_object inContext:(id)_context { return [self isGreaterThanOrEqualTo:_object]; } - (BOOL)doesContain:(id)_object inContext:(id)_context { return [self doesContain:_object]; } - (BOOL)isLike:(NSString *)_object inContext:(id)_context { return [self isLike:_object]; } - (BOOL)isCaseInsensitiveLike:(NSString *)_object inContext:(id)_context { return [self isCaseInsensitiveLike:_object]; } @end SOPE/sope-core/NGExtensions/EOExt.subproj/EOQualifierGrouping.m0000644000000000000000000000366215004363604023317 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOGrouping.h" #import #include "common.h" @implementation EOQualifierGrouping - (id)initWithQualifier:(EOQualifier *)_qualifier name:(NSString *)_name { if ((self = [super initWithDefaultName:nil])) { self->name = [_name copy]; self->qualifier = [_qualifier retain]; } return self; } - (void)dealloc { [self->qualifier release]; [self->name release]; [super dealloc]; } /* accessors */ - (void)setName:(NSString *)_name { NSAssert1(_name != nil, @"%s: name is nil", __PRETTY_FUNCTION__); ASSIGNCOPY(self->name, _name); } - (NSString *)name { return self->name; } - (void)setQualifier:(EOQualifier *)_qualifier { ASSIGN(self->qualifier, _qualifier); } - (EOQualifier *)qualifier { return self->qualifier; } /* operations */ - (NSString *)groupNameForObject:(id)_object { if (self->qualifier == nil) return self->name; if ([(id)self->qualifier evaluateWithObject:_object]) return self->name; return self->defaultName; } - (NSArray *)orderedGroupNames { return [NSArray arrayWithObjects:[self name], [self defaultName], nil]; } @end /* EOQualifierGrouping */ SOPE/sope-core/NGExtensions/EOExt.subproj/EOKeyGrouping.m0000644000000000000000000000370315004363604022122 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOGrouping.h" #include "common.h" @implementation EOKeyGrouping - (id)initWithKey:(NSString *)_key { if ((self = [super initWithDefaultName:nil]) != nil) { self->key = [_key copy]; // TODO: create on-demand? self->groupNames = [[NSMutableArray alloc] initWithCapacity:32]; } return self; } - (void)dealloc { [self->key release]; [self->groupNames release]; [super dealloc]; } /* accessors */ - (void)setKey:(NSString *)_key { NSAssert1(_key != nil, @"%s: nil _key parameter", __PRETTY_FUNCTION__); ASSIGNCOPY(self->key, _key); } - (NSString *)key { return self->key; } /* operations */ - (NSString *)groupNameForObject:(id)_object { NSString *result = nil; if ([self->key length] == 0) return @""; result = [[_object valueForKey:self->key] stringValue]; result = (result != nil) ? result : self->defaultName; if (result == nil) return nil; if (![self->groupNames containsObject:result]) [self->groupNames addObject:result]; return result; } - (NSArray *)orderedGroupNames { if ([self->key length] == 0) return [NSArray arrayWithObject:@""]; return self->groupNames; } @end /* EOKeyGrouping */ SOPE/sope-core/NGExtensions/EOExt.subproj/GNUmakefile0000644000000000000000000000134515004363604021327 0ustar rootroot# GNUstep makefile include ../../../config.make include ../../common.make SUBPROJECT_NAME = EOExt EOExt_PCH_FILE = common.h EOExt_OBJC_FILES = \ EOCacheDataSource.m \ EOCompoundDataSource.m \ EODataSource+NGExtensions.m \ EOFetchSpecification+plist.m \ EOFilterDataSource.m \ EOGrouping.m \ EOGroupingSet.m \ EOKeyGrouping.m \ EOKeyMapDataSource.m \ EOQualifier+CtxEval.m \ EOQualifier+plist.m \ EOQualifierGrouping.m \ EOSortOrdering+plist.m \ EOTrueQualifier.m \ NSArray+EOGrouping.m \ EOGlobalID+Ext.m \ ADDITIONAL_INCLUDE_DIRS += -I. -I.. -I../NGExtensions/ \ -I../FdExt.subproj/ \ -I../.. -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/subproject.make -include GNUmakefile.postamble SOPE/sope-core/NGExtensions/EOExt.subproj/NSArray+EOGrouping.m0000644000000000000000000000513015004363604022760 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOGrouping.h" #import #include "common.h" @implementation NSArray(EOGrouping) static BOOL ProfileComponents = NO; - (NSDictionary *)arrayGroupedBy:(EOGrouping *)_grouping { NSMutableDictionary *result; NSEnumerator *keyEnum; NSString *key; NSArray *sortings; int i, cnt; IMP objAtIndex; IMP groupForObj; NSTimeInterval st = 0.0; if (ProfileComponents) st = [[NSDate date] timeIntervalSince1970]; cnt = [self count]; result = [NSMutableDictionary dictionaryWithCapacity:cnt]; objAtIndex = [self methodForSelector:@selector(objectAtIndex:)]; groupForObj = [_grouping methodForSelector:@selector(groupNameForObject:)]; for (i = 0; i < cnt; i++) { NSString *gName = nil; // groupName NSMutableArray *tmp = nil; id obj = nil; obj = objAtIndex(self, @selector(objectAtIndex:), i); gName = groupForObj(_grouping, @selector(groupNameForObject:), obj); if (gName == nil) continue; if (!(tmp = [result objectForKey:gName])) { tmp = [[[NSMutableArray alloc] initWithCapacity:4] autorelease]; [result setObject:tmp forKey:gName]; } [tmp addObject:obj]; } sortings = [_grouping sortOrderings]; if ([sortings count] > 0) { // sort each group keyEnum = [result keyEnumerator]; while ((key = [keyEnum nextObject])) { NSArray *tmp; tmp = [result objectForKey:key]; tmp = [tmp sortedArrayUsingKeyOrderArray:sortings]; [result setObject:tmp forKey:key]; } } if (ProfileComponents) { NSTimeInterval diff; diff = [[NSDate date] timeIntervalSince1970] - st; printf("NSArray+Grouping: %0.4fs\n", diff); } return result; } @end /* NSArray(EOGrouping) */ SOPE/sope-core/NGExtensions/EOExt.subproj/common.h0000644000000000000000000000002715004363604020712 0ustar rootroot#include "../common.h" SOPE/sope-core/NGExtensions/EOExt.subproj/EOFilterDataSource.m0000644000000000000000000001400715004363604023056 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOFilterDataSource.h" #include "EODataSource+NGExtensions.h" #include "EOGrouping.h" #import #include "common.h" @interface NSDictionary(EOFilterDataSource) - (NSArray *)flattenedArrayWithHint:(unsigned int)_hint andKeys:(NSArray *)_keys; @end @implementation EOFilterDataSource - (id)initWithDataSource:(EODataSource *)_ds { if ((self = [super init])) { [self setSource:_ds]; } return self; } - (id)init { return [self initWithDataSource:nil]; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [self->sortOrderings release]; [self->groupings release]; [self->auxiliaryQualifier release]; [self->source release]; [super dealloc]; } /* accessors */ - (void)setSource:(EODataSource *)_source { NSNotificationCenter *nc; if (self->source == _source) return; nc = [NSNotificationCenter defaultCenter]; if (self->source) { [nc removeObserver:self name:EODataSourceDidChangeNotification object:self->source]; } ASSIGN(self->source, _source); if (self->source) { [nc addObserver:self selector:@selector(_sourceDidChange:) name:EODataSourceDidChangeNotification object:self->source]; } [self postDataSourceChangedNotification]; } - (EODataSource *)source { return self->source; } - (void)setAuxiliaryQualifier:(EOQualifier *)_q { if ([_q isEqual:self->auxiliaryQualifier]) return; ASSIGN(self->auxiliaryQualifier, _q); [self postDataSourceChangedNotification]; } - (EOQualifier *)auxiliaryQualifier { return self->auxiliaryQualifier; } - (void)setSortOrderings:(NSArray *)_so { if (self->sortOrderings == _so) return; _so = [_so shallowCopy]; [self->sortOrderings release]; self->sortOrderings = _so; [self postDataSourceChangedNotification]; } - (NSArray *)sortOrderings { return self->sortOrderings; } - (void)setGroupings:(NSArray *)_groupings { if (self->groupings == _groupings) return; _groupings = [_groupings shallowCopy]; [self->groupings release]; self->groupings = _groupings; [self postDataSourceChangedNotification]; } - (NSArray *)groupings { return self->groupings; } - (void)setFetchSpecification:(EOFetchSpecification *)_fspec { [[self source] setFetchSpecification:_fspec]; } - (EOFetchSpecification *)fetchSpecification { return [[self source] fetchSpecification]; } /* notifications */ - (void)_sourceDidChange:(NSNotification *)_notification { [self postDataSourceChangedNotification]; } /* operations */ - (NSArray *)fetchObjects { NSAutoreleasePool *pool; NSArray *objs; NSArray *groups; pool = [[NSAutoreleasePool alloc] init]; objs = [[self source] fetchObjects]; if ([self auxiliaryQualifier] != nil) objs = [objs filteredArrayUsingQualifier:[self auxiliaryQualifier]]; if ((groups = [self groupings]) != nil) { unsigned int cnt; EOGrouping *grouping; NSArray *allKeys; NSArray *sos; NSDictionary *groupDict; cnt = [objs count]; grouping = [groups lastObject]; if ((sos = [self sortOrderings]) != nil) [grouping setSortOrderings:sos]; groupDict = [objs arrayGroupedBy:grouping]; allKeys = [groupDict allKeys]; allKeys = [allKeys sortedArrayUsingSelector:@selector(compare:)]; objs = [groupDict flattenedArrayWithHint:cnt andKeys:allKeys]; } else if ([self sortOrderings] != nil) objs = [objs sortedArrayUsingKeyOrderArray:[self sortOrderings]]; objs = [objs copy]; [pool release]; return [objs autorelease]; } - (void)insertObject:(id)_obj { [[self source] insertObject:_obj]; } - (void)deleteObject:(id)_obj { [[self source] deleteObject:_obj]; } - (void)updateObject:(id)_obj { [self->source updateObject:_obj]; } - (id)createObject { return [[self source] createObject]; } - (EOClassDescription *)classDescriptionForObjects { return [[self source] classDescriptionForObjects]; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:64]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if (self->source != nil) [ms appendFormat:@" source=%@", self->source]; if (self->auxiliaryQualifier != nil) [ms appendFormat:@" qualifier=%@", self->auxiliaryQualifier]; if (self->sortOrderings != nil) [ms appendFormat:@" orderings=%@", self->sortOrderings]; if (self->groupings != nil) [ms appendFormat:@" groupings=%@", self->groupings]; [ms appendString:@">"]; return ms; } @end /* EOFilterDataSource */ @implementation NSDictionary(EOFilterDataSource) - (NSArray *)flattenedArrayWithHint:(unsigned int)_hint andKeys:(NSArray *)_keys { /* This works on a dictionary of arrays. It walks over the keys in the given order and flattenes the value arrays into one array. */ NSMutableArray *result = nil; unsigned int i, cnt; result = [[NSMutableArray alloc] initWithCapacity:_hint]; // should be improved for (i = 0, cnt = [_keys count]; i < cnt; i++) { NSString *key; NSArray *tmp; key = [_keys objectAtIndex:i]; tmp = [self objectForKey:key]; [result addObjectsFromArray:tmp]; } return [result autorelease]; } @end /* NSDictionary(EOFilterDataSource) */ SOPE/sope-core/NGExtensions/EOExt.subproj/EOTrueQualifier.m0000644000000000000000000000242415004363604022437 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOTrueQualifier.h" #include "common.h" @implementation EOTrueQualifier static EOTrueQualifier *tq = nil; - (id)init { if (tq == nil) { tq = [[super init] retain]; return tq; } else { [self release]; return [tq retain]; } } - (BOOL)evaluateWithObject:(id)_object { /* we always evaluate to "true" ... */ return YES; } /* description */ - (NSString *)stringValue { return @"*true*"; } - (NSString *)description { return [self stringValue]; } @end /* EOTrueQualifier */ SOPE/sope-core/NGExtensions/EOExt.subproj/EOQualifier+plist.m0000644000000000000000000000432015004363604022723 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "common.h" @implementation EOQualifier(plist) - (id)initWithDictionary:(NSDictionary *)_dict { [self release]; return [[EOQualifier qualifierToMatchAllValues:_dict] retain]; } - (id)initWithArray:(NSArray *)_array { unsigned count; NSString *fmt; NSArray *args; [self release]; if ((count = [_array count]) == 0) { NSLog(@"%s: invalid array for qualifier: %@", __PRETTY_FUNCTION__, _array); return nil; } fmt = [_array objectAtIndex:0]; if (count == 1) args = nil; else args = [_array subarrayWithRange:NSMakeRange(1, (count - 1))]; return [[EOQualifier qualifierWithQualifierFormat:fmt arguments:args] retain]; } - (id)initWithString:(NSString *)_string { [self release]; return [[EOQualifier qualifierWithQualifierFormat:_string] retain]; } - (id)initWithPropertyList:(id)_plist owner:(id)_owner { if ([_plist isKindOfClass:[NSDictionary class]]) return [self initWithDictionary:_plist]; if ([_plist isKindOfClass:[NSString class]]) return [self initWithString:_plist]; if ([_plist isKindOfClass:[NSArray class]]) return [self initWithArray:_plist]; if ([_plist isKindOfClass:[self class]]) { [self release]; return [_plist copy]; } [self release]; return nil; } - (id)initWithPropertyList:(id)_plist { return [self initWithPropertyList:_plist owner:nil]; } @end /* EOQualifier(plist) */ SOPE/sope-core/NGExtensions/EOExt.subproj/EOGlobalID+Ext.m0000644000000000000000000000215015004363604022023 0ustar rootroot/* Copyright (C) 2008 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #import #import @implementation EOGlobalID(SOPEExt) #if !LIB_FOUNDATION_LIBRARY - (id)valueForUndefinedKey:(NSString *)_key { NSLog(@"WARNING: tried to access undefined KVC key '%@' on GID object: %@", _key, self); return nil; } #endif @end /* EOGlobalID(SOPEExt) */ SOPE/sope-core/NGExtensions/EOExt.subproj/EOGroupingSet.m0000644000000000000000000000432115004363604022122 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOGrouping.h" #include "common.h" @interface EOGroupingSet(PrivateMethodes) - (void)_updateDefaultNames; @end @implementation EOGroupingSet - (void)dealloc { [self->groupings release]; [super dealloc]; } - (void)setGroupings:(NSArray *)_groupings { ASSIGN(self->groupings, _groupings); [self _updateDefaultNames]; } - (NSArray *)groupings { return self->groupings; } - (void)setDefaultName:(NSString *)_defaultName { [super setDefaultName:_defaultName]; [self _updateDefaultNames]; } - (NSString *)groupNameForObject:(id)_object { NSString *result; int i, cnt; for (i = 0, cnt = [self->groupings count]; i < cnt; i++) { EOGrouping *group; group = [self->groupings objectAtIndex:i]; if ((result = [group groupNameForObject:_object])) return result; } return self->defaultName; } - (NSArray *)orderedGroupNames { NSMutableArray *result; unsigned int i, cnt; result = [NSMutableArray arrayWithCapacity:8]; for (i = 0, cnt = [self->groupings count]; i < cnt; i++) { EOGrouping *group; group = [self->groupings objectAtIndex:i]; [result addObjectsFromArray:[group orderedGroupNames]]; } return result; } /* PrivateMethodes */ - (void)_updateDefaultNames { unsigned int i, cnt; for (i = 0, cnt = [self->groupings count]; i < cnt; i++) { EOGrouping *group; group = [self->groupings objectAtIndex:i]; [group setDefaultName:nil]; } } @end /* EOGroupingSet */ SOPE/sope-core/NGExtensions/EOExt.subproj/EODataSource+NGExtensions.m0000644000000000000000000000343315004363604024271 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EODataSource+NGExtensions.h" #import #include "common.h" NGExtensions_DECLARE NSString *EODataSourceDidChangeNotification = @"EODataSourceDidChangeNotification"; NGExtensions_DECLARE NSString *EONoFetchWithEmptyQualifierHint = @"EONoFetchWithEmptyQualifierHint"; @implementation EODataSource(NGExtensions) - (void)setFetchSpecification:(EOFetchSpecification *)_fetchSpec { [self doesNotRecognizeSelector:_cmd]; } - (EOFetchSpecification *)fetchSpecification { [self doesNotRecognizeSelector:_cmd]; return nil; } - (void)updateObject:(id)_obj { [self doesNotRecognizeSelector:_cmd]; } - (void)postDataSourceChangedNotification { static NSNotificationCenter *nc = nil; if (nc == nil) nc = [[NSNotificationCenter defaultCenter] retain]; [nc postNotificationName:EODataSourceDidChangeNotification object:self]; } @end /* EODataSource(NGExtensions) */ /* static linking */ void __link_EODataSource_NGExtensions(void) { __link_EODataSource_NGExtensions(); } SOPE/sope-core/NGExtensions/EOExt.subproj/EOCacheDataSource.m0000644000000000000000000001273215004363604022637 0ustar rootroot/* Copyright (C) 2000-2006 SKYRIX Software AG Copyright (C) 2006 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //#define PROFILE 1 #include "EOCacheDataSource.h" #import #import "EODataSource+NGExtensions.h" #import "common.h" #include @interface EOCacheDataSource(Private) - (void)_registerForSource:(id)_source; - (void)_removeObserverForSource:(id)_source; - (void)_clearCache; @end @interface EOCacheDataSourceTimer : NSObject { @public EOCacheDataSource *ds; /* non-retained! */ } @end @implementation EOCacheDataSource - (id)initWithDataSource:(EODataSource *)_ds { if ((self = [super init])) { self->source = [_ds retain]; self->timeout = 0; self->timer = nil; self->time = 0; [self _registerForSource:self->source]; } return self; } - (void)dealloc { [self _removeObserverForSource:self->source]; [self->timer invalidate]; [self->timer release]; [self->source release]; [self->cache release]; [super dealloc]; } /* accessors */ - (void)setSource:(EODataSource *)_source { if (self->source == _source) return; [self _removeObserverForSource:self->source]; ASSIGN(self->source, _source); [self _registerForSource:self->source]; [self _clearCache]; } - (EODataSource *)source { return self->source; } - (void)setTimeout:(NSTimeInterval)_timeout { self->timeout = _timeout; } - (NSTimeInterval)timeout { return self->timeout; } /* operations */ - (NSArray *)fetchObjects { BEGIN_PROFILE; self->_isFetching = YES; if (self->time > 0) { if (self->time < [[NSDate date] timeIntervalSinceReferenceDate]) { [self->cache release]; self->cache = nil; } } if (self->cache == nil) { self->time = 0; if (self->timer != nil) { [self->timer invalidate]; [self->timer release]; self->timer = nil; } self->cache = [[self->source fetchObjects] retain]; if (self->timeout > 0) { EOCacheDataSourceTimer *holder; /* this object is here to avoid a retain cycle */ holder = [[EOCacheDataSourceTimer alloc] init]; holder->ds = self; self->time = [[NSDate date] timeIntervalSinceReferenceDate] + self->timeout; /* the timer retains the holder, but no the DS */ self->timer = [[NSTimer scheduledTimerWithTimeInterval:self->timeout target:holder selector:@selector(clear) userInfo:nil repeats:NO] retain]; [holder release]; holder = nil; } PROFILE_CHECKPOINT("cache miss"); } else { PROFILE_CHECKPOINT("cache hit"); } self->_isFetching = NO; END_PROFILE; return self->cache; } - (void)setFetchSpecification:(EOFetchSpecification *)_fetchSpec { [self->source setFetchSpecification:_fetchSpec]; } - (EOFetchSpecification *)fetchSpecification { return [self->source fetchSpecification]; } /* operations */ - (void)insertObject:(id)_obj { [self _clearCache]; [self->source insertObject:_obj]; } - (void)deleteObject:(id)_obj { [self _clearCache]; [self->source deleteObject:_obj]; } - (id)createObject { return [self->source createObject]; } - (void)updateObject:(id)_obj { [self->source updateObject:_obj]; [self _clearCache]; } - (EOClassDescription *)classDescriptionForObjects { return [[self source] classDescriptionForObjects]; } - (void)clear { [self _clearCache]; } /* description */ - (NSString *)description { NSString *fmt; fmt = [NSString stringWithFormat:@"<%@[0x%p]: source=%@>", NSStringFromClass([self class]), self, self->source]; return fmt; } /* private methods */ - (void)_registerForSource:(id)_source { static NSNotificationCenter *nc = nil; if (_source != nil) { if (nc == nil) nc = [[NSNotificationCenter defaultCenter] retain]; [nc addObserver:self selector:@selector(_clearCache) name:EODataSourceDidChangeNotification object:_source]; } } - (void)_removeObserverForSource:(id)_source { static NSNotificationCenter *nc = nil; if (_source != nil) { if (nc == nil) nc = [NSNotificationCenter defaultCenter]; [nc removeObserver:self name:EODataSourceDidChangeNotification object:_source]; } } - (void)_clearCache { #if DEBUG && 0 NSLog(@"clearing cache (%s)...", self->_isFetching?"fetching":""); if (fgetc(stdin) == 'a') abort(); #endif self->time = 0; if (self->timer) { [self->timer invalidate]; [self->timer release]; self->timer = nil; } if (self->cache) { [self->cache release]; self->cache = nil; [self postDataSourceChangedNotification]; } } @end /* EOCacheDataSource */ @implementation EOCacheDataSourceTimer - (void)clear { [self->ds clear]; } @end /* EOCacheDataSourceTimer */ SOPE/sope-core/NGExtensions/EOExt.subproj/EOCompoundDataSource.m0000644000000000000000000001520015004363604023411 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOCompoundDataSource.h" #import #import "EODataSource+NGExtensions.h" #import "common.h" @implementation EOCompoundDataSource - (id)initWithDataSources:(NSArray *)_ds { if ((self = [super init])) { self->sources = [_ds shallowCopy]; } return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [self->sortOrderings release]; [self->auxiliaryQualifier release]; [self->sources release]; [super dealloc]; } /* accessors */ - (void)setSources:(NSArray *)_sources { NSNotificationCenter *nc; NSEnumerator *enumerator; id obj; if (self->sources == _sources) return; // BUG: this needs to unregister the old datssources! _sources = [_sources shallowCopy]; [self->sources release]; self->sources = _sources; nc = [NSNotificationCenter defaultCenter]; enumerator = [self->sources objectEnumerator]; while ((obj = [enumerator nextObject]) != nil) { [nc addObserver:self selector:@selector(postDataSourceChangedNotification) name:EODataSourceDidChangeNotification object:obj]; } [self postDataSourceChangedNotification]; } - (NSArray *)sources { return self->sources; } - (void)setAuxiliaryQualifier:(EOQualifier *)_q { ASSIGN(self->auxiliaryQualifier, _q); [self postDataSourceChangedNotification]; } - (EOQualifier *)auxiliaryQualifier { return self->auxiliaryQualifier; } - (void)setSortOrderings:(NSArray *)_so { if (self->sortOrderings == _so) return; _so = [_so shallowCopy]; [self->sortOrderings release]; self->sortOrderings = _so; [self postDataSourceChangedNotification]; } - (NSArray *)sortOrderings { return self->sortOrderings; } /* operations */ - (NSArray *)fetchObjects { NSArray *objs; unsigned count; if ((count = [[self sources] count]) == 0) { objs = nil; } else if (count == 1) objs = [[[self sources] objectAtIndex:0] fetchObjects]; else { NSMutableArray *a; NSEnumerator *e; EODataSource *ds; a = nil; e = [[self sources] objectEnumerator]; while ((ds = [e nextObject])) { NSArray *o; o = [ds fetchObjects]; if ([o count] > 0) { if (a == nil) a = [NSMutableArray arrayWithCapacity:[o count]]; [a addObjectsFromArray:o]; } } objs = [[a shallowCopy] autorelease]; } if (objs == nil) return [NSArray array]; if ([self auxiliaryQualifier] != nil) objs = [objs filteredArrayUsingQualifier:[self auxiliaryQualifier]]; if ([self sortOrderings] != nil) objs = [objs sortedArrayUsingKeyOrderArray:[self sortOrderings]]; return objs; } - (void)insertObject:(id)_obj { unsigned count; if ((count = [[self sources] count]) == 0) [super insertObject:_obj]; else if (count == 1) [[[self sources] objectAtIndex:0] insertObject:_obj]; else { NSEnumerator *e; EODataSource *ds; e = [[self sources] objectEnumerator]; while ((ds = [e nextObject])) { BOOL didFail = NO; NS_DURING [ds insertObject:_obj]; NS_HANDLER didFail = YES; NS_ENDHANDLER; if (!didFail) return; } /* all datasources failed to insert .. */ [super insertObject:_obj]; } [self postDataSourceChangedNotification]; } - (void)deleteObject:(id)_obj { unsigned count; if ((count = [[self sources] count]) == 0) [super deleteObject:_obj]; else if (count == 1) [[[self sources] objectAtIndex:0] deleteObject:_obj]; else { NSEnumerator *e; EODataSource *ds; e = [[self sources] objectEnumerator]; while ((ds = [e nextObject])) { BOOL didFail = NO; NS_DURING [ds deleteObject:_obj]; NS_HANDLER didFail = YES; NS_ENDHANDLER; if (!didFail) return; } /* all datasources failed to delete .. */ [super deleteObject:_obj]; } [self postDataSourceChangedNotification]; } - (id)createObject { unsigned count; id newObj = nil; if ((count = [[self sources] count]) == 0) newObj = [[super createObject] retain]; else if (count == 1) newObj = [[[[self sources] objectAtIndex:0] createObject] retain]; else { NSEnumerator *e; EODataSource *ds; e = [[self sources] objectEnumerator]; while ((ds = [e nextObject]) != nil) { id obj; if ((obj = [ds createObject])) { newObj = [obj retain]; break; } } /* all datasources failed to create .. */ if (newObj == nil) newObj = [[super createObject] retain]; } [self postDataSourceChangedNotification]; return [newObj autorelease]; } - (void)updateObject:(id)_obj { unsigned count; if ((count = [[self sources] count]) == 0) [super updateObject:_obj]; else if (count == 1) [[[self sources] objectAtIndex:0] updateObject:_obj]; else { NSEnumerator *e; EODataSource *ds; e = [[self sources] objectEnumerator]; while ((ds = [e nextObject])) { BOOL didFail = NO; NS_DURING [ds updateObject:_obj]; NS_HANDLER didFail = YES; NS_ENDHANDLER; if (!didFail) return; } /* all datasources failed to update .. */ [super updateObject:_obj]; } [self postDataSourceChangedNotification]; } - (EOClassDescription *)classDescriptionForObjects { unsigned count; NSEnumerator *e; EODataSource *ds; if ((count = [[self sources] count]) == 0) return [super classDescriptionForObjects]; if (count == 1) return [[[self sources] objectAtIndex:0] classDescriptionForObjects]; e = [[self sources] objectEnumerator]; while ((ds = [e nextObject]) != nil) { EOClassDescription *cd; if ((cd = [ds classDescriptionForObjects]) != nil) return cd; } /* all datasources failed to create .. */ return [super classDescriptionForObjects]; } @end /* EOCompoundDataSource */ SOPE/sope-core/NGExtensions/EOExt.subproj/README.txt0000644000000000000000000000540715004363604020756 0ustar rootrootExtensions for EOControl ======================== This subproject contains categories and additional classes to enhance functionality provided by EOControl. General additions: a) plist init methods, like -initWithPropertyList:, -initWithPropertyList:owner:, -initWithString:, -initWithDictionary:, etc DataSources =========== General Additions ***************** NGExtensions adds the following to datasources: a) standardized -setFetchSpecification:/-fetchSpecification b) -updateObject: for triggering updates in 'raw' datasources c) -postDataSourceChanged, to notify the system of changed datasource fetch specifications EOCacheDataSource ***************** A "regular" EODataSource in SOPE is not supposed to cache the results it fetches, it should just perform the raw fetch and then tidy up. To provide caching, you can wrap an arbitary datasource in an EOCacheDataSource which will manage the cache, perform on-demand loads etc. To keep the cache consistent, in SOPE a EODataSource is supposed to call -postDataSourceChanged when its fetch-specification changes in a way which would lead to different fetch results. (Notably an EODatabaseDataSource in EOF2 often has implicit caching in the EOObjectStore/EOEditingContext, the above applies more to SOPE and OGo datasources like the NGLdapDataSource, NGImap4FolderDataSource, EOAdaptorDataSource etc). EOCompoundDataSource ******************** As the name suggests this datasource joins the results of other datasources into one. In the context of create/insert/delete/update operations, the datasource tries each of the child datasources in sequence until one of them succeeds in the delete and otherwise calls the super method. Finally this datasource has own sort-orderings and an own auxiliaryQualifier. EOFilterDataSource ****************** This datasource is somewhat similar to EOCompoundDataSource but intended for subclassing and has just one source datasources. It provides own sort-orderings, groupings and an own auxiliaryQualifier. It can be used as-is to add grouping capabilities to datasources. EOKeyMapDataSource ****************** TODO: document - EOMappedObject - EOKeyMapDataSourceEnumerator Grouping ======== TODO document. - Groupings on an EODataSource still return an array, but one sorted by the 'grouping keys'. Remember that the grouping does *not* need to be a plain KVC key but can be arbitary. - You can add grouping facilities to arbitary datasources using EOFilterDataSource. Convenience methods ******************* NSArray - (NSArray *)arrayGroupedBy:(EOGrouping *)_grouping; EOFetchSpecification: - setGroupings:(NSArray *)_groupings; // sets 'EOGroupingHint' - (NSArray *)groupings; Classes ******* EOGrouping EOGroupingSet EOKeyGrouping EOQualifierGrouping SOPE/sope-core/NGExtensions/EOExt.subproj/EOGrouping.m0000644000000000000000000000462715004363604021457 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOGrouping.h" #include "common.h" @implementation EOGrouping - (id)initWithDefaultName:(NSString *)_defaultName { if ((self = [super init])) { self->defaultName = [_defaultName copy]; } return self; } - (id)init { return [self initWithDefaultName:nil]; } - (void)dealloc { [self->defaultName release]; [self->sortOrderings release]; [super dealloc]; } /* accessors */ - (void)setDefaultName:(NSString *)_defaultName { ASSIGN(self->defaultName, _defaultName); } - (NSString *)defaultName { return self->defaultName; } - (void)setSortOrderings:(NSArray *)_sortOrderings { ASSIGN(self->sortOrderings, _sortOrderings); } - (NSArray *)sortOrderings { return self->sortOrderings; } /* operations */ - (NSString *)groupNameForObject:(id)_object { [self doesNotRecognizeSelector:_cmd]; // subclass return nil; } - (NSArray *)orderedGroupNames { [self doesNotRecognizeSelector:_cmd]; // subclass return nil; } - (NSString *)description { return @"EOGrouping"; } @end /* EOGrouping */ NSString *EOGroupingHint = @"EOGroupingHint"; @implementation EOFetchSpecification(Groupings) - (void)setGroupings:(NSArray *)_groupings { NSDictionary *lhints; NSMutableDictionary *md; lhints = [self hints]; md = lhints ? [lhints mutableCopy] : [[NSMutableDictionary alloc] init]; if (_groupings) [md setObject:_groupings forKey:EOGroupingHint]; else [md removeObjectForKey:EOGroupingHint]; lhints = [md copy]; [md release]; [self setHints:lhints]; [lhints release]; } - (NSArray *)groupings { return [[self hints] objectForKey:EOGroupingHint]; } @end /* EOFetchSpecification(Groupings) */ SOPE/sope-core/NGExtensions/FileObjectHolder.m0000644000000000000000000001134515004363604020131 0ustar rootroot/* Copyright (C) 2002-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "FileObjectHolder.h" #include "NSRunLoop+FileObjects.h" #import #import #import #include "common.h" @implementation FileObjectHolder - (id)initWithFileObject:(id)_object activities:(int)_activities mode:(NSString *)_mode { if (_object == nil) { [self release]; return nil; } self->fileObject = [_object retain]; self->fd = [_object fileDescriptor]; self->activities = _activities; self->mode = [_mode copy]; self->fileHandle = [[NSFileHandle alloc] initWithFileDescriptor:self->fd closeOnDealloc:NO]; NSAssert(self->fileHandle, @"couldn't create filehandle ..."); [[self notificationCenter] addObserver:self selector:@selector(_dataAvailable:) name:NSFileHandleDataAvailableNotification object:self->fileHandle]; [[self notificationCenter] addObserver:self selector:@selector(_acceptAvailable:) name:NSFileHandleConnectionAcceptedNotification object:self->fileHandle]; return self; } - (void)dealloc { if (self->waitActive) [[self notificationCenter] removeObserver:self]; [self->mode release]; [self->fileHandle release]; [self->fileObject release]; [super dealloc]; } /* accessors */ - (int)fileDescriptor { return self->fd; } - (NSFileHandle *)fileHandle { return self->fileHandle; } - (id)fileObject { return self->fileObject; } - (int)activities { return self->activities; } - (NSString *)mode { return self->mode; } - (NSArray *)modes { return [NSArray arrayWithObject:[self mode]]; } /* notifications */ - (NSNotificationCenter *)notificationCenter { return [NSNotificationCenter defaultCenter]; } - (void)handleException:(NSException *)_exception { NSLog(@"%s: catched: %@", __PRETTY_FUNCTION__, _exception); } - (void)_dataAvailable:(NSNotification *)_notification { if ([_notification object] != self->fileHandle) { NSLog(@"%s: notification object %@ does not match file handle %@", __PRETTY_FUNCTION__, [_notification object], self->fileHandle); return; } if (![self->fileObject isOpen]) { //NSLog(@"file object is closed ..."); return; } NS_DURING { self->waitActive = NO; [self wait]; [[self notificationCenter] postNotificationName:NSFileObjectBecameActiveNotificationName object:self->fileObject]; } NS_HANDLER [self handleException:localException]; NS_ENDHANDLER; } - (void)_acceptAvailable:(NSNotification *)_notification { NSLog(@"accept available ..."); if ([_notification object] != self->fileHandle) { NSLog(@"%s: notification object %@ does not match file handle %@", __PRETTY_FUNCTION__, [_notification object], self->fileHandle); return; } [[self notificationCenter] postNotificationName:NSFileObjectBecameActiveNotificationName object:self->fileObject]; } /* operations */ - (void)wait { if (self->waitActive) return; if (![self->fileObject isOpen]) return; self->waitActive = YES; #if 0 /* use accept for passive fileobjects ?, wait seems to work too ... :-) */ if ([self->fileObject isPassive]) { NSLog(@"add passive %@ ..", self->fileObject); // => this also accepts the connection :-( [self->fileHandle acceptConnectionInBackgroundAndNotifyForModes: [self modes]]; } else #endif [self->fileHandle waitForDataInBackgroundAndNotifyForModes:[self modes]]; } - (void)stopWaiting { } /* equality */ - (BOOL)isEqualToFileObjectHolder:(FileObjectHolder *)_other { if (self->fd != _other->fd) return NO; if (![self->mode isEqualToString:_other->mode]) return NO; if (![self->fileObject isEqual:_other->fileObject]) return NO; return YES; } - (BOOL)isEqual:(id)_other { if (_other == self) return YES; if (_other == nil) return NO; if ([_other class] != [self class]) return NO; return [self isEqualToFileObjectHolder:_other]; } /* description */ @end /* FileObject */ SOPE/sope-core/NGExtensions/NGFileManagerURL.m0000644000000000000000000001076015004363604017747 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGFileManagerURL.h" #include "common.h" @interface NGFileManagerURLHandle : NSURLHandle { id fileManager; NSString *path; BOOL shallCache; NSURLHandleStatus status; NSData *cachedData; NSDictionary *cachedProperties; } @end @implementation NGFileManagerURL - (id)initWithPath:(NSString *)_path fileManager:(id)_fm { static BOOL didRegisterHandleClass = NO; if (!didRegisterHandleClass) { [NSURLHandle registerURLHandleClass:[NGFileManagerURLHandle class]]; didRegisterHandleClass = YES; } self->path = [[_fm standardizePath:_path] copy]; self->fileManager = [_fm retain]; return self; } - (void)dealloc { [self->path release]; [self->fileManager release]; [super dealloc]; } /* accessors */ - (id)fileManager { return self->fileManager; } - (NSString *)fragment { return nil; } - (NSString *)host { return nil; } - (NSString *)path { return self->path; } - (NSString *)scheme { return nil; } - (NSString *)user { return nil; } - (NSString *)password { return nil; } - (NSNumber *)port { return nil; } - (NSString *)query { return nil; } - (BOOL)isFileURL { return NO; } @end /* NGFileManagerURL */ @implementation NGFileManagerURLHandle + (BOOL)canInitWithURL:(NSURL *)_url { return [_url isKindOfClass:[NGFileManagerURL class]] ? YES : NO; } - (id)initWithURL:(NSURL *)_url cached:(BOOL)_flag { if (![[self class] canInitWithURL:_url]) { [self release]; return nil; } self->fileManager = [[(NGFileManagerURL *)_url fileManager] retain]; self->path = [[_url path] copy]; self->shallCache = _flag; self->status = NSURLHandleNotLoaded; return self; } - (void)dealloc { [self->cachedData release]; [self->cachedProperties release]; [self->path release]; [self->fileManager release]; [super dealloc]; } - (NSData *)loadInForeground { [self->cachedProperties release]; self->cachedProperties = nil; [self->cachedData release]; self->cachedData = nil; self->cachedData = [[self->fileManager contentsAtPath:self->path] retain]; self->cachedProperties = [[self->fileManager fileAttributesAtPath:self->path traverseLink:YES] copy]; return self->cachedData; } - (void)loadInBackground { [self loadInBackground]; } - (void)flushCachedData { [self->cachedData release]; self->cachedData = nil; [self->cachedProperties release]; self->cachedProperties = nil; } - (NSData *)resourceData { NSData *data; if (self->cachedData) return [[self->cachedData copy] autorelease]; data = [self loadInForeground]; data = [data copy]; if (!self->shallCache) [self flushCachedData]; return [data autorelease]; } - (NSData *)availableResourceData { return [[self->cachedData copy] autorelease]; } - (NSURLHandleStatus)status { return self->status; } - (NSString *)failureReason { if (self->status != NSURLHandleLoadFailed) return nil; return @"loading of URL failed"; } /* properties */ - (id)propertyForKey:(NSString *)_key { if (self->cachedProperties) return [self->cachedProperties objectForKey:_key]; if ([self loadInForeground]) { id value; value = [self->cachedProperties objectForKey:_key]; value = [value retain]; if (!self->shallCache) [self flushCachedData]; return [value autorelease]; } else { [self flushCachedData]; return nil; } } - (id)propertyForKeyIfAvailable:(NSString *)_key { return [self->cachedProperties objectForKey:_key]; } /* writing */ - (BOOL)writeData:(NSData *)_data { [self flushCachedData]; return NO; } @end /* NGFileManagerURLHandle */ SOPE/sope-core/NGExtensions/NGExtensions-Info.plist0000644000000000000000000000135215004363604021136 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable NGExtensions CFBundleGetInfoString CFBundleIdentifier org.OpenGroupware.SOPE.core.NGExtensions CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType FMWK CFBundleShortVersionString CFBundleSignature ???? CFBundleVersion 4.5 SOPE/sope-core/NGExtensions/Version0000644000000000000000000000016615004363604016156 0ustar rootroot# version SUBMINOR_VERSION:=203 # v4.3.115 requires libFoundation v1.0.59 # v4.2.72 requires libEOControl v4.2.39 SOPE/sope-core/NGExtensions/NGHashMap.m0000644000000000000000000006074115004363604016537 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGHashMap.h" #include "common.h" #if !LIB_FOUNDATION_LIBRARY @interface NSException(SetUI) /* allowed on Jaguar ? */ - (void)setUserInfo:(NSDictionary *)_ui; @end #endif typedef struct _LList { struct _LList *next; struct _LList *last; id object; unsigned int count; } LList; static inline void *initLListElement(id _object, LList* _next) { LList *element = malloc(sizeof(LList)); _object = [_object retain]; element->object = _object; element->next = _next; element->count = 0; return element; } static inline void checkForAddErrorMessage(id _self, id _object, id _key) { NSException *exc; NSDictionary *ui; NSString *r; if (_key == nil) { r = [[NSString alloc] initWithFormat: @"nil key to be added in HashMap with object %@", (_object != nil ? _object : (id)@"")]; ui = [[NSDictionary alloc] initWithObjectsAndKeys: _self, @"map", _key ? _key : (id)@"", @"key", _object ? _object : (id)@"", @"object", nil]; exc = [NSException exceptionWithName:NSInvalidArgumentException reason:r userInfo:ui]; [r release]; r = nil; [ui release]; ui = nil; [exc raise]; } if (_object == nil) { r = [[NSString alloc] initWithFormat: @"nil object to be added in HashMap for key %@", _key ? _key : (id)@""]; ui = [[NSDictionary alloc] initWithObjectsAndKeys: _self, @"map", _key ? _key : (id)@"", @"key", _object ? _object : (id)@"", @"object", nil]; exc = [NSException exceptionWithName:NSInvalidArgumentException reason:r userInfo:ui]; [r release]; r = nil; [ui release]; ui = nil; [exc raise]; } } static inline void checkForRemoveErrorMessage(id _self, id _object, id _key) { NSException *exc; NSDictionary *ui; NSString *r; if (_object != nil && _key != nil) return; r = [[NSString alloc] initWithFormat: @"nil object to be removed in HashMap for key %@", _key ? _key : (id)@""]; ui = [[NSDictionary alloc] initWithObjectsAndKeys: _self, @"map", _key ? _key : (id)@"", @"key", _object ? _object : (id)@"", @"object", nil]; exc = [NSException exceptionWithName:NSInvalidArgumentException reason:r userInfo:ui]; [ui release]; ui = nil; [r release]; r = nil; [exc raise]; } static inline void raiseInvalidArgumentExceptionForNilKey(id _self) { NSException *exc = nil; exc = [NSException exceptionWithName:NSInvalidArgumentException reason:@"key is nil" userInfo:[NSDictionary dictionaryWithObject:_self forKey:@"map"]]; [exc raise]; } @interface _NGHashMapObjectEnumerator : NSEnumerator { NSEnumerator *keys; NSEnumerator *elements; NGHashMap *hashMap; } - (id)initWithHashMap:(NGHashMap *)_hashMap; - (id)nextObject; @end @interface _NGHashMapObjectForKeyEnumerator : NSEnumerator { LList *element; NGHashMap *map; } - (id)initWithHashMap:(NGHashMap *)_hashMap andKey:(id)_key; - (id)nextObject; @end @interface _NGHashMapKeyEnumerator : NSEnumerator { NSMapEnumerator enumerator; NGHashMap *map; } - (id)initWithHashMap:(NGHashMap *)_hashMap; - (id)nextObject; @end // ************************* NGHashMap ************************* @interface NGHashMap(private) - (LList *)__structForKey:(id)_key; - (NSMapEnumerator)__keyEnumerator; - (void)__removeAllObjectsForKey:(id)_key; - (void)__removeAllObjects; @end static Class NSArrayClass = Nil; @implementation NGHashMap + (void)initialize { NSArrayClass = [NSArray class]; } /* final methods */ static inline void _removeAllObjectsInList(LList *list) { while (list) { register LList *element; [list->object release]; element = list; list = list->next; if (element) free(element); } } static inline LList *__structForKey(NGHashMap *self, id _key) { if (_key == nil) raiseInvalidArgumentExceptionForNilKey(self); #if DEBUG NSCAssert(self->table, @"missing table .."); #endif return (LList *)NSMapGet(self->table, (void *)_key); } static inline unsigned __countObjectsForKey(NGHashMap *self, id _key) { LList *list = NULL; return (list = __structForKey(self, _key)) ? list->count : 0; } /* methods */ + (id)hashMap { return [[[self alloc] init] autorelease]; } + (id)hashMapWithHashMap:(NGHashMap *)_hashMap { return [[[self alloc] initWithHashMap:_hashMap] autorelease]; } + (id)hashMapWithObjects:(NSArray *)_objects forKey:(id)_key { return [[[self alloc] initWithObjects:_objects forKey:_key] autorelease]; } + (id)hashMapWithDictionary:(NSDictionary *)_dict { return [[[self alloc] initWithDictionary:_dict] autorelease]; } - (id)init { return [self initWithCapacity:0]; } - (id)initWithCapacity:(NSUInteger)_size { if ((self = [super init])) { self->table = NSCreateMapTableWithZone(NSObjectMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, _size * 4/3 ,NULL); NSAssert1(self->table, @"missing table for hashmap of size %d ..", _size); } return self; } - (id)initWithHashMap:(NGHashMap *)_hashMap { NSEnumerator *keys = nil; id key = nil; LList *list = NULL; LList *newList = NULL; LList *oldList = NULL; if ((self = [self initWithCapacity:[_hashMap count]])) { keys = [_hashMap keyEnumerator]; while ((key = [keys nextObject])) { list = [_hashMap __structForKey:key]; newList = initLListElement(list->object,NULL); newList->count = list->count; NSMapInsert(self->table,key,newList); while (list->next) { oldList = newList; list = list->next; newList = initLListElement(list->object,NULL); oldList->next = newList; } } } return self; } - (id)initWithObjects:(NSArray *)_objects forKey:(id)_key { LList *root = NULL; LList *element = NULL; LList *pred = NULL; int count = 0; int i = 0; if (( self = [self initWithCapacity:1])) { count = [_objects count]; if (count == 0) return self; root = initLListElement([_objects objectAtIndex:0], NULL); pred = root; for (i = 1; i < count; i++) { element = initLListElement([_objects objectAtIndex:i], NULL); pred->next = element; pred = element; } root->count = i; NSMapInsert(self->table,_key, root); } NSAssert(self->table, @"missing table for hashmap .."); return self; } - (id)initWithDictionary:(NSDictionary *)_dictionary { if (![self isKindOfClass:[NGMutableHashMap class]]) { self = [self autorelease]; self = [[NGMutableHashMap allocWithZone:[self zone]] initWithCapacity:[_dictionary count]]; } else self = [self initWithCapacity:[_dictionary count]]; if (self) { NSEnumerator *keys; id key; keys = [_dictionary keyEnumerator]; while ((key = [keys nextObject])) { [(NGMutableHashMap *)self setObject:[_dictionary objectForKey:key] forKey:key]; } } NSAssert(self->table, @"missing table for hashmap .."); return self; } - (void)dealloc { if (self->table) { NSMapEnumerator mapenum; id key = nil, value = nil; mapenum = [self __keyEnumerator]; while (NSNextMapEnumeratorPair(&mapenum, (void **)&key, (void **)&value)) _removeAllObjectsInList((LList *)value); NSFreeMapTable(self->table); self->table = NULL; } [super dealloc]; } /* removing */ - (void)__removeAllObjectsForKey:(id)_key { _removeAllObjectsInList(__structForKey(self, _key)); NSMapRemove(self->table, _key); } - (void)__removeAllObjects { NSEnumerator *keys = nil; id key = nil; keys = [self keyEnumerator]; while ((key = [keys nextObject])) _removeAllObjectsInList(__structForKey(self, key)); NSResetMapTable(self->table); } /* equality */ - (NSUInteger)hash { return [self count]; } - (BOOL)isEqual:(id)anObject { if (self == anObject) return YES; if (![anObject isKindOfClass:[NGHashMap class]]) return NO; return [self isEqualToHashMap:anObject]; } - (BOOL)isEqualToHashMap:(NGHashMap *)_other { NSEnumerator *keyEnumerator = nil; id key = nil; LList *selfList = NULL; LList *otherList = NULL; if (_other == self) return YES; if ([self count] != [_other count]) return NO; keyEnumerator = [self keyEnumerator]; while ((key = [keyEnumerator nextObject])) { if (__countObjectsForKey(self, key) != [_other countObjectsForKey:key]) return NO; selfList = __structForKey(self, key); otherList = [_other __structForKey:key]; while (selfList) { if (![selfList->object isEqual:otherList->object]) return NO; selfList = selfList->next; otherList = otherList->next; } } return YES; } - (id)objectForKey:(id)_key { LList *list; if (!(list = __structForKey(self, _key))) return nil; if (list->next) { NSLog(@"WARNING[%s] more than one element for key %@ objects: %@, " @"return first object", __PRETTY_FUNCTION__, _key, [self objectsForKey:_key]); } return list->object; } - (NSArray *)objectsForKey:(id)_key { NSArray *array = nil; NSEnumerator *objectEnum = nil; id object = nil; id *objects = NULL; unsigned int i = 0; if ((objectEnum = [self objectEnumeratorForKey:_key]) == nil) return nil; objects = calloc(__countObjectsForKey(self, _key) + 1, sizeof(id)); for (i = 0; (object = [objectEnum nextObject]); i++) objects[i] = object; array = [NSArrayClass arrayWithObjects:objects count:i]; if (objects) free(objects); return array; } - (id)objectAtIndex:(NSUInteger)_index forKey:(id)_key { LList *list = NULL; if (!(list = __structForKey(self, _key))) return nil; if ((_index < list->count) == 0) { [NSException raise:NSRangeException format:@"index %"PRIuPTR" out of range for key %@ of length %d", _index, _key, list->count]; return nil; } while (_index--) list = list->next; return list->object; } - (NSArray *)allKeys { NSArray *array = nil; NSEnumerator *keys; id *objects; id object; int i; objects = calloc([self count] + 1, sizeof(id)); keys = [self keyEnumerator]; for(i = 0; (object = [keys nextObject]); i++) objects[i] = object; array = [[NSArrayClass alloc] initWithObjects:objects count:i]; if (objects) free (objects); return [array autorelease]; } - (NSArray *)allObjects { NSEnumerator *keys = nil; id object = nil; NSMutableArray *mArray = nil; NSArray *result = nil; mArray = [[NSMutableArray alloc] init]; keys = [self keyEnumerator]; while ((object = [keys nextObject])) [mArray addObjectsFromArray:[self objectsForKey:object]]; result = [mArray copy]; [mArray release]; mArray = nil; return [result autorelease]; } - (NSUInteger)countObjectsForKey:(id)_key { return __countObjectsForKey(self, _key); } - (NSEnumerator *)keyEnumerator { return [[[_NGHashMapKeyEnumerator alloc] initWithHashMap:self] autorelease]; } - (NSEnumerator *)objectEnumerator { return [[[_NGHashMapObjectEnumerator alloc] initWithHashMap:self] autorelease]; } - (NSEnumerator *)objectEnumeratorForKey:(id)_key { if (_key == nil) raiseInvalidArgumentExceptionForNilKey(self); return [[[_NGHashMapObjectForKeyEnumerator alloc] initWithHashMap:self andKey:_key] autorelease]; } - (NSDictionary *)asDictionaryWithArraysForValues:(BOOL)arraysOnly { NSDictionary *dict = nil; NSEnumerator *keys; id key; id *dicObj; id *dicKeys; int cntKey; keys = [self keyEnumerator]; cntKey = [self count]; dicObj = calloc(cntKey + 1, sizeof(id)); dicKeys = calloc(cntKey + 1, sizeof(id)); for (cntKey = 0; (key = [keys nextObject]); ) { id object = nil; LList *list; if ((list = __structForKey(self, key)) == NULL) { NSLog(@"ERROR(%s): did not find key '%@' in hashmap: %@", __PRETTY_FUNCTION__, key, self); continue; } if (list->next) { id *objects = NULL; int cntObj = 0; objects = calloc(list->count + 1, sizeof(id)); { cntObj = 0; while (list) { objects[cntObj++] = list->object; list = list->next; } object = [NSArray arrayWithObjects:objects count:cntObj]; } if (objects) free(objects); objects = NULL; } else { if (arraysOnly) { object = [NSArray arrayWithObject:list->object ]; } else { object = list->object; } } dicObj[cntKey] = object; dicKeys[cntKey++] = key; } dict = [[NSDictionary alloc] initWithObjects:dicObj forKeys:dicKeys count:cntKey]; if (dicObj) free(dicObj); dicObj = NULL; if (dicKeys) free(dicKeys); dicKeys = NULL; return [dict autorelease]; } - (NSDictionary *)asDictionary { return [ self asDictionaryWithArraysForValues: NO ]; } - (NSDictionary *)asDictionaryWithArraysForValues { return [ self asDictionaryWithArraysForValues: YES ]; } - (id)propertyList { NSDictionary *dict = nil; NSEnumerator *keys = nil; id key; id *dicObj = NULL; id *dicKeys = NULL; int cntKey = 0; keys = [self keyEnumerator]; cntKey = [self count]; dicObj = calloc(cntKey + 1, sizeof(id)); dicKeys = calloc(cntKey + 1, sizeof(id)); for (cntKey = 0; (key = [keys nextObject]); ) { id object = nil; LList *list = NULL; list = __structForKey(self, key); if (list->next) { id *objects = NULL; int cntObj = 0; objects = calloc(list->count + 1, sizeof(id)); { cntObj = 0; while (list) { objects[cntObj++] = list->object; list = list->next; } object = [NSArrayClass arrayWithObjects:objects count:cntObj]; } if (objects) free(objects); objects = NULL; } else object = list->object; dicObj[cntKey] = object; dicKeys[cntKey] = key; cntKey++; } dict = [[[NSDictionary alloc] initWithObjects:dicObj forKeys:dicKeys count:cntKey] autorelease]; if (dicObj) free(dicObj); dicObj = NULL; if (dicKeys) free(dicKeys); dicKeys = NULL; return dict; } /* description */ - (NSString *)description { return [[self propertyList] description]; } - (NSUInteger)count { return self->table ? NSCountMapTable(table) : 0; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { return [[NGHashMap allocWithZone:_zone] initWithHashMap:self]; } - (id)mutableCopyWithZone:(NSZone *)_zone { return [[NGMutableHashMap allocWithZone:_zone] initWithHashMap:self]; } /* */ - (NSMapEnumerator)__keyEnumerator { return NSEnumerateMapTable(table); } - (LList *)__structForKey:(id)_key { return __structForKey(self, _key); } /* NSCoding */ - (void)encodeWithCoder:(NSCoder *)_encoder { unsigned keyCount = [self count]; NSMapEnumerator mapenum = [self __keyEnumerator]; id key = nil; LList *value = NULL; [_encoder encodeValueOfObjCType:@encode(unsigned) at:&keyCount]; while (NSNextMapEnumeratorPair(&mapenum, (void **)&key, (void **)&value)) { unsigned valueCount = value ? value->count : 0; unsigned outCount = 0; // debugging [_encoder encodeObject:key]; [_encoder encodeValueOfObjCType:@encode(unsigned) at:&valueCount]; while (value) { [_encoder encodeObject:value->object]; value = value->next; outCount++; } NSAssert(valueCount == outCount, @"didn't encode enough value objects"); } } - (id)initWithCoder:(NSCoder *)_decoder { NGMutableHashMap *map = [[NGMutableHashMap alloc] init]; unsigned keyCount; unsigned cnt; [_decoder decodeValueOfObjCType:@encode(unsigned) at:&keyCount]; for (cnt = 0; cnt < keyCount; cnt++) { unsigned valueCount = 0, cnt2 = 0; id key = nil; key = [_decoder decodeObject]; [_decoder decodeValueOfObjCType:@encode(unsigned) at:&valueCount]; for (cnt2 = 0; cnt2 < valueCount; cnt2++) { id value = [_decoder decodeObject]; [map addObject:value forKey:key]; } } self = [self initWithHashMap:map]; [map release]; map = nil; return self; } @end /* NGHashMap */ // ************************* NGMutableHashMap ****************** @implementation NGMutableHashMap + (id)hashMapWithCapacity:(NSUInteger)_numItems { return [[[self alloc] initWithCapacity:_numItems] autorelease]; } - (id)init { return [self initWithCapacity:0]; } /* inserting objects */ - (void)insertObject:(id)_object atIndex:(NSUInteger)_index forKey:(id)_key { [self insertObjects:&_object count:1 atIndex:_index forKey:_key]; } - (void)insertObjects:(NSArray *)_objects atIndex:(NSUInteger)_index forKey:(id)_key { id *objects = NULL; int i = 0; int cntI = 0; cntI = [_objects count]; objects = calloc(cntI + 1, sizeof(id)); for (i = 0 ; i < cntI; i++) objects[i] = [_objects objectAtIndex:i]; [self insertObjects:objects count:cntI atIndex:_index forKey:_key]; if (objects) free(objects); } - (void)insertObjects:(id*)_objects count:(NSUInteger)_count atIndex:(NSUInteger)_index forKey:(id)_key { id object = nil; LList *root = NULL; LList *element = NULL; unsigned i = 0; if (_count == 0) return; checkForAddErrorMessage(self, _objects[0],_key); if ((root = [self __structForKey:_key]) == NULL) { if (_index > 0) { [NSException raise:NSRangeException format:@"index %"PRIuPTR" out of range in map 0x%p", _index, self]; return; } root = initLListElement(_objects[0], NULL); root->count = _count; NSMapInsert(self->table, _key, root); } else { if (!(_index < root->count)) { [NSException raise:NSRangeException format:@"index %"PRIuPTR" out of range in map 0x%p length %d", _index, self, root->count]; return; } root->count += _count; if (_index == 0) { element = initLListElement(_objects[0],NULL); object = element->object; element->next = root->next; element->object = root->object; root->object = object; root->next = element; } else { while (--_index) root = root->next; element = initLListElement(_objects[0], NULL); element->next = root->next; root->next = element; root = root->next; } } for (i = 1; i < _count; i++) { checkForAddErrorMessage(self, _objects[i], _key); element = initLListElement(_objects[i], NULL); element->next = root->next; root->next = element; root = element; } } /* adding objects */ - (void)addObjects:(id*)_objects count:(NSUInteger)_count forKey:(id)_key { LList *root = NULL; LList *element = NULL; unsigned i = 0; if (_count == 0) return; checkForAddErrorMessage(self, _objects[0],_key); if ((root = [self __structForKey:_key]) == NULL) { root = initLListElement(_objects[0], NULL); root->count = _count; root->last = root; NSMapInsert(self->table, _key, root); } else { root->count += _count; element = initLListElement(_objects[0], NULL); root->last->next = element; root->last = element; } for (i = 1; i < _count; i++) { checkForAddErrorMessage(self, _objects[i], _key); element = initLListElement(_objects[i], NULL); root->last->next = element; root->last = element; } } - (void)addObject:(id)_object forKey:(id)_key { checkForAddErrorMessage(self, _object,_key); [self addObjects:&_object count:1 forKey:_key]; } - (void)addObjects:(NSArray *)_objects forKey:(id)_key { id *objects = NULL; int i = 0; int cntI = 0; cntI = [_objects count]; objects = malloc((cntI + 1) * sizeof(id)); for (i = 0 ; i < cntI; i++) objects[i] = [_objects objectAtIndex:i]; [self addObjects:objects count:cntI forKey:_key]; free(objects); } /* setting objects */ - (void)setObject:(id)_object forKey:(id)_key { checkForAddErrorMessage(self, _object, _key); [self removeAllObjectsForKey:_key]; [self addObjects:&_object count:1 forKey:_key]; } - (void)setObjects:(NSArray *)_objects forKey:(id)_key { checkForAddErrorMessage(self, _objects, _key); [self removeAllObjectsForKey:_key]; [self addObjects:_objects forKey:_key]; } /* removing objects */ - (void)removeAllObjects { [self __removeAllObjects]; } - (void)removeAllObjectsForKey:(id)_key { [self __removeAllObjectsForKey:_key]; } - (void)removeAllObjects:(id)_object forKey:(id)_key { LList *list = NULL; LList *root = NULL; LList *oldList = NULL; unsigned int cnt = 0; checkForRemoveErrorMessage(self, _object, _key); if (!(root = [self __structForKey:_key])) return; while ([root->object isEqual:_object]) { [root->object release]; if (root->next == NULL) { if (root) free(root); root = NULL; NSMapRemove(self->table,_key); break; } else { list = root->next; root->next = list->next; root->object = list->object; root->count--; if (list) free(list); list = NULL; } } if (root) { list = root; while (list->next) { oldList = list; list = list->next; if ([list->object isEqual:_object]) { cnt++; oldList->next = list->next; if (list) free(list); list = oldList; } } root->count -= cnt; } } - (void)removeAllObjectsForKeys:(NSArray *)_keyArray { register int index = 0; for (index = [_keyArray count]; index > 0;) [self removeAllObjectsForKey:[_keyArray objectAtIndex:--index]]; } @end /* NGMutableHashMap */ // ************************* Enumerators ****************** @implementation _NGHashMapKeyEnumerator - (id)initWithHashMap:(NGHashMap *)_hashMap { self->map = [_hashMap retain]; self->enumerator = [_hashMap __keyEnumerator]; return self; } - (void)dealloc { [self->map release]; [super dealloc]; } - (id)nextObject { id key, value; return NSNextMapEnumeratorPair(&self->enumerator,(void**)&key, (void**)&value) ? key : nil; } @end /* _NGHashMapKeyEnumerator */ @implementation _NGHashMapObjectEnumerator - (id)initWithHashMap:(NGHashMap *)_hashMap { self->keys = [[_hashMap keyEnumerator] retain]; self->hashMap = [_hashMap retain]; self->elements = nil; return self; } - (void)dealloc { [self->keys release]; [self->hashMap release]; [self->elements release]; [super dealloc]; } - (id)nextObject { id object; id key; if ((object = [self->elements nextObject])) return object; if ((key = [self->keys nextObject])) { ASSIGN(self->elements, [self->hashMap objectEnumeratorForKey:key]); object = [self->elements nextObject]; } return object; } @end /* _NGHashMapObjectEnumerator */ @implementation _NGHashMapObjectForKeyEnumerator - (id)initWithHashMap:(NGHashMap *)_hashMap andKey:(id)_key { element = [_hashMap __structForKey:_key]; self->map = [_hashMap retain]; return self; } - (void)dealloc { [self->map release]; [super dealloc]; } - (id)nextObject { id object; if (element == NULL) return nil; object = element->object; element = element->next; return object; } @end /* _NGHashMapObjectForKeyEnumerator */ SOPE/sope-core/NGExtensions/NGStack.m0000644000000000000000000001574215004363604016264 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #include "NGStack.h" #include "NGMemoryAllocation.h" @interface _NGConcreteStackEnumerator : NSEnumerator { NGStack *stack; // for retain id *trace; unsigned toGo; BOOL downWard; // top=>down } - (id)initWithStack:(NGStack *)_stack trace:(id *)_ptr count:(int)_size topDown:(BOOL)_downWard; - (id)nextObject; @end @implementation NGStack + (id)stackWithCapacity:(NSUInteger)_capacity { return [[[self alloc] initWithCapacity:_capacity] autorelease]; } + (id)stack { return [[[self alloc] init] autorelease]; } + (id)stackWithArray:(NSArray *)_array { return [[[self alloc] initWithArray:_array] autorelease]; } - (id)init { return [self initWithCapacity:256]; } - (id)initWithCapacity:(NSUInteger)_capacity { if ((self = [super init])) { stackPointer = 0; capacity = (_capacity > 0) ? _capacity : 16; stack = NGMalloc(sizeof(id) * capacity); } return self; } - (id)initWithArray:(NSArray *)_array { register unsigned int count = [_array count]; if ((self = [self initWithCapacity:(count + 1)])) { unsigned cnt; for (cnt = 0; cnt < count; cnt++) [self push:[_array objectAtIndex:cnt]]; } return self; } - (void)dealloc { if (self->stack) { [self clear]; NGFree(self->stack); } [super dealloc]; } /* sizing */ - (void)_increaseStack { if (capacity > 256) capacity += 256; else capacity *= 2; stack = NGRealloc(stack, sizeof(id) * capacity); } /* state */ - (NSUInteger)capacity { return capacity; } - (NSUInteger)stackPointer { return stackPointer; } - (NSUInteger)count { return stackPointer; } - (BOOL)isEmpty { return (stackPointer == 0); } /* operations */ - (void)push:(id)_obj { stackPointer++; if (stackPointer >= capacity) [self _increaseStack]; stack[stackPointer] = [_obj retain]; } - (id)pop { id obj = stack[stackPointer]; if (stackPointer <= 0) { [[[NGStackException alloc] initWithName:@"StackException" reason:@"tried to pop an object from an empty stack !" userInfo:nil] raise]; } stack[stackPointer] = nil; stackPointer--; return [obj autorelease]; } - (void)clear { unsigned cnt; for (cnt = 1; cnt <= stackPointer; cnt++) { #if !LIB_FOUNDATION_BOEHM_GC [stack[cnt] release]; #endif stack[cnt] = nil; } stackPointer = 0; } /* elements */ - (id)elementAtTop { return (stackPointer == 0) ? nil : stack[stackPointer]; } - (id)elementAtBottom { return (stackPointer == 0) ? nil : stack[1]; } - (NSEnumerator *)topDownEnumerator { if (stackPointer == 0) return nil; return [[[_NGConcreteStackEnumerator alloc] initWithStack:self trace:&(stack[stackPointer]) count:stackPointer topDown:YES] autorelease]; } - (NSEnumerator *)bottomUpEnumerator { if (stackPointer == 0) return nil; return [[[_NGConcreteStackEnumerator alloc] initWithStack:self trace:&(stack[1]) count:stackPointer topDown:NO] autorelease]; } /* NSCoding */ - (Class)classForCoder { return [NGStack class]; } - (void)encodeWithCoder:(NSCoder *)_encoder { unsigned cnt; [_encoder encodeValueOfObjCType:@encode(NSUInteger) at:&capacity]; [_encoder encodeValueOfObjCType:@encode(NSUInteger) at:&stackPointer]; for (cnt = 1; cnt <= stackPointer; cnt++) { id obj = stack[cnt]; [_encoder encodeObject:obj]; } } - (id)initWithCoder:(NSCoder *)_decoder { int tmpCapacity; int tmpStackPointer; [_decoder decodeValueOfObjCType:@encode(NSUInteger) at:&tmpCapacity]; [_decoder decodeValueOfObjCType:@encode(NSUInteger) at:&tmpStackPointer]; self = [self initWithCapacity:tmpCapacity]; { register int cnt; for (cnt = 1; cnt <= tmpStackPointer; cnt++) { id obj = [_decoder decodeObject]; stack[cnt] = [obj retain]; } stackPointer = tmpStackPointer; } return self; } /* copying */ - (id)copyWithZone:(NSZone *)_zone { register NGStack *newStack = nil; register unsigned cnt; newStack = [[NGStack allocWithZone:(_zone ? _zone : NSDefaultMallocZone())] initWithCapacity:[self stackPointer]]; for (cnt = 1; cnt <= stackPointer; cnt++) [newStack push:stack[cnt]]; return newStack; } /* description */ - (NSString *)description { return [NSString stringWithFormat: @"<%@[0x%p] capacity=%"PRIuPTR" SP=%"PRIuPTR" count=%"PRIuPTR" content=%s>", NSStringFromClass([self class]), self, [self capacity], [self stackPointer], [self count], [[[self toArray] description] cString]]; } - (NSArray *)toArray { register NSMutableArray *array = nil; register unsigned cnt; array = [[NSMutableArray alloc] initWithCapacity:stackPointer]; for (cnt = 1; cnt <= stackPointer; cnt++) [array addObject:stack[cnt]]; return [array autorelease]; } @end /* NGStack */ @implementation _NGConcreteStackEnumerator - (id)initWithStack:(NGStack *)_stack trace:(id *)_ptr count:(int)_size topDown:(BOOL)_downWard { stack = [_stack retain]; trace = _ptr; toGo = _size; downWard = _downWard; return self; } - (void)dealloc { [self->stack release]; trace = NULL; [super dealloc]; } - (id)nextObject { id result = nil; if (toGo == 0) return nil; toGo--; result = *trace; if (downWard) trace--; // top=>bottom (downward) else trace++; // bottom=>top (upward) return result; } @end /* NGStack */ @implementation NGStackException @end /* NGStackException */ @implementation NSMutableArray(StackImp) /* state */ - (NSUInteger)stackPointer { return ([self count] - 1); } - (BOOL)isEmpty { return ([self count] == 0) ? YES : NO; } /* operations */ - (void)push:(id)_obj { [self addObject:_obj]; } - (id)pop { NSUInteger lastIdx = ([self count] - 1); id element = [self objectAtIndex:lastIdx]; [self removeObjectAtIndex:lastIdx]; return element; } - (void)clear { [self removeAllObjects]; } /* elements */ - (id)elementAtTop { return [self lastObject]; } - (NSEnumerator *)topDownEnumerator { return [self reverseObjectEnumerator]; } - (NSEnumerator *)bottomUpEnumerator { return [self objectEnumerator]; } @end /* NSMutableArray(NGStack) */ void __link_NGExtensions_NGStack() { __link_NGExtensions_NGStack(); } SOPE/sope-core/NGExtensions/NGFileFolderInfoDataSource.m0000644000000000000000000001004515004363604022010 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #import #import #import #include "common.h" NGExtensions_DECLARE NSString *NSFileName = @"NSFileName"; NGExtensions_DECLARE NSString *NSFilePath = @"NSFilePath"; NGExtensions_DECLARE NSString *NSParentPath = @"NSParentPath"; NGExtensions_DECLARE NSString *NSTraverseLinks = @"NSTraverseLinks"; @implementation NGFileFolderInfoDataSource - (id)initWithFolderPath:(NSString *)_path { if ((self = [self init])) { self->folderPath = [_path copy]; } return self; } - (void)dealloc { [self->fspec release]; [self->folderPath release]; [super dealloc]; } /* accessors */ - (void)setFetchSpecification:(EOFetchSpecification *)_fspec { ASSIGN(self->fspec, _fspec); } - (EOFetchSpecification *)fetchSpecification { return self->fspec; } /* operations */ - (NSArray *)_attributesForPaths:(NSEnumerator *)_paths filterUsingQualifier:(EOQualifier *)_q fileManager:(NSFileManager *)_fm { NSMutableArray *ma; NSMutableDictionary *workArea; NSArray *result; NSString *path; BOOL tlinks; ma = [NSMutableArray arrayWithCapacity:256]; workArea = [NSMutableDictionary dictionaryWithCapacity:32]; tlinks = [[[self->fspec hints] objectForKey:@"NSTraverseLinks"] boolValue]; while ((path = [_paths nextObject])) { NSDictionary *record; NSString *fullPath; fullPath = [self->folderPath stringByAppendingPathComponent:path]; [workArea setDictionary: [_fm fileAttributesAtPath:fullPath traverseLink:tlinks]]; [workArea setObject:path forKey:@"NSFileName"]; [workArea setObject:fullPath forKey:@"NSFilePath"]; [workArea setObject:self->folderPath forKey:@"NSParentPath"]; record = [[workArea copy] autorelease]; if (_q) { if (![(id)_q evaluateWithObject:record]) /* filter out */ continue; } /* add to result set */ [ma addObject:record]; } result = [[ma copy] autorelease]; return result; } - (NSArray *)_fetchObjectsFromFileManager:(NSFileManager *)_fm { NSAutoreleasePool *pool; BOOL isDir; NSArray *array; NSArray *sortOrderings; if (![_fm fileExistsAtPath:self->folderPath isDirectory:&isDir]) /* path does not exist */ return nil; if (!isDir) /* path is not a directory */ return nil; pool = [[NSAutoreleasePool alloc] init]; array = [_fm directoryContentsAtPath:self->folderPath]; if ([array count] == 0) { /* no directory contents */ array = [array retain]; [pool release]; return [array autorelease]; } array = [self _attributesForPaths:[array objectEnumerator] filterUsingQualifier:[self->fspec qualifier] fileManager:_fm]; if ((sortOrderings = [self->fspec sortOrderings])) /* sort set */ array = [array sortedArrayUsingKeyOrderArray:sortOrderings]; array = [array retain]; [pool release]; return [array autorelease]; } - (NSArray *)fetchObjects { NSFileManager *fm; fm = [NSFileManager defaultManager]; return [self _fetchObjectsFromFileManager:fm]; } @end /* NGFileInfoDataSource */ SOPE/sope-core/NGExtensions/COPYRIGHT0000644000000000000000000000010615004363604016073 0ustar rootrootCopyright (C) 2000-2005 SKYRIX Software AG Contact: info@skyrix.com SOPE/sope-core/NGExtensions/NGQuotedPrintableCoding.m0000644000000000000000000002651315004363604021443 0ustar rootroot/* Copyright (C) 2000-2008 SKYRIX Software AG Copyright (C) 2006-2008 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGQuotedPrintableCoding.h" #include "common.h" #include "NGMemoryAllocation.h" @implementation NSString(QuotedPrintableCoding) - (NSString *)stringByDecodingQuotedPrintable { NSData *data; data = ([self length] > 0) ? [self dataUsingEncoding:NSASCIIStringEncoding] : [NSData data]; data = [data dataByDecodingQuotedPrintable]; // TODO: should we default to some specific charset instead? (either // Latin1 or UTF-8 // or the charset of the receiver? return [NSString stringWithCString:[data bytes] length:[data length]]; } - (NSString *)stringByEncodingQuotedPrintable { NSData *data; // TBD: which encoding to use? data = ([self length] > 0) ? [self dataUsingEncoding:[NSString defaultCStringEncoding]] : [NSData data]; data = [data dataByEncodingQuotedPrintable]; return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease]; } @end /* NSString(QuotedPrintableCoding) */ @implementation NSData(QuotedPrintableCoding) - (NSData *)dataByDecodingQuotedPrintable { char *dest; size_t destSize; size_t resSize; destSize = [self length]; dest = malloc(destSize * sizeof(char) + 2); resSize = NGDecodeQuotedPrintableX([self bytes], [self length], dest, destSize, YES); if ((int)resSize == -1) { free(dest); return nil; } return [NSData dataWithBytesNoCopy:dest length:resSize]; } - (NSData *)dataByDecodingQuotedPrintableTransferEncoding { char *dest; size_t destSize; size_t resSize; destSize = [self length]; dest = malloc(destSize * sizeof(char) + 2); resSize = NGDecodeQuotedPrintableX([self bytes], [self length], dest, destSize, NO); if ((int)resSize == -1) { free(dest); return nil; } return [NSData dataWithBytesNoCopy:dest length:resSize]; } - (NSData *)dataByEncodingQuotedPrintable { const char *bytes = [self bytes]; unsigned int length = [self length]; char *des = NULL; unsigned int desLen = 0; // length/64*4 should be plenty for soft newlines desLen = (length + length/64) * 4; des = malloc(sizeof(char) * desLen); desLen = NGEncodeQuotedPrintable(bytes, length, des, desLen); if ((int)desLen == -1) { free(des); return nil; } return [NSData dataWithBytesNoCopy:des length:desLen]; } @end /* NSData(QuotedPrintableCoding) */ // implementation static inline signed char __hexToChar(char c) { if ((c > 47) && (c < 58)) // '0' .. '9' return c - 48; if ((c > 64) && (c < 71)) // 'A' .. 'F' return c - 55; if ((c > 96) && (c < 103)) // 'a' .. 'f' return c - 87; return -1; } int NGDecodeQuotedPrintableX(const char *_src, unsigned _srcLen, char *_dest, unsigned _destLen, BOOL _replaceUnderline) { /* Eg: "Hello=20World" => "Hello World" =XY where XY is a hex encoded byte. In addition '_' is decoded as 0x20 (not as space!, this depends on the charset, see RFC 2047 4.2). */ unsigned cnt = 0; unsigned destCnt = 0; if (_srcLen < _destLen) return -1; for (cnt = 0; ((cnt < _srcLen) && (destCnt < _destLen)); cnt++) { if (_src[cnt] != '=') { _dest[destCnt] = (_replaceUnderline && _src[cnt] == '_') ? 0x20 : _src[cnt]; destCnt++; } else { if ((_srcLen - cnt) > 1) { signed char c1, c2; cnt++; // skip '=' c1 = _src[cnt]; // first hex digit if (c1 == '\r' || c1 == '\n') { if (c1 == '\r' && cnt < _srcLen && _src[cnt + 1] == '\n') // CRLF cnt++; continue; } if (cnt == _srcLen) /* We have reached the end of the _src */ break; c1 = __hexToChar(c1); cnt++; // skip first hex digit c2 = __hexToChar(_src[cnt]); if ((c1 == -1) || (c2 == -1)) { if ((_destLen - destCnt) > 1) { _dest[destCnt] = _src[cnt - 1]; destCnt++; _dest[destCnt] = _src[cnt]; destCnt++; } else break; } else { register unsigned char c = ((c1 << 4) | c2); _dest[destCnt] = c; destCnt++; } } else break; } } if (cnt < _srcLen && ((_srcLen - cnt) > 1 || _src[_srcLen-1] != '=')) return -1; return destCnt; } int NGDecodeQuotedPrintable(const char *_src, unsigned _srcLen, char *_dest, unsigned _destLen) { // should we deprecated that? return NGDecodeQuotedPrintableX(_src, _srcLen, _dest, _destLen, YES); } /* From RFC 2045 Multipurpose Internet Mail Extensions 6.7. Quoted-Printable Content-Transfer-Encoding ... In this encoding, octets are to be represented as determined by the following rules: (1) (General 8bit representation) Any octet, except a CR or LF that is part of a CRLF line break of the canonical (standard) form of the data being encoded, may be represented by an "=" followed by a two digit hexadecimal representation of the octet's value. The digits of the hexadecimal alphabet, for this purpose, are "0123456789ABCDEF". Uppercase letters must be used; lowercase letters are not allowed. Thus, for example, the decimal value 12 (US-ASCII form feed) can be represented by "=0C", and the decimal value 61 (US- ASCII EQUAL SIGN) can be represented by "=3D". This rule must be followed except when the following rules allow an alternative encoding. (2) (Literal representation) Octets with decimal values of 33 through 60 inclusive, and 62 through 126, inclusive, MAY be represented as the US-ASCII characters which correspond to those octets (EXCLAMATION POINT through LESS THAN, and GREATER THAN through TILDE, respectively). (3) (White Space) Octets with values of 9 and 32 MAY be represented as US-ASCII TAB (HT) and SPACE characters, respectively, but MUST NOT be so represented at the end of an encoded line. Any TAB (HT) or SPACE characters on an encoded line MUST thus be followed on that line by a printable character. In particular, an "=" at the end of an encoded line, indicating a soft line break (see rule #5) may follow one or more TAB (HT) or SPACE characters. It follows that an octet with decimal value 9 or 32 appearing at the end of an encoded line must be represented according to Rule #1. This rule is necessary because some MTAs (Message Transport Agents, programs which transport messages from one user to another, or perform a portion of such transfers) are known to pad lines of text with SPACEs, and others are known to remove "white space" characters from the end of a line. Therefore, when decoding a Quoted-Printable body, any trailing white space on a line must be deleted, as it will necessarily have been added by intermediate transport agents. (4) (Line Breaks) A line break in a text body, represented as a CRLF sequence in the text canonical form, must be represented by a (RFC 822) line break, which is also a CRLF sequence, in the Quoted-Printable encoding. Since the canonical representation of media types other than text do not generally include the representation of line breaks as CRLF sequences, no hard line breaks (i.e. line breaks that are intended to be meaningful and to be displayed to the user) can occur in the quoted-printable encoding of such types. Sequences like "=0D", "=0A", "=0A=0D" and "=0D=0A" will routinely appear in non-text data represented in quoted- printable, of course. (5) (Soft Line Breaks) The Quoted-Printable encoding REQUIRES that encoded lines be no more than 76 characters long. If longer lines are to be encoded with the Quoted-Printable encoding, "soft" line breaks must be used. An equal sign as the last character on a encoded line indicates such a non-significant ("soft") line break in the encoded text. */ int NGEncodeQuotedPrintable(const char *_src, unsigned _srcLen, char *_dest, unsigned _destLen) { unsigned cnt = 0; unsigned destCnt = 0; unsigned lineStart= destCnt; char hexT[16] = {'0','1','2','3','4','5','6','7','8', '9','A','B','C','D','E','F'}; if (_srcLen > _destLen) return -1; for (cnt = 0; (cnt < _srcLen) && (destCnt < _destLen); cnt++) { char c = _src[cnt]; if ((c == 9 || // tab (HT) c == 32) && // space _srcLen - cnt > 0 && (_src[cnt+1] == 13 || _src[cnt+1] == 10)) { if (_destLen - destCnt > 2) { // Encode trailing white space (32) or tab (9) _dest[destCnt++] = '='; _dest[destCnt++] = hexT[(c >> 4) & 15]; _dest[destCnt++] = hexT[c & 15]; continue; } else break; } if (destCnt - lineStart > 70 && // Possibly going to exceed 76 chars this line c != 13 && c != 10) { // Not CR/LF if (_destLen - destCnt > 2) { _dest[destCnt++] = '='; _dest[destCnt++] = '\r'; _dest[destCnt++] = '\n'; lineStart = destCnt; } else break; } if (c == 95) { // we encode the _, otherwise we'll always decode it as a space! if (_destLen - destCnt > 2) { _dest[destCnt++] = '='; _dest[destCnt++] = '5'; _dest[destCnt++] = 'F'; } else break; } else if ((c == 9) || (c == 13) || // carriage return ((c > 31) && (c < 61)) || // alphanumeric without the equal sign ((c > 61) && (c < 127))) { // remaining alphanumeric _dest[destCnt++] = c; // no quoting } else if (c == 10) { // line feed; reset line length counter _dest[destCnt++] = c; lineStart = destCnt; } else { // need to be quoted if (_destLen - destCnt > 2) { _dest[destCnt++] = '='; _dest[destCnt++] = hexT[(c >> 4) & 15]; _dest[destCnt++] = hexT[c & 15]; } else break; } } if (cnt < _srcLen) return -1; return destCnt; } // static linking void __link_NGQuotedPrintableCoding(void) { __link_NGQuotedPrintableCoding(); } SOPE/sope-core/NGExtensions/NGResourceLocator.m0000644000000000000000000001625315004363604020330 0ustar rootroot/* Copyright (C) 2000-2006 SKYRIX Software AG Copyright (C) 2006 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGResourceLocator.h" #include "NSNull+misc.h" #include "common.h" @implementation NGResourceLocator + (id)resourceLocatorForGNUstepPath:(NSString *)_path fhsPath:(NSString *)_fhs{ return [[[self alloc] initWithGNUstepPath:_path fhsPath:_fhs] autorelease]; } - (id)initWithGNUstepPath:(NSString *)_path fhsPath:(NSString *)_fhs { if ((self = [super init])) { self->gsSubPath = [_path copy]; self->fhsSubPath = [_fhs copy]; self->fileManager = [[NSFileManager defaultManager] retain]; self->flags.cacheSearchPathes = 1; self->flags.cachePathMisses = 1; self->flags.cachePathHits = 1; } return self; } - (id)init { #if GNUSTEP_BASE_LIBRARY return [self initWithGNUstepPath:@"Resources" fhsPath:@"share"]; #else return [self initWithGNUstepPath:@"Library/Resources" fhsPath:@"share"]; #endif } - (void)dealloc { [self->nameToPathCache release]; [self->searchPathes release]; [self->fhsSubPath release]; [self->gsSubPath release]; [self->fileManager release]; [super dealloc]; } /* search pathes */ - (NSArray *)gsRootPathes { static NSArray *pathes = nil; NSDictionary *env; NSString *apath; if (pathes != nil) return [pathes isNotNull] ? pathes : (NSArray *)nil; env = [[NSProcessInfo processInfo] environment]; if ((apath = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"]) == nil) apath = [env objectForKey:@"GNUSTEP_PATHLIST"]; if (![apath isNotNull]) return nil; pathes = [[apath componentsSeparatedByString:@":"] copy]; return pathes; } - (NSArray *)fhsRootPathes { // TODO: we probably want to make this configurable?! At least with an envvar static NSArray *pathes = nil; if (pathes == nil) { pathes = [[NSArray alloc] initWithObjects: #ifdef FHS_INSTALL_ROOT FHS_INSTALL_ROOT, #endif @"/usr/local/", @"/usr/", nil]; } return pathes; } - (NSArray *)collectSearchPathes { NSMutableArray *ma; NSEnumerator *e; NSString *p; ma = [NSMutableArray arrayWithCapacity:6]; if ([self->gsSubPath length] > 0) { #if GNUSTEP_BASE_LIBRARY NSString *directory; e = [NSStandardLibraryPaths() objectEnumerator]; while ((directory = [e nextObject])) [ma addObject: [directory stringByAppendingPathComponent:self->gsSubPath]]; #else /* Old hack using GNUSTEP_PATHLIST. Should be removed at some point. */ e = [[self gsRootPathes] objectEnumerator]; while ((p = [e nextObject]) != nil) { p = [p stringByAppendingPathComponent:self->gsSubPath]; if ([ma containsObject:p]) continue; if (![self->fileManager fileExistsAtPath:p]) continue; [ma addObject:p]; } #endif } e = ([self->fhsSubPath length] > 0) ? [[self fhsRootPathes] objectEnumerator] : (NSEnumerator *)nil; while ((p = [e nextObject]) != nil) { p = [p stringByAppendingPathComponent:self->fhsSubPath]; if ([ma containsObject:p]) continue; if (![self->fileManager fileExistsAtPath:p]) continue; [ma addObject:p]; } return ma; } - (NSArray *)searchPathes { NSArray *a; if (self->searchPathes != nil) return self->searchPathes; a = [self collectSearchPathes]; if (self->flags.cacheSearchPathes) { ASSIGNCOPY(self->searchPathes, a); return self->searchPathes; /* return copy */ } return a; } /* cache */ - (void)cachePath:(NSString *)_path forName:(NSString *)_name { if (self->nameToPathCache == nil) self->nameToPathCache = [[NSMutableDictionary alloc] initWithCapacity:64]; [self->nameToPathCache setObject:(_path ? _path : (NSString *)[NSNull null]) forKey:_name]; } /* operation */ - (NSString *)lookupFileWithName:(NSString *)_name { NSEnumerator *e; NSString *p; if (![_name isNotNull] || [_name length] == 0) return nil; if ((p = [self->nameToPathCache objectForKey:_name]) != nil) return [p isNotNull] ? p : (NSString *)nil; e = [[self searchPathes] objectEnumerator]; while ((p = [e nextObject]) != nil) { p = [p stringByAppendingPathComponent:_name]; if (![self->fileManager fileExistsAtPath:p]) continue; [self cachePath:p forName:_name]; return p; } if (self->flags.cachePathMisses) [self cachePath:nil forName:_name]; return nil; } - (NSString *)lookupFileWithName:(NSString *)_name extension:(NSString *)_ext { if ([_ext isNotNull] && [_ext length] > 0) _name = [_name stringByAppendingPathExtension:_ext]; return [self lookupFileWithName:_name]; } - (NSArray *)lookupAllFilesWithExtension:(NSString *)_ext doReturnFullPath:(BOOL)_withPath { /* only deliver each filename once */ NSMutableArray *pathes; NSMutableSet *uniquer; NSArray *lSearchPathes; unsigned i, count; _ext = ([_ext length] > 0) ? [@"." stringByAppendingString:_ext] : (NSString *)nil; uniquer = [NSMutableSet setWithCapacity:128]; pathes = _withPath ? [NSMutableArray arrayWithCapacity:64] : nil; lSearchPathes = [self searchPathes]; for (i = 0, count = [lSearchPathes count]; i < count; i++) { NSArray *filenames; unsigned j, jcount; filenames = [self->fileManager directoryContentsAtPath: [lSearchPathes objectAtIndex:i]]; for (j = 0, jcount = [filenames count]; j < jcount; j++) { NSString *fn, *pn; fn = [filenames objectAtIndex:j]; if (_ext != nil) { if (![fn hasSuffix:_ext]) continue; } if ([uniquer containsObject:fn]) continue; [uniquer addObject:fn]; /* build and cache path */ pn = [[lSearchPathes objectAtIndex:i] stringByAppendingPathComponent:fn]; [self cachePath:pn forName:fn]; if (_withPath) [pathes addObject:pn]; } } return _withPath ? (NSArray *)pathes : [uniquer allObjects]; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; [ms appendFormat:@" gs=%@ fhs=%@", self->gsSubPath, self->fhsSubPath]; [ms appendString:@" cache"]; if (self->flags.cacheSearchPathes) [ms appendString:@":pathes"]; if (self->flags.cachePathHits) [ms appendString:@":hits"]; if (self->flags.cachePathMisses) [ms appendString:@":misses"]; [ms appendFormat:@":#%"PRIuPTR, [self->nameToPathCache count]]; [ms appendString:@">"]; return ms; } @end /* NGResourceLocator */ SOPE/sope-core/NGExtensions/libNGExtensions.def0000644000000000000000000000133615004363604020341 0ustar rootrootEXPORTS __objc_class_name_NGBitSet; __objc_class_name_NGConcreteBitSetEnumerator; __objc_class_name_NGBundleManager; __objc_class_name_NGBundle; __objc_class_name_NGCString; __objc_class_name_NGMutableCString; __objc_class_name_NGExtensions; __objc_class_name_NGHashMap; __objc_class_name_NGMutableHashMap; __objc_class_name__NGHashMapKeyEnumerator; __objc_class_name__NGHashMapObjectEnumerator; __objc_class_name__NGHashMapObjectForKeyEnumerator; __objc_class_name_NGMD5Generator; __objc_class_name_NGStack; __objc_class_name__NGConcreteStackEnumerator; __objc_class_name_NGStackException; NGBundleWasLoadedNotificationName; NGEncodeQuotedPrintable; NGDecodeQuotedPrintable; EODataSourceDidChangeNotification; SOPE/sope-core/NGExtensions/NGLogging.subproj/0000755000000000000000000000000015004363604020101 5ustar rootrootSOPE/sope-core/NGExtensions/NGLogging.subproj/NGLogStderrAppender.m0000644000000000000000000000211115004363604024063 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLogFileHandleAppender.h" @interface NGLogStderrAppender : NGLogFileHandleAppender { } @end #include "common.h" @implementation NGLogStderrAppender - (void)openFileHandleWithConfig:(NSDictionary *)_config { self->fh = [[NSFileHandle fileHandleWithStandardError] retain]; } @end /* NGLogStderrAppender */ SOPE/sope-core/NGExtensions/NGLogging.subproj/NGLogStdoutAppender.m0000644000000000000000000000212315004363604024105 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLogFileHandleAppender.h" @interface NGLogStdoutAppender : NGLogFileHandleAppender { } @end #include "common.h" @implementation NGLogStdoutAppender - (void)openFileHandleWithConfig:(NSDictionary *)_config { self->fh = [[NSFileHandle fileHandleWithStandardOutput] retain]; } @end /* NGLogStdoutAppender */ SOPE/sope-core/NGExtensions/NGLogging.subproj/GNUmakefile0000644000000000000000000000116315004363604022154 0ustar rootroot# GNUstep makefile include ../../../config.make include ../../common.make SUBPROJECT_NAME = NGLogging NGLogging_PCH_FILE = common.h NGLogging_OBJC_FILES += \ NGLogger.m \ NGLoggerManager.m \ NGLogEvent.m \ NGLogEventFormatter.m \ NGLogEventDetailedFormatter.m \ NGLogAppender.m \ NGLogFileHandleAppender.m \ NGLogStdoutAppender.m \ NGLogStderrAppender.m \ # TODO: disable on Windows NGLogging_OBJC_FILES += \ NGLogSyslogAppender.m ADDITIONAL_INCLUDE_DIRS += -I. -I../NGExtensions/ -I.. -I../.. -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/subproject.make -include GNUmakefile.postamble SOPE/sope-core/NGExtensions/NGLogging.subproj/ChangeLog0000644000000000000000000000676015004363604021664 0ustar rootroot2013-06-20 Jean Raby * NGLogger.m (_logLevelForString): fix the check and return the defaultLogLevel instead of hardcoding INFO 2004-12-14 Marcus Mueller * NGLogEventDetailedFormatter.m: added comment regarding process name. 2004-11-19 Marcus Mueller * *.h: added detailed documentation * *.m: added -description where appropriate * NGLogger.m: removed +defaultLogger from the API, it's used internally though. * NGLoggerManager.m: reinstated caching of loggers. Added optimization to reuse a "default" logger when no config is available. * NGLogEvent.[hm]: changed -date to return NSCalendarDate instead of NSDate. * NGLogEventFormatter.[hm]: new base class for implementing formatters. Also offers a factory for creating log event formatter instances from configurations. * NGLogEventDetailedFormatter.m: offers rich logging, similar to what NSLog() in libFoundation has to offer. * NGLogConsoleAppender.m: removed, obsoleted by NGLogStdoutAppender. * NGLogFileHandleAppender.[hm]: new base class for implementing file handle based appenders. * NGLogStdoutAppender.m, NGLogStderrAppender.m: appenders for logging to stdout/stderr. 2004-11-19 Helge Hess * NGLoggerManager.m: use default logger if none is registered * NGLogger.m: cleaned up -init, added default logger * NGLogConsoleAppender.m: removed the bug with using a message in place of a format, rewrote logger to be sufficiently fast 2004-11-18 Marcus Mueller * NGLogLevel.h: new header bearing the log levels * NSObject+ExtendedLogging.[hm]: removed. All equivalent functionality is now in NSObject+Logs.[hm]. * NGLogger.[hm]: changed API to that required by NSObject+Logs.m. 2004-11-17 Marcus Mueller * *.h: provided some documentation * NGLoggerManager.[hm]: new method -loggerForFacilityNamed: for sharing/referencing instances based on names. * NSObject+NGExtendedLogging.h: fixed some serious misordering in log levels (thanks to Helge Hess for reporting this! ;-) * NSObject+NGExtendedLogging.m: some optimizations to default logging facilities (check wheter loglevel is enabled before allocating strings which is expensive). * NGLogger.m: changed some code to address changes in NGLogLevel, shortcut logging immediately if minimum log level is not met. 2004-11-12 Helge Hess * deprecated -defaultManager in favor of -defaultLoggerManager * code cleanups for SOPE styleguides 2004-11-12 Marcus Mueller * NSObject+ExtendedLogging.[hm]: -(id)logger queries NGLoggerManager now. Also, a new default "NGDefaultLogLevel" triggers default NSObject based logging now. * README: new file 2004-11-11 Marcus Mueller * NGLoggerManager.[hm]: controller providing loggers based on information from user defaults (currently) 2004-05-27 Marcus Mueller * NGLogAppender.[hm]: introduced -formattedEvent:, currently not configurable. * NGLogSyslogAppender.m: works as expected now. * NGLogger.m: uses new default (see README) to select the default appender. Not optimal, but sufficient. * NGLogConsoleAppender.m: changed to use -formattedEvent: now. 2004-05-27 Marcus Mueller * NGLogSyslogAppender.[hm]: syslog appender, untested. * ChangeLog: created SOPE/sope-core/NGExtensions/NGLogging.subproj/common.h0000644000000000000000000000002715004363604021541 0ustar rootroot#include "../common.h" SOPE/sope-core/NGExtensions/NGLogging.subproj/NGLogEventDetailedFormatter.m0000644000000000000000000000606315004363604025554 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLogEventFormatter.h" #include "NGLogLevel.h" @class NSString; @interface NGLogEventDetailedFormatter : NGLogEventFormatter { } @end #include "NGLogEvent.h" #include "common.h" #include "NSProcessInfo+misc.h" @implementation NGLogEventDetailedFormatter static unsigned char *processName = NULL; static NSProcessInfo *processInfo = nil; static char *monthNames[14] = { "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan" }; + (void)initialize { static BOOL didInit = NO; unsigned len; NSString *pn; if (didInit) return; didInit = YES; processInfo = [[NSProcessInfo processInfo] retain]; /* NOTE: the processName isn't guaranteed to remain constant - NSProcessInfo even offers an API to change it during runtime. Looking at lF this seems to be unimplemented on an OS level though, and Apple's documentation explicitly states that changing the process name at runtime might be unwise to do. Let's treat it as constant. */ pn = [processInfo processName]; len = [pn cStringLength]; processName = malloc(len + 4); [pn getCString:(char *)processName]; } static __inline__ unsigned char *levelPrefixForEvent(NGLogEvent *_event) { switch ([_event level]) { case NGLogLevelWarn: return (unsigned char *)"[WARN] "; case NGLogLevelError: return (unsigned char *)"[ERROR] "; case NGLogLevelFatal: return (unsigned char *)"[FATAL] "; default: return (unsigned char *)""; } } - (NSString *)formattedEvent:(NGLogEvent *)_event { NSMutableString *fe; NSCalendarDate *date; fe = [NSMutableString stringWithCapacity:160]; /* timestamp, process name, process id, level prefix */ date = [_event date]; [fe appendFormat:@"%s %02"PRIiPTR" %02"PRIiPTR":%02"PRIiPTR":%02"PRIiPTR" %s [%d]: %s", monthNames[[date monthOfYear]], [date dayOfMonth], [date hourOfDay], [date minuteOfHour], [date secondOfMinute], processName, /* Note: pid can change after a fork() */ #if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY [processInfo processIdentifier], #else [[processInfo processId] intValue], #endif levelPrefixForEvent(_event)]; /* message */ [fe appendString:[_event message]]; return fe; } @end /* NGLogEventDetailedFormatter */ SOPE/sope-core/NGExtensions/NGLogging.subproj/NGLogAppender.m0000644000000000000000000000476615004363604022721 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLogAppender.h" #include "NGLogLevel.h" #include "NGLogEvent.h" #include "NGLogEventFormatter.h" #include "common.h" @implementation NGLogAppender static NSString *defaultAppenderClassName = nil; + (void)initialize { static BOOL didInit = NO; NSUserDefaults *ud; if (didInit) return; didInit = YES; ud = [NSUserDefaults standardUserDefaults]; defaultAppenderClassName = [[ud stringForKey:@"NGLogDefaultAppenderClass"] retain]; if (defaultAppenderClassName == nil) defaultAppenderClassName = @"NGLogStderrAppender"; } + (id)logAppenderFromConfig:(NSDictionary *)_config { NSString *className; Class clazz; id appender; className = [_config objectForKey:@"Class"]; if (!className) className = defaultAppenderClassName; clazz = NSClassFromString(className); if (clazz == Nil) { NSLog(@"ERROR: can't instantiate appender class named '%@'", className); return nil; } appender = [[[clazz alloc] initWithConfig:_config] autorelease]; return appender; } - (id)initWithConfig:(NSDictionary *)_config { self = [super init]; if (self) { NSDictionary *formatterConfig; formatterConfig = [_config objectForKey:@"Formatter"]; self->formatter = [[NGLogEventFormatter logEventFormatterFromConfig:formatterConfig] retain]; } return self; } - (void)appendLogEvent:(NGLogEvent *)_event { #if LIB_FOUNDATION_LIBRARY [self subclassResponsibility:_cmd]; #else NSLog(@"ERROR(%s): method should be implemented by subclass!", __PRETTY_FUNCTION__); #endif } /* formatting */ - (NSString *)formattedEvent:(NGLogEvent *)_event { return [self->formatter formattedEvent:_event]; } @end /* NGLogAppender */ SOPE/sope-core/NGExtensions/NGLogging.subproj/README0000644000000000000000000000132315004363604020760 0ustar rootrootNGLogging OVERVIEW ================== TBD: write overview! NOTES ===== NGLoggerManager: - provide some extra config for configuration of appenders for loggers NGLogger: - what about loggingPrefix? - provide API for setting appenders NSObject+ExtendedLogging: - should check if -loggingPrefix is defined. If YES should provide this to logger NGLogEvent - should remember its logger? -> probably important for filtering APPENDER NOTES ============== - We're probably not interested in providing lots of appenders for lots of different loggers. Most of the time we have something like a default appender, say NGLogConsoleAppender during development and NGLogSyslogAppender for deployment (or file appenders) SOPE/sope-core/NGExtensions/NGLogging.subproj/NGLogSyslogAppender.m0000644000000000000000000000546315004363604024115 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLogSyslogAppender.h" #include "NGLogEvent.h" #include #include #include "common.h" @interface NGLogSyslogAppender (PrivateAPI) - (int)syslogLevelForLogLevel:(NGLogLevel)_level; @end @implementation NGLogSyslogAppender static NSString *defaultSyslogIdentifier = nil; + (void)initialize { NSUserDefaults *ud; static BOOL isInitialized = NO; if (isInitialized) return; ud = [NSUserDefaults standardUserDefaults]; defaultSyslogIdentifier = [[ud stringForKey:@"NGLogSyslogIdentifier"] retain]; isInitialized = YES; } + (id)sharedAppender { static id sharedAppender = nil; if (sharedAppender == nil) { sharedAppender = [[self alloc] init]; } return sharedAppender; } - (id)initWithConfig:(NSDictionary *)_config { NSString *identifier; identifier = [_config objectForKey:@"SyslogIdentifier"]; if(!identifier) identifier = defaultSyslogIdentifier; return [self initWithIdentifier:identifier]; } - (id)initWithIdentifier:(NSString *)_ident { if ((self = [super init])) { // TODO: default flags? // TODO: error code processing? openlog([_ident cString], LOG_PID | LOG_NDELAY, LOG_USER); } return self; } - (void)dealloc { closelog(); [super dealloc]; } /* operations */ - (void)appendLogEvent:(NGLogEvent *)_event { NSString *formattedMsg; int level; formattedMsg = [self formattedEvent:_event]; level = [self syslogLevelForLogLevel:[_event level]]; syslog(level, "%s", [formattedMsg cString]); } - (int)syslogLevelForLogLevel:(NGLogLevel)_level { int level; switch (_level) { case NGLogLevelDebug: level = LOG_DEBUG; break; case NGLogLevelInfo: level = LOG_INFO; break; case NGLogLevelWarn: level = LOG_WARNING; break; case NGLogLevelError: level = LOG_ERR; break; case NGLogLevelFatal: level = LOG_ALERT; // LOG_EMERG is broadcast to all users... break; default: level = LOG_NOTICE; break; } return level; } @end /* NGLogSyslogAppender */ SOPE/sope-core/NGExtensions/NGLogging.subproj/NGLoggerManager.m0000644000000000000000000000675515004363604023233 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLoggerManager.h" #include "NGLogLevel.h" #include "NGLogger.h" #include "NSNull+misc.h" #include "common.h" @interface NGLoggerManager (PrivateAPI) - (NGLogger *)_getConfiguredLoggerNamed:(NSString *)_name; @end @implementation NGLoggerManager static NGLoggerManager *sharedInstance = nil; static NSNull *sharedNull = nil; static BOOL debugAll = NO; + (void)initialize { static BOOL didInit = NO; NSUserDefaults *ud; if (didInit) return; didInit = YES; sharedInstance = [[self alloc] init]; sharedNull = [[NSNull null] retain]; ud = [NSUserDefaults standardUserDefaults]; debugAll = [ud boolForKey:@"NGLogDebugAllEnabled"]; } + (id)defaultLoggerManager { return sharedInstance; } + (id)defaultManager { NSLog(@"WARNING(%s): called deprecated method.", __PRETTY_FUNCTION__); return [self defaultLoggerManager]; } - (id)init { self = [super init]; if (self) { self->loggerMap = [[NSMutableDictionary alloc] initWithCapacity:50]; } return self; } - (void)dealloc { [self->loggerMap release]; [super dealloc]; } /* operations */ - (NGLogger *)loggerForDefaultKey:(NSString *)_defaultKey { id logger; logger = [self->loggerMap objectForKey:_defaultKey]; if (!logger) { NSUserDefaults *ud; ud = [NSUserDefaults standardUserDefaults]; if (!debugAll && ![ud boolForKey:_defaultKey]) { [self->loggerMap setObject:sharedNull forKey:_defaultKey]; logger = sharedNull; } else { logger = [self _getConfiguredLoggerNamed:_defaultKey]; [self->loggerMap setObject:logger forKey:_defaultKey]; } } return (logger != sharedNull) ? logger : nil; } - (NGLogger *)loggerForFacilityNamed:(NSString *)_name { NGLogger *logger; // TODO: expensive, use a faster map (at least NSMapTable) if ((logger = [self->loggerMap objectForKey:_name]) != nil) return logger; logger = [self _getConfiguredLoggerNamed:_name]; [self->loggerMap setObject:logger forKey:_name]; return logger; } - (NGLogger *)loggerForClass:(Class)_clazz { NSString *name; name = _clazz != Nil ? NSStringFromClass(_clazz) : (NSString *)nil; return [self loggerForFacilityNamed:name]; } /* Private */ - (NGLogger *)_getConfiguredLoggerNamed:(NSString *)_name { NSString *configKey; configKey = [NSString stringWithFormat:@"%@LoggerConfig", _name]; return [NGLogger loggerWithConfigFromUserDefaults:configKey]; } /* description */ - (NSString *)description { return [NSString stringWithFormat: @"<%@[0x%p] debugAll=%@ #loggers=%"PRIuPTR">", NSStringFromClass([self class]), self, debugAll ? @"YES" : @"NO", [self->loggerMap count]]; } @end /* NGLoggerManager */ SOPE/sope-core/NGExtensions/NGLogging.subproj/NGLogger.m0000644000000000000000000001544415004363604021733 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLogger.h" #include "NGLogEvent.h" #include "NGLogAppender.h" #include "NSNull+misc.h" #include "common.h" @interface NGLogger (PrivateAPI) + (NGLogLevel)_logLevelForString:(NSString *)_level; @end @implementation NGLogger static Class NSStringClass = Nil; static NGLogger *defaultLogger = nil; static NGLogLevel defaultLogLevel = NGLogLevelInfo; + (void)initialize { static BOOL didInit = NO; NSUserDefaults *ud; NSString *level; if (didInit) return; didInit = YES; NSStringClass = [NSString class]; ud = [NSUserDefaults standardUserDefaults]; level = [ud stringForKey:@"NGLogDefaultLogLevel"]; defaultLogLevel = [self _logLevelForString:level]; defaultLogger = [[self alloc] init]; } + (id)loggerWithConfigFromUserDefaults:(NSString *)_defaultName { NSUserDefaults *ud; NSDictionary *config; id logger; ud = [NSUserDefaults standardUserDefaults]; config = [ud dictionaryForKey:_defaultName]; if(!config) return defaultLogger; logger = [[[NGLogger alloc] initWithConfig:config] autorelease]; return logger; } - (id)init { return [self initWithConfig:nil]; } - (id)initWithConfig:(NSDictionary *)_config { self = [super init]; if (self) { NSArray *appenderConfigs; NGLogAppender *appender; NSString *levelString; NGLogLevel level; unsigned count; self->appenders = [[NSMutableArray alloc] initWithCapacity:1]; levelString = [_config objectForKey:@"LogLevel"]; level = [NGLogger _logLevelForString:levelString]; [self setLogLevel:level]; appenderConfigs = [_config objectForKey:@"Appenders"]; count = [appenderConfigs count]; if(!count) { /* create a default appender */ appender = [NGLogAppender logAppenderFromConfig:nil]; [self addAppender:appender]; } else { unsigned i; for(i = 0; i < count; i++) { NSDictionary *appenderConfig; appenderConfig = [appenderConfigs objectAtIndex:i]; appender = [NGLogAppender logAppenderFromConfig:appenderConfig]; if(appender) [self addAppender:appender]; } } } return self; } - (id)initWithLogLevel:(NGLogLevel)_level { self = [self initWithConfig:nil]; if (self) { [self setLogLevel:_level]; } return self; } - (void)dealloc { [self->appenders release]; [super dealloc]; } /* accessors */ - (void)setLogLevel:(NGLogLevel)_level { self->logLevel = _level; } - (NGLogLevel)logLevel { return self->logLevel; } - (void)addAppender:(NGLogAppender *)_appender { [self->appenders addObject:_appender]; } - (void)removeAppender:(NGLogAppender *)_appender { [self->appenders removeObject:_appender]; } /* logging */ - (void)debugWithFormat:(NSString *)_fmt arguments:(va_list)_va { NSString *msg; if (self->logLevel < NGLogLevelDebug) return; msg = [[NSStringClass alloc] initWithFormat:_fmt arguments:_va]; [self logLevel:NGLogLevelDebug message:msg]; [msg release]; } - (void)logWithFormat:(NSString *)_fmt arguments:(va_list)_va { NSString *msg; if (self->logLevel < NGLogLevelInfo) return; msg = [[NSStringClass alloc] initWithFormat:_fmt arguments:_va]; [self logLevel:NGLogLevelInfo message:msg]; [msg release]; } - (void)warnWithFormat:(NSString *)_fmt arguments:(va_list)_va { NSString *msg; if (self->logLevel < NGLogLevelWarn) return; msg = [[NSStringClass alloc] initWithFormat:_fmt arguments:_va]; [self logLevel:NGLogLevelWarn message:msg]; [msg release]; } - (void)errorWithFormat:(NSString *)_fmt arguments:(va_list)_va { NSString *msg; if (self->logLevel < NGLogLevelError) return; msg = [[NSStringClass alloc] initWithFormat:_fmt arguments:_va]; [self logLevel:NGLogLevelError message:msg]; [msg release]; } - (void)fatalWithFormat:(NSString *)_fmt arguments:(va_list)_va { NSString *msg; if (self->logLevel < NGLogLevelFatal) return; msg = [[NSStringClass alloc] initWithFormat:_fmt arguments:_va]; [self logLevel:NGLogLevelFatal message:msg]; [msg release]; } - (void)logLevel:(NGLogLevel)_level message:(NSString *)_msg { NGLogEvent *event; unsigned i, count; event = [[NGLogEvent alloc] initWithLevel:_level message:_msg]; count = [self->appenders count]; for(i = 0; i < count; i++) { NGLogAppender *appender; appender = [self->appenders objectAtIndex:i]; [appender appendLogEvent:event]; } [event release]; } /* log conditions */ - (BOOL)isDebuggingEnabled { return self->logLevel >= NGLogLevelDebug; } - (BOOL)isLogInfoEnabled { return self->logLevel >= NGLogLevelInfo; } - (BOOL)isLogWarnEnabled { return self->logLevel >= NGLogLevelWarn; } - (BOOL)isLogErrorEnabled { return self->logLevel >= NGLogLevelError; } - (BOOL)isLogFatalEnabled { return self->logLevel >= NGLogLevelFatal; } /* Private */ + (NGLogLevel)_logLevelForString:(NSString *)_level { if ([_level length]) { _level = [_level uppercaseString]; if ([_level isEqualToString:@"DEBUG"]) return NGLogLevelDebug; else if ([_level isEqualToString:@"INFO"]) return NGLogLevelInfo; else if ([_level isEqualToString:@"WARN"]) return NGLogLevelWarn; else if ([_level isEqualToString:@"ERROR"]) return NGLogLevelError; else if ([_level isEqualToString:@"FATAL"]) return NGLogLevelFatal; return NGLogLevelAll; /* better than nothing */ } return defaultLogLevel; } /* description */ - (NSString *)description { NSString *lvl; switch (self->logLevel) { case NGLogLevelOff: lvl = @"OFF"; break; case NGLogLevelDebug: lvl = @"DEBUG"; break; case NGLogLevelInfo: lvl = @"INFO"; break; case NGLogLevelWarn: lvl = @"WARN"; break; case NGLogLevelError: lvl = @"ERROR"; break; case NGLogLevelFatal: lvl = @"FATAL"; break; default: lvl = @"ALL"; break; } return [NSString stringWithFormat:@"<%@[0x%p] logLevel=%@ appenders:%@>", NSStringFromClass([self class]), self, lvl, self->appenders]; } @end /* NGLogger */ SOPE/sope-core/NGExtensions/NGLogging.subproj/NGLogEvent.m0000644000000000000000000000434115004363604022231 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLogEvent.h" #include "common.h" @implementation NGLogEvent static Class DateClass = Nil; + (void)initialize { static BOOL didInit = NO; if (didInit) return; didInit = YES; DateClass = [NSCalendarDate class]; } - (id)initWithLevel:(NGLogLevel)_level message:(NSString *)_msg { self = [super init]; if (self) { // TODO: get time using libc function, cheaper self->date = [DateClass timeIntervalSinceReferenceDate]; self->level = _level; self->msg = [_msg copy]; } return self; } - (void)dealloc { [self->msg release]; [super dealloc]; } /* accessors */ - (NGLogLevel)level { return self->level; } - (NSString *)message { return self->msg; } - (NSCalendarDate *)date { // TODO: set to GMT? return [DateClass dateWithTimeIntervalSinceReferenceDate:self->date]; } /* description */ - (NSString *)description { NSString *lvl; switch (self->level) { case NGLogLevelOff: lvl = @"OFF"; break; case NGLogLevelDebug: lvl = @"DEBUG"; break; case NGLogLevelInfo: lvl = @"INFO"; break; case NGLogLevelWarn: lvl = @"WARN"; break; case NGLogLevelError: lvl = @"ERROR"; break; case NGLogLevelFatal: lvl = @"FATAL"; break; default: lvl = @"ALL"; break; } return [NSString stringWithFormat:@"<%@[0x%p] date=%@ level=%@ msg:%@>", NSStringFromClass([self class]), self, [self date], lvl, self->msg]; } @end /* NGLogEvent */ SOPE/sope-core/NGExtensions/NGLogging.subproj/NGLogFileHandleAppender.m0000644000000000000000000000375715004363604024634 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLogFileHandleAppender.h" #include "NGLogEvent.h" #include "common.h" @implementation NGLogFileHandleAppender static NSData *nextLineData = nil; + (void)initialize { static BOOL didInit = NO; if (didInit) return; didInit = YES; nextLineData = [[@"\n" dataUsingEncoding:NSASCIIStringEncoding] retain]; } - (id)initWithConfig:(NSDictionary *)_config { self = [super initWithConfig:_config]; if (self) { self->flushImmediately = NO; self->encoding = [NSString defaultCStringEncoding]; [self openFileHandleWithConfig:_config]; } return self; } - (void)dealloc { if ([self isFileHandleOpen]) [self closeFileHandle]; [self->fh release]; [super dealloc]; } - (BOOL)isFileHandleOpen { return self->fh ? YES : NO; } - (void)openFileHandleWithConfig:(NSDictionary *)_config { } - (void)closeFileHandle { [self->fh closeFile]; } - (void)appendLogEvent:(NGLogEvent *)_event { NSString *formatted; NSData *bin; formatted = [self formattedEvent:_event]; bin = [formatted dataUsingEncoding:self->encoding]; [self->fh writeData:bin]; [self->fh writeData:nextLineData]; if (self->flushImmediately) [self->fh synchronizeFile]; } @end /* NGLogFileHandleAppender */ SOPE/sope-core/NGExtensions/NGLogging.subproj/NGLogEventFormatter.m0000644000000000000000000000401715004363604024115 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLogEventFormatter.h" #include "NGLogEvent.h" #include "common.h" @implementation NGLogEventFormatter static NSString *defaultFormatterClassName = nil; + (void)initialize { static BOOL didInit = NO; NSUserDefaults *ud; if (didInit) return; didInit = YES; ud = [NSUserDefaults standardUserDefaults]; defaultFormatterClassName = [[ud stringForKey:@"NGLogDefaultLogEventFormatterClass"] retain]; if (defaultFormatterClassName == nil) defaultFormatterClassName = @"NGLogEventFormatter"; } + (id)logEventFormatterFromConfig:(NSDictionary *)_config { NSString *className; Class clazz; id formatter; className = [_config objectForKey:@"Class"]; if (!className) className = defaultFormatterClassName; clazz = NSClassFromString(className); if (clazz == Nil) { NSLog(@"ERROR: can't instantiate log event formatter class named '%@'", className); return nil; } formatter = [[[clazz alloc] initWithConfig:_config] autorelease]; return formatter; } - (id)initWithConfig:(NSDictionary *)_config { self = [super init]; if (self) { } return self; } /* formatting */ - (NSString *)formattedEvent:(NGLogEvent *)_event { return [_event message]; } @end /* NGLogEventFormatter */ SOPE/sope-core/NGExtensions/TODO0000644000000000000000000000342015004363604015272 0ustar rootrootTODO ==== - remove dependency on FoundationExt on GNUstep Base and Cocoa - added source of FileObjectHolder, NSRunLoop+FileObjects NSString+Encoding.m: - encoding support for MacOSX and other non-iconv platforms - add a "charset" encoding registry - improve error handling - improve buffer size handling NGLogger: - fix format bugs - fix performance - running two format parsers and varargs processors is unnecessary and far too expensive - running seven methods calls just in logWithFormat:arguments: is expensive - analysis: (for a simple logWithFormat:) - NSObject logWithFormat:arguments: - one format parser - one varargs run - 7 method calls - NSObject logger - caches in static variable, no method call after warm up - NGLogger isLogInfoEnabled - simple comparison (use macro or access public ivars?) - NSObject loggingPrefix - one autorelease string - one format parser - 2 method calls - NGLogger logWithFormat:arguments: - since we already know that logging is enabled, we do not need to check again => forceLogWithPrefix:string: or -logLevel:message: - one format parser - one varargs run - 4 method calls - NGLogger logLevel:message: - creates/releases a log event object - calls appender - 4 method calls - NGLogConsoleAppender - (incorrectly) calls NSLog => one varargs parser - 1 method call - NGLogAppender formattedEvent: - 8 method calls - creates an autorelease string - NGLogAppender localizedNameOfLogLevel: - simple switch - summary: limit NGLogger to the few applications which require it - having -logWithFormat:arguments: on NSObject seems unnecessary, there is no reason to override this method SOPE/sope-core/NGExtensions/NGFileManager.m0000644000000000000000000001766715004363604017401 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGFileManager.h" #include "NGFileManagerURL.h" #include "NSObject+Logs.h" #include "common.h" @implementation NGFileManager static BOOL logPathOps = NO; - (id)init { if ((self = [super init])) { self->cwd = @"/"; } return self; } - (void)dealloc { [self->cwd release]; [super dealloc]; } /* path modifications */ - (NSString *)standardizePath:(NSString *)_path { NSMutableArray *rpc; NSArray *pc; unsigned i, pcn; NSString *result; if (logPathOps) [self logWithFormat:@"standardize: %@", _path]; pc = [_path pathComponents]; if ((pcn = [pc count]) == 0) return _path; if (logPathOps) { [self logWithFormat:@" components: %@", [pc componentsJoinedByString:@" => "]]; } rpc = [NSMutableArray arrayWithCapacity:pcn]; for (i = 0; i < pcn; i++) { NSString *p; p = [pc objectAtIndex:i]; if ([p isEqualToString:@"/"]) { /* found root */ [rpc removeAllObjects]; [rpc addObject:@"/"]; } else if ([p isEqualToString:@"."]) { /* found current directory */ /* '.' can always be removed, right ??? ... */ } else if ([p isEqualToString:@".."]) { /* found parent directory */ if (i == 0) /* relative path starting with '..' */ [rpc addObject:p]; else { /* remove last path component .. */ unsigned count; if ((count = [rpc count]) > 0) [rpc removeObjectAtIndex:(count - 1)]; } } else if ([p isEqualToString:@""]) { /* ignore empty strings */ } else { /* usual path */ [rpc addObject:p]; } } if (logPathOps) { [self logWithFormat:@" new components: %@", [rpc componentsJoinedByString:@" => "]]; } result = [NSString pathWithComponents:rpc]; if ([result length] == 0) return _path; if (logPathOps) [self logWithFormat:@" standardized: %@", result]; return result; } - (NSString *)resolveSymlinksInPath:(NSString *)_path { return _path; } - (NSString *)expandTildeInPath:(NSString *)_path { return _path; } /* directory operations */ - (BOOL)changeCurrentDirectoryPath:(NSString *)_path { BOOL isDir; if (![self fileExistsAtPath:_path isDirectory:&isDir]) return NO; if (!isDir) return NO; ASSIGNCOPY(self->cwd, _path); return YES; } - (NSString *)currentDirectoryPath { return self->cwd; } - (BOOL)createDirectoryAtPath:(NSString *)_path attributes:(NSDictionary *)_ats { return NO; } /* file operations */ - (BOOL)copyPath:(NSString *)_s toPath:(NSString *)_d handler:(id)_handler { return NO; } - (BOOL)movePath:(NSString *)_s toPath:(NSString *)_d handler:(id)_handler { return NO; } - (BOOL)linkPath:(NSString *)_s toPath:(NSString *)_d handler:(id)_handler { return NO; } - (BOOL)removeFileAtPath:(NSString *)_path handler:(id)_handler { return NO; } - (BOOL)createFileAtPath:(NSString *)_path contents:(NSData *)_contents attributes:(NSDictionary *)_attributes { return NO; } /* getting and comparing file contents */ - (NSData *)contentsAtPath:(NSString *)_path { return nil; } - (BOOL)contentsEqualAtPath:(NSString *)_path1 andPath:(NSString *)_path2 { NSData *data1, *data2; data1 = [self contentsAtPath:_path1]; data2 = [self contentsAtPath:_path2]; if (data1 == data2) return YES; if (data1 == nil || data2 == nil) return NO; return [data1 isEqual:data2]; } /* determining access to files */ - (BOOL)fileExistsAtPath:(NSString *)_path { BOOL dummy = NO; return [self fileExistsAtPath:_path isDirectory:&dummy]; } - (BOOL)fileExistsAtPath:(NSString *)_path isDirectory:(BOOL*)_isDirectory { return NO; } - (BOOL)isReadableFileAtPath:(NSString *)_path { return NO; } - (BOOL)isWritableFileAtPath:(NSString *)_path { return NO; } - (BOOL)isExecutableFileAtPath:(NSString *)_path { return NO; } - (BOOL)isDeletableFileAtPath:(NSString *)_path { return NO; } /* Getting and setting attributes */ - (NSDictionary *)fileAttributesAtPath:(NSString *)_p traverseLink:(BOOL)_flag{ return nil; } - (NSDictionary *)fileSystemAttributesAtPath:(NSString *)_p { return nil; } - (BOOL)changeFileAttributes:(NSDictionary *)_attributes atPath:(NSString *)_p{ return NO; } /* discovering directory contents */ - (NSArray *)directoryContentsAtPath:(NSString *)_path { return nil; } - (NSDirectoryEnumerator *)enumeratorAtPath:(NSString *)_path { return nil; } - (NSArray *)subpathsAtPath:(NSString *)_path { return nil; } /* symbolic-link operations */ - (BOOL)createSymbolicLinkAtPath:(NSString *)_p pathContent:(NSString *)_dpath{ return NO; } - (NSString *)pathContentOfSymbolicLinkAtPath:(NSString *)_path { return nil; } /* feature check */ - (BOOL)supportsVersioningAtPath:(NSString *)_path { return [self supportsFeature:NGFileManagerFeature_Versioning atPath:_path]; } - (BOOL)supportsLockingAtPath:(NSString *)_path { return [self supportsFeature:NGFileManagerFeature_Locking atPath:_path]; } - (BOOL)supportsFolderDataSourceAtPath:(NSString *)_path { return [self supportsFeature:NGFileManagerFeature_DataSources atPath:_path]; } - (BOOL)supportsFeature:(NSString *)_featureURI atPath:(NSString *)_path { return NO; } /* writing */ - (BOOL)writeContents:(NSData *)_content atPath:(NSString *)_path { return NO; } /* global-IDs */ - (EOGlobalID *)globalIDForPath:(NSString *)_path; { return nil; } - (NSString *)pathForGlobalID:(EOGlobalID *)_gid { return nil; } /* trash */ - (BOOL)supportsTrashFolderAtPath:(NSString *)_path { return NO; } - (NSString *)trashFolderForPath:(NSString *)_path { return nil; } - (BOOL)trashFileAtPath:(NSString *)_path handler:(id)_handler { NSString *trash, *destPath; BOOL isDir; unsigned i; NSString *tmp; if (![self supportsTrashFolderAtPath:_path]) return NO; if ([(trash = [self trashFolderForPath:_path]) length] == 0) return NO; if ([_path hasPrefix:trash]) /* path already is in trash ... */ return YES; /* ensure that the trash folder is existent */ if ([self fileExistsAtPath:trash isDirectory:&isDir]) { if (!isDir) { NSLog(@"%s: '%@' exists, but isn't a folder !", __PRETTY_FUNCTION__, trash); return NO; } } else { /* trash doesn't exist yet */ if (![self createDirectoryAtPath:trash attributes:nil]) { NSLog(@"%s: couldn't create trash folder '%@' !", __PRETTY_FUNCTION__, trash); return NO; } } /* construct trash path for target ... */ destPath = [trash stringByAppendingPathComponent: [_path lastPathComponent]]; tmp = destPath; i = 0; while ([self fileExistsAtPath:tmp]) { i++; tmp = [destPath stringByAppendingFormat:@"%d", i]; if (i > 40) { NSLog(@"%s: too many files named similar to '%@' in trash folder '%@'", __PRETTY_FUNCTION__, destPath, trash); return NO; } } destPath = tmp; /* move to trash */ if (![self movePath:_path toPath:destPath handler:_handler]) return NO; return YES; } /* URLs */ - (NSURL *)urlForPath:(NSString *)_path { return [[[NGFileManagerURL alloc] initWithPath:_path fileManager:self] autorelease]; } @end /* NGFileManager */ SOPE/sope-core/NGExtensions/GNUmakefile.preamble0000644000000000000000000000323715004363604020450 0ustar rootroot# compilation settings ADDITIONAL_INCLUDE_DIRS += \ -I./NGExtensions/ \ -I./FdExt.subproj/ -I./EOExt.subproj/ ADDITIONAL_CPP_FLAGS += -Wall -Wno-import -Wno-protocol -O2 libNGExtensions_INCLUDE_DIRS += -I.. # Parameters for resource lookup ifneq ($(FHS_INSTALL_ROOT),) ADDITIONAL_CPPFLAGS += -DFHS_INSTALL_ROOT=\@\"$(FHS_INSTALL_ROOT)\" endif ifeq ($(CONFIGURE_64BIT),yes) ADDITIONAL_CPPFLAGS += -DCONFIGURE_64BIT=1 endif # dependencies libNGExtensions_LIBRARIES_DEPEND_UPON += \ -lEOControl -lDOM -lSaxObjC \ -lz $(BASE_LIBS) NGExtensions_LIBRARIES_DEPEND_UPON += \ -framework EOControl \ -framework DOM -framework SaxObjC \ -lz # library/framework search pathes DEP_DIRS = \ ../EOControl \ ../../sope-xml/DOM ../../sope-xml/SaxObjC ifneq ($(frameworks),yes) ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),\ -L$(GNUSTEP_BUILD_DIR)/$(dir)/$(GNUSTEP_OBJ_DIR_NAME)) else ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir)) endif ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) SYSTEM_LIB_DIR += -L/usr/local/lib64 -L/usr/lib64 else SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib endif # Apple ifeq ($(FOUNDATION_LIB),apple) libNGExtensions_PREBIND_ADDR="0xC1200000" libNGExtensions_LDFLAGS += -seg1addr $(libNGExtensions_PREBIND_ADDR) endif # platform specific settings ifeq ($(GNUSTEP_HOST_OS),rhapsody5.5) #libNGExtensions_LIBRARIES_DEPEND_UPON += -lFoundationExt endif ifeq ($(GNUSTEP_TARGET_OS),freebsd) libNGExtensions_LIB_DIRS += -L/usr/local/lib libNGExtensions_LIBRARIES_DEPEND_UPON += -liconv endif # Foundation specific settings ifeq ($(FOUNDATION_LIB),nx) ADDITIONAL_LDFLAGS += -framework Foundation endif SOPE/sope-core/NGExtensions/NGCustomFileManager.m0000644000000000000000000003400615004363604020556 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "common.h" typedef struct { NSString *sourcePath; NSString *absolutePath; NSString *path; NGCustomFileManagerInfo *info; id fileManager; } NGCustomFMPath; @interface NGCustomFileManager(Helpers) - (NGCustomFMPath)_resolvePath:(NSString *)_path; - (BOOL)_boolDo:(SEL)_sel onPath:(NSString *)_path; - (BOOL)_boolDo:(SEL)_sel onPath:(NSString *)_path handler:(id)_handler; - (id)_do:(SEL)_sel onPath:(NSString *)_path; @end @implementation NGCustomFileManager /* customization */ - (NSString *)makeAbsolutePath:(NSString *)_path { if ([_path isAbsolutePath]) return _path; return [[self currentDirectoryPath] stringByAppendingPathComponent:_path]; } - (NGCustomFileManagerInfo *)fileManagerInfoForPath:(NSString *)_path { return nil; } /* common ops */ - (NGCustomFMPath)_resolvePath:(NSString *)_path { NGCustomFMPath p; p.sourcePath = _path; p.absolutePath = [self makeAbsolutePath:_path]; p.info = [self fileManagerInfoForPath:_path]; p.path = [p.info rewriteAbsolutePath:p.absolutePath]; p.fileManager = [p.info fileManager]; return p; } - (BOOL)_boolDo:(SEL)_sel onPath:(NSString *)_path { NGCustomFMPath p; BOOL (*op)(id,SEL,NSString *); if (_sel == NULL) return NO; p = [self _resolvePath:_path]; if ((_path = p.path) == nil) return NO; if ((op = (void *)[p.fileManager methodForSelector:_sel]) == NULL) return NO; return op(p.fileManager, _sel, _path); } - (BOOL)_boolDo:(SEL)_sel onPath:(NSString *)_path handler:(id)_handler { NGCustomFMPath p; BOOL (*op)(id,SEL,NSString *,id); if (_sel == NULL) return NO; p = [self _resolvePath:_path]; if ((_path = p.path) == nil) return NO; if ((op = (void *)[p.fileManager methodForSelector:_sel]) == NULL) return NO; return op(p.fileManager, _sel, _path, _handler); } - (id)_do:(SEL)_sel onPath:(NSString *)_path { NGCustomFMPath p; id (*op)(id,SEL,NSString *); if (_sel == NULL) return nil; p = [self _resolvePath:_path]; if ((_path = p.path) == nil) return nil; if ((op = (void *)[p.fileManager methodForSelector:_sel]) == NULL) return nil; return op(p.fileManager, _sel, _path); } /* directory operations */ - (BOOL)changeCurrentDirectoryPath:(NSString *)_path { BOOL isDir = NO; if ((_path = [self makeAbsolutePath:_path]) == nil) return NO; if (![self fileExistsAtPath:_path isDirectory:&isDir]) return NO; if (!isDir) return NO; ASSIGNCOPY(self->cwd, _path); return YES; } - (NSString *)currentDirectoryPath { return self->cwd; } - (BOOL)createDirectoryAtPath:(NSString *)_path attributes:(NSDictionary *)_ats { NGCustomFMPath p; p = [self _resolvePath:_path]; if (p.path == nil) return NO; return [p.fileManager createDirectoryAtPath:p.path attributes:_ats]; } /* file operations */ - (BOOL)copyPath:(NSString *)_s toPath:(NSString *)_d handler:(id)_handler { NGCustomFileManagerInfo *sinfo, *dinfo; if ((_s = [self makeAbsolutePath:_s]) == nil) return NO; if ((_d = [self makeAbsolutePath:_d]) == nil) return NO; if ((sinfo = [self fileManagerInfoForPath:_s]) == nil) return NO; if ((dinfo = [self fileManagerInfoForPath:_d]) == nil) return NO; _s = [sinfo rewriteAbsolutePath:_s]; _d = [dinfo rewriteAbsolutePath:_d]; if ([sinfo isEqual:dinfo]) /* same filemanager */ return [[sinfo fileManager] copyPath:_s toPath:_d handler:_handler]; /* operation between different filemanagers ... */ return NO; } - (BOOL)movePath:(NSString *)_s toPath:(NSString *)_d handler:(id)_handler { NGCustomFileManagerInfo *sinfo, *dinfo; if ((_s = [self makeAbsolutePath:_s]) == nil) return NO; if ((_d = [self makeAbsolutePath:_d]) == nil) return NO; if ((sinfo = [self fileManagerInfoForPath:_s]) == nil) return NO; if ((dinfo = [self fileManagerInfoForPath:_d]) == nil) return NO; _s = [sinfo rewriteAbsolutePath:_s]; _d = [dinfo rewriteAbsolutePath:_d]; if ([sinfo isEqual:dinfo]) /* same filemanager */ return [[sinfo fileManager] movePath:_s toPath:_d handler:_handler]; /* operation between different filemanagers ... */ return NO; } - (BOOL)linkPath:(NSString *)_s toPath:(NSString *)_d handler:(id)_handler { NGCustomFileManagerInfo *sinfo, *dinfo; if ((_s = [self makeAbsolutePath:_s]) == nil) return NO; if ((_d = [self makeAbsolutePath:_d]) == nil) return NO; if ((sinfo = [self fileManagerInfoForPath:_s]) == nil) return NO; if ((dinfo = [self fileManagerInfoForPath:_d]) == nil) return NO; _s = [sinfo rewriteAbsolutePath:_s]; _d = [dinfo rewriteAbsolutePath:_d]; if ([sinfo isEqual:dinfo]) /* same filemanager */ return [[sinfo fileManager] linkPath:_s toPath:_d handler:_handler]; /* operation between different filemanagers ... */ return NO; } - (BOOL)removeFileAtPath:(NSString *)_path handler:(id)_handler { return [self _boolDo:_cmd onPath:_path handler:_handler]; } - (BOOL)createFileAtPath:(NSString *)_path contents:(NSData *)_contents attributes:(NSDictionary *)_attributes { NGCustomFMPath p; p = [self _resolvePath:_path]; if (p.path == nil) return NO; return [p.fileManager createFileAtPath:p.path contents:_contents attributes:_attributes]; } /* getting and comparing file contents */ - (NSData *)contentsAtPath:(NSString *)_path { return [self _do:_cmd onPath:_path]; } - (BOOL)contentsEqualAtPath:(NSString *)_path1 andPath:(NSString *)_path2 { NGCustomFileManagerInfo *info1, *info2; if ((_path1 = [self makeAbsolutePath:_path1]) == nil) return NO; if ((_path2 = [self makeAbsolutePath:_path2]) == nil) return NO; if ((info1 = [self fileManagerInfoForPath:_path1]) == nil) return NO; if ((info2 = [self fileManagerInfoForPath:_path2]) == nil) return NO; _path1 = [info1 rewriteAbsolutePath:_path1]; _path2 = [info2 rewriteAbsolutePath:_path2]; if ([info1 isEqual:info2]) /* same filemanager */ return [[info1 fileManager] contentsEqualAtPath:_path1 andPath:_path2]; /* operation between different filemanagers ... */ return NO; } /* determining access to files */ - (BOOL)fileExistsAtPath:(NSString *)_path { return [self _boolDo:_cmd onPath:_path]; } - (BOOL)fileExistsAtPath:(NSString *)_path isDirectory:(BOOL *)_isDirectory { NGCustomFMPath p; p = [self _resolvePath:_path]; if (p.path == nil) return NO; return [p.fileManager fileExistsAtPath:p.path isDirectory:_isDirectory]; } - (BOOL)isReadableFileAtPath:(NSString *)_path { return [self _boolDo:_cmd onPath:_path]; } - (BOOL)isWritableFileAtPath:(NSString *)_path { return [self _boolDo:_cmd onPath:_path]; } - (BOOL)isExecutableFileAtPath:(NSString *)_path { return [self _boolDo:_cmd onPath:_path]; } - (BOOL)isDeletableFileAtPath:(NSString *)_path { return [self _boolDo:_cmd onPath:_path]; } /* Getting and setting attributes */ - (NSDictionary *)fileAttributesAtPath:(NSString *)_p traverseLink:(BOOL)_flag{ NGCustomFMPath p; p = [self _resolvePath:_p]; if (p.path == nil) return nil; /* special link handling required ??? */ return [p.fileManager fileAttributesAtPath:p.path traverseLink:_flag]; } - (NSDictionary *)fileSystemAttributesAtPath:(NSString *)_p { return [self _do:_cmd onPath:_p]; } - (BOOL)changeFileAttributes:(NSDictionary *)_attributes atPath:(NSString *)_p{ NGCustomFMPath p; p = [self _resolvePath:_p]; if (p.path == nil) return NO; return [p.fileManager changeFileAttributes:_attributes atPath:p.path]; } /* discovering directory contents */ - (NSArray *)directoryContentsAtPath:(NSString *)_path { /* this returns relative path's, can be passed back */ return [self _do:_cmd onPath:_path]; } - (NSDirectoryEnumerator *)enumeratorAtPath:(NSString *)_path { /* this needs to be wrapped ! */ return nil; } - (NSArray *)subpathsAtPath:(NSString *)_path { /* this returns relative path's, can be passed back */ return [self _do:_cmd onPath:_path]; } /* symbolic-link operations */ - (BOOL)createSymbolicLinkAtPath:(NSString *)_p pathContent:(NSString *)_dpath{ /* should that process the link-path somehow ??? */ NGCustomFMPath p; p = [self _resolvePath:_p]; if (p.path == nil) return NO; return [p.fileManager createSymbolicLinkAtPath:p.path pathContent:_dpath]; } - (NSString *)pathContentOfSymbolicLinkAtPath:(NSString *)_path { /* should that process the link-path somehow ??? */ return [self _do:_cmd onPath:_path]; } /* feature check */ - (BOOL)supportsVersioningAtPath:(NSString *)_path { return [self _boolDo:_cmd onPath:_path]; } - (BOOL)supportsLockingAtPath:(NSString *)_path { return [self _boolDo:_cmd onPath:_path]; } - (BOOL)supportsFolderDataSourceAtPath:(NSString *)_path { return [self _boolDo:_cmd onPath:_path]; } - (BOOL)supportsFeature:(NSString *)_featureURI atPath:(NSString *)_path { NGCustomFMPath p; p = [self _resolvePath:_path]; if (p.path == nil) return NO; return [p.fileManager supportsFeature:_featureURI atPath:p.path]; } /* writing */ - (BOOL)writeContents:(NSData *)_content atPath:(NSString *)_path { NGCustomFMPath p; p = [self _resolvePath:_path]; if (p.path == nil) return NO; return [p.fileManager writeContents:_content atPath:p.path]; } /* global-IDs */ - (EOGlobalID *)globalIDForPath:(NSString *)_path { NGCustomFileManagerInfo *info; if ((_path = [self makeAbsolutePath:_path]) == nil) return nil; if ((info = [self fileManagerInfoForPath:_path]) == nil) return nil; if (![info supportsGlobalIDs]) return nil; if ((_path = [info rewriteAbsolutePath:_path]) == nil) return nil; return [[info fileManager] globalIDForPath:_path]; } - (NSString *)pathForGlobalID:(EOGlobalID *)_gid { return nil; } /* trash */ - (BOOL)supportsTrashFolderAtPath:(NSString *)_path { return [self _boolDo:_cmd onPath:_path]; } - (NSString *)trashFolderForPath:(NSString *)_path { return nil; } @end /* NGCustomFileManager */ @implementation NGCustomFileManager(NGFileManagerVersioning) /* versioning */ - (BOOL)checkoutFileAtPath:(NSString *)_path handler:(id)_handler { return [self _boolDo:_cmd onPath:_path handler:_handler]; } - (BOOL)releaseFileAtPath:(NSString *)_path handler:(id)_handler { return [self _boolDo:_cmd onPath:_path handler:_handler]; } - (BOOL)rejectFileAtPath:(NSString *)_path handler:(id)_handler { return [self _boolDo:_cmd onPath:_path handler:_handler]; } - (BOOL)checkoutFileAtPath:(NSString *)_path version:(NSString *)_version handler:(id)_handler { NGCustomFMPath p; p = [self _resolvePath:_path]; if (p.path == nil) return NO; return [p.fileManager checkoutFileAtPath:p.path version:_version handler:_handler]; } /* versioning data */ - (NSString *)lastVersionAtPath:(NSString *)_path { return [self _do:_cmd onPath:_path]; } - (NSArray *)versionsAtPath:(NSString *)_path { return [self _do:_cmd onPath:_path]; } - (NSData *)contentsAtPath:(NSString *)_path version:(NSString *)_version { NGCustomFMPath p; p = [self _resolvePath:_path]; if (p.path == nil) return nil; return [p.fileManager contentsAtPath:p.path version:_version]; } - (NSDictionary *)fileAttributesAtPath:(NSString *)_path traverseLink:(BOOL)_followLink version:(NSString *)_version { NGCustomFMPath p; p = [self _resolvePath:_path]; if (p.path == nil) return nil; /* do something special to symlink ??? */ return [p.fileManager fileAttributesAtPath:p.path traverseLink:_followLink version:_version]; } @end /* NGCustomFileManager(NGFileManagerVersioning) */ @implementation NGCustomFileManager(NGFileManagerLocking) - (BOOL)lockFileAtPath:(NSString *)_path handler:(id)_handler { return [self _boolDo:_cmd onPath:_path handler:_handler]; } - (BOOL)unlockFileAtPath:(NSString *)_path handler:(id)_handler { return [self _boolDo:_cmd onPath:_path handler:_handler]; } - (BOOL)isFileLockedAtPath:(NSString *)_path { return [self _boolDo:_cmd onPath:_path]; } /* access rights */ - (BOOL)isLockableFileAtPath:(NSString *)_path { return [self _boolDo:_cmd onPath:_path]; } - (BOOL)isUnlockableFileAtPath:(NSString *)_path { return [self _boolDo:_cmd onPath:_path]; } @end /* NGCustomFileManager(NGFileManagerLocking) */ @implementation NGCustomFileManager(NGFileManagerDataSources) /* datasources (work on folders) */ - (EODataSource *)dataSourceAtPath:(NSString *)_path { return [self _do:_cmd onPath:_path]; } - (EODataSource *)dataSource { return [self dataSourceAtPath:[self currentDirectoryPath]]; } @end /* NGCustomFileManager(NGFileManagerDataSources) */ @implementation NGCustomFileManagerInfo - (id)initWithCustomFileManager:(NGCustomFileManager *)_master fileManager:(id)_fm { self->master = _master; self->fileManager = [_fm retain]; return self; } - (id)init { return [self initWithCustomFileManager:nil fileManager:nil]; } - (void)dealloc { [self->fileManager release]; [super dealloc]; } - (void)resetMaster { self->master = nil; } /* accessors */ - (NGCustomFileManager *)master { return self->master; } - (id)fileManager { return self->fileManager; } /* operations */ - (NSString *)rewriteAbsolutePath:(NSString *)_path { return _path; } /* capabilities */ - (BOOL)supportsGlobalIDs { return [self->fileManager respondsToSelector:@selector(globalIDForPath:)]; } @end /* NGCustomFileManagerInfo */ SOPE/sope-core/NGExtensions/XmlExt.subproj/0000755000000000000000000000000015004363604017507 5ustar rootrootSOPE/sope-core/NGExtensions/XmlExt.subproj/GNUmakefile0000644000000000000000000000054015004363604021560 0ustar rootroot# GNUstep makefile include ../../../config.make include ../../common.make SUBPROJECT_NAME = XmlExt XmlExt_OBJC_FILES = \ DOMNode+EOQualifier.m ADDITIONAL_INCLUDE_DIRS += \ -I. -I.. \ -I../NGExtensions/ \ -I../../../sope-xml/ \ -I../.. -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/subproject.make -include GNUmakefile.postamble SOPE/sope-core/NGExtensions/XmlExt.subproj/DOMNode+EOQualifier.m0000644000000000000000000000663715004363604023267 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DOMNode+EOQualifier.h" #import #include "common.h" @interface NSObject(DOMNodeEOQualifier) - (NSArray *)_domChildrenMatchingQualifier:(EOQualifier *)_qualifier; - (NSArray *)_domDescendantsMatchingQualifier:(EOQualifier *)_qualifier includeSelf:(BOOL)_includeSelf; @end @implementation NSObject(DOMNodeEOQualifier) /* this category is used to support DOM ops on any object */ static NSArray *emptyArray = nil; - (NSArray *)_domChildrenMatchingQualifier:(EOQualifier *)_qualifier { id children; unsigned count; if (![(id)self hasChildNodes]) return nil; if ((children = [(id)self childNodes]) == nil) return nil; if ((count = [children count]) == 0) { if (emptyArray == nil) emptyArray = [[NSArray alloc] init]; return emptyArray; } else { NSMutableArray *marray; unsigned i; marray = [NSMutableArray arrayWithCapacity:(count + 1)]; for (i = 0; i < count; i++) { id childNode; if ((childNode = [children objectAtIndex:i])) { if ((_qualifier == nil) || [(id)_qualifier evaluateWithObject:childNode]) [marray addObject:childNode]; } } return [[marray copy] autorelease]; } } - (void)_addDOMDescendantsMatchingQualifier:(EOQualifier *)_qualifier toMutableArray:(NSMutableArray *)_array includeSelf:(BOOL)_includeSelf { id children; unsigned i, count; if (_includeSelf) { if ([(id)_qualifier evaluateWithObject:self]) [_array addObject:self]; } if (![(id)self hasChildNodes]) return; children = [(id)self childNodes]; for (i = 0, count = [children count]; i < count; i++) { [[children objectAtIndex:i] _addDOMDescendantsMatchingQualifier:_qualifier toMutableArray:_array includeSelf:YES]; } } - (NSArray *)_domDescendantsMatchingQualifier:(EOQualifier *)_qualifier includeSelf:(BOOL)_includeSelf { NSMutableArray *marray; marray = [NSMutableArray arrayWithCapacity:16]; [self _addDOMDescendantsMatchingQualifier:_qualifier toMutableArray:marray includeSelf:_includeSelf]; return [[marray copy] autorelease]; } @end /* NSObject(DOMNodeEOQualifier) */ @implementation NGDOMNode(EOQualifier) - (NSArray *)childrenMatchingQualifier:(EOQualifier *)_qualifier { return [self _domChildrenMatchingQualifier:_qualifier]; } - (NSArray *)descendantsMatchingQualifier:(EOQualifier *)_qualifier { return [self _domDescendantsMatchingQualifier:_qualifier includeSelf:NO]; } @end /* NGDOMNode(EOQualifier) */ SOPE/sope-core/GNUmakefile0000644000000000000000000000111315004363604014265 0ustar rootroot# GNUstep makefile include ../config.make include $(GNUSTEP_MAKEFILES)/common.make PACKAGE_NAME=sope-core VERSION=4.5.0 SUBPROJECTS += \ EOControl \ NGExtensions \ NGStreams # compile EOCoreData if we are on Tiger ifeq ($(findstring darwin8, $(GNUSTEP_TARGET_OS)), darwin8) SUBPROJECTS += EOCoreData endif ifeq ($(frameworks),yes) include umbrella.make endif # project makefiles include $(GNUSTEP_MAKEFILES)/aggregate.make ifeq ($(frameworks),yes) include $(GNUSTEP_MAKEFILES)/framework.make endif # package macosx-pkg :: all ../maintenance/make-osxpkg.sh $(PACKAGE_NAME) SOPE/sope-core/ChangeLog0000644000000000000000000000650015004363604013772 0ustar rootroot2008-03-04 Marcus Mueller * README-OSX.txt: Updated 2005-08-26 Helge Hess * all makefiles: add common.h as the precompiled header file 2005-08-17 Helge Hess * added sope-core umbrella framework 2005-08-10 Helge Hess * all makefiles: added flags to build only frameworks on MacOSX 2005-08-08 Marcus Mueller * README-OSX.txt: updated prebinding info 2004-10-17 Helge Hess * all makefiles: include config.make if available 2004-09-22 Marcus Mueller * sope-core.xcode: Fixed wrong build order 2004-09-21 Marcus Mueller * sope-core.xcode: Fixed dependencies to resemble the make process more closely. Our aim should be to stick to the make process as closely as possible, so we shouldn't introduce dependencies in non-toplevel projects. 2004-08-29 Marcus Mueller * sope-core.xcode: fixed file encodings * SxCore*: removed old Xcode and related files 2004-08-23 Marcus Mueller * added new sope-core.xcode 2004-08-20 Helge Hess * common.make: updated for new SOPE 4.3 hierarchy * updated Version to 4.3 2004-08-16 Marcus Mueller * SxCore.xcode: added NGCalendarDateRange.[hm] 2004-07-21 Marcus Mueller * SxCore.xcode: fixed incorrect framework search paths. 2004-07-21 Marcus Mueller * README-OSX.txt: Major overhaul for build description, especially the Xcode section. 2004-07-16 Marcus Mueller * SxCore.xcode: added 'Wrapper' build style and 'Wrapper Contents' target. Use these to build the frameworks in an appropriate form to have them embedded in an applications app wrapper's 'Frameworks' folder. * SxCore.xcode: LDAP related targets link against new LDAP system framework now. 2004-06-11 Marcus Mueller * SxCore.xcode: removed NGCString from NGExtensions (deprecated) 2004-06-09 Helge Hess * common.make: removed local ADDITIONAL_LIB_DIRS since those might not yet be available during compilation, which in turn prints warnings with Apple gcc 2004-05-09 Helge Hess * SxCore.xcode: added subclassing test tool 2004-03-24 Marcus Mueller * SxCore.xcode: added NSString+German.[hm] in NGExtensions. Also, added -headerpad_max_install_names link option where appropriate. 2004-03-15 Helge Hess * SxCore.xcode: added new plist categories in NGExtensions to Xcode project 2004-03-08 Helge Hess * SxCore.xcode: added new source files in EOControl to Xcode project * README-OSX.txt: added some build notes 2004-02-10 Marcus Mueller * SxCore.xcode: Updated prebinding information according to README-OSX.txt. Also, added Foundation.framework explicitly to all subprojects. * README-OSX.txt: New README currently describing prebinding information for Mac OS X. * ChangeLog: created. SOPE/sope-core/dummy.c0000644000000000000000000000215415004363604013520 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* this is required by the "fake" frameworks NGImap4 and NGMail, otherwise linking will fail with: ---snip--- ld: /Users/helge/build/NGImap4.framework/NGImap4 tocoff in load command 7 extends past the end of the file ld: /Users/helge/build/NGMail.framework/NGMail tocoff in load command 7 extends past the end of the file ---snap--- */ SOPE/sope-core/COPYING0000644000000000000000000006130315004363604013255 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-core/README0000644000000000000000000000042115004363604013074 0ustar rootrootsope-core ========= This repository contains the core libraries of the SOPE application server, that is, extensions to the Foundation library (NGExtensions), streaming IO and network classes (NGStreams), libraries for datastore abstractions (EOControl). TODO: write more SOPE/sope-core/Version0000644000000000000000000000032415004363604013566 0ustar rootroot# # This file is included by library makefiles to set the version information # of the executable. MAJOR_VERSION=4 MINOR_VERSION=9 # subminor versions are set in the Version files contained in the library path SOPE/sope-core/NGStreams/0000755000000000000000000000000015004363604014062 5ustar rootrootSOPE/sope-core/NGStreams/NGDatagramPacket.m0000644000000000000000000000467015004363604017344 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGDatagramPacket.h" #include "common.h" @implementation NGDatagramPacket + (id)packetWithData:(NSData *)_data { return [[[self alloc] initWithData:_data] autorelease]; } + (id)packetWithBytes:(const void *)_bytes size:(int)_packetSize { return [[[self alloc] initWithBytes:_bytes size:_packetSize] autorelease]; } - (id)initWithBytes:(const void *)_bytes size:(int)_packetSize { return [self initWithData:[NSData dataWithBytes:_bytes length:_packetSize]]; } - (id)initWithData:(NSData *)_data { if ((self = [self init])) { self->packet = [_data copyWithZone:[self zone]]; } return self; } - (void)dealloc { [self->packet release]; [self->sender release]; [self->receiver release]; [super dealloc]; } /* accessors */ - (void)setSender:(id)_address { ASSIGN(self->sender, _address); } - (id)sender { return self->sender; } - (void)setReceiver:(id)_address { ASSIGN(self->receiver, _address); } - (id)receiver { return self->receiver; } - (void)setData:(NSData *)_data { ASSIGN(self->packet, _data); } - (NSData *)data { return self->packet; } - (int)packetSize { return [self->packet length]; } /* operations */ - (void)reverseAddresses { id oldSender = [[self sender] retain]; [self setSender:[self receiver]]; [self setReceiver:oldSender]; [oldSender release]; oldSender = nil; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"<%@[0x%p]: from=%@ to=%@ size=%i>", NSStringFromClass([self class]), self, [self sender], [self receiver], [self packetSize]]; } @end /* NGDatagramPacket */ SOPE/sope-core/NGStreams/NGDescriptorFunctions.m0000644000000000000000000002361515004363604020503 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if !defined(WIN32) || defined(__CYGWIN32__) // similar functions for Windows can be found in NGSocket.[hm] #include "NGDescriptorFunctions.h" #include "NGStreamExceptions.h" #include "common.h" #include "config.h" #ifdef HAVE_POLL # ifdef HAVE_POLL_H # include # endif # ifdef HAVE_SYS_POLL_H # include # endif # ifndef POLLRDNORM # define POLLRDNORM POLLIN /* needed on Linux */ # endif #else # ifdef HAVE_SELECT_H # include # endif #endif #if defined(HAVE_SYS_SOCKET_H) || defined(__APPLE__) # include #endif #ifdef HAVE_SYS_FCNTL_H # include #endif #if defined(HAVE_FCNTL_H) || defined(__APPLE__) # include #endif #if HAVE_UNISTD_H || defined(__APPLE__) # include #endif #if HAVE_LIMITS_H # include #endif #if HAVE_SYS_TIME_H || defined(__APPLE__) # include #endif #if HAVE_SYS_TYPES_H || defined(__APPLE__) # include #endif #if !HAVE_TTYNAME_R # if LIB_FOUNDATION_LIBRARY extern NSRecursiveLock *libFoundationLock = nil; # define systemLock libFoundationLock # else # ifndef __APPLE__ # warning "No locking support for ttyname on this platform" # endif # define systemLock (id)nil # endif #endif // ******************** Poll ********************* int NGPollDescriptor(int _fd, short _events, int _timeout) { #ifdef HAVE_POLL struct pollfd pfd; int result; pfd.fd = _fd; pfd.events = _events; pfd.revents = 0; do { result = poll(&pfd, 1, _timeout); if (result < 0) { // error int e = errno; if (e == 0) { NSLog(@"%s: errno is 0, but return value of poll is <0 (%i) (retry) ?!", __PRETTY_FUNCTION__, result); continue; } if ((e != EAGAIN) && (e != EINTR)) // only retry of interrupted or repeatable break; } } while (result < 0); /* revents: POLLERR POLLHUP POLLNVAL */ return (result < 0) ? -1 : result; #else struct timeval timeout; fd_set rSet; fd_set wSet; fd_set eSet; int result; FD_ZERO(&rSet); FD_ZERO(&wSet); FD_ZERO(&eSet); if (_events & POLLIN) FD_SET(_fd, &rSet); if (_events & POLLOUT) FD_SET(_fd, &wSet); if (_events & POLLERR) FD_SET(_fd, &eSet); timeout.tv_sec = _timeout / 1000; timeout.tv_usec = _timeout * 1000 - timeout.tv_sec * 1000000; do { result = select(FD_SETSIZE, &rSet, &wSet, &eSet, &timeout); if (result == -1) { // error int e = errno; if ((e != EAGAIN) && (e != EINTR)) // only retry of interrupted or repeatable break; } } while (result == -1); return (result < 0) ? -1 : result; #endif } // ******************** Flags ******************** int NGGetDescriptorFlags(int _fd) { int val; val = fcntl(_fd, F_GETFL, 0); if (val < 0) [NGIOException raiseWithReason:@"could not get descriptor flags"]; return val; } void NGSetDescriptorFlags(int _fd, int _flags) { if (fcntl(_fd, F_SETFL, _flags) == -1) [NGIOException raiseWithReason:@"could not set descriptor flags"]; } void NGAddDescriptorFlag(int _fd, int _flag) { int val = NGGetDescriptorFlags(_fd); NGSetDescriptorFlags(_fd, val | _flag); } // ******************** NonBlocking IO ************ static int enableDescLogging = -1; int NGDescriptorRecv(int _fd, char *_buf, int _len, int _flags, int _timeout /* in ms */) { int errorCode; int result; if (enableDescLogging == -1) { enableDescLogging = [[[NSUserDefaults standardUserDefaults] objectForKey:@"NGLogDescriptorRecv"] boolValue] ? YES : NO; } if (enableDescLogging) { NSLog(@"%s(fd=%i,buf=0x%p,len=%i,flags=%i,timeout=%i)", __PRETTY_FUNCTION__, _fd,_buf,_len,_flags,_timeout); } if (_timeout == -1) _timeout = 1000 * 60 * 60; /* default timeout: 1 hour */ result = recv(_fd, _buf, _len, _flags); errorCode = errno; if (result == 0) return 0; // EOF if (enableDescLogging) { if ((result < 0) && (errorCode == EINVAL)) { NSLog(@"%s: invalid argument in recv(%i, 0x%p, %i, %i)", __PRETTY_FUNCTION__, _fd, _buf, _len, _flags); } } if (enableDescLogging) { NSLog(@"result=%i, error=%i(%s)", result, errorCode, strerror(errorCode)); } if ((result == -1) && (errorCode == EWOULDBLOCK)) { // retry #if HAVE_POLL struct pollfd pfd; pfd.fd = _fd; pfd.events = POLLRDNORM; pfd.revents = 0; do { if (enableDescLogging) NSLog(@"starting poll, loop (to=%i)", _timeout); if ((result = poll(&pfd, 1, _timeout)) < 0) { errorCode = errno; if (enableDescLogging) { if (errno == EINVAL) NSLog(@"%s: invalid argument to poll(...)", __PRETTY_FUNCTION__); } if (errorCode == 0) { NSLog(@"%s: errno is 0, but return value of poll is <0 (%i) (retry) ?!", __PRETTY_FUNCTION__, result); continue; } // retry if interrupted if ((errorCode != EINTR) && (errorCode != EAGAIN)) break; } } while (result < 0); #else struct timeval timeout; fd_set rSet; fd_set wSet; fd_set eSet; FD_ZERO(&rSet); FD_ZERO(&wSet); FD_ZERO(&eSet); FD_SET(_fd, &rSet); timeout.tv_sec = _timeout / 1000; timeout.tv_usec = _timeout * 1000 - timeout.tv_sec * 1000000; do { result = select(FD_SETSIZE, &rSet, &wSet, &eSet, &timeout); if (enableDescLogging) { if ((result < 0) && (errno == EINVAL)) NSLog(@"%s: invalid argument in select(...)", __PRETTY_FUNCTION__); } if (result == -1) { // error int e = errno; if ((e != EAGAIN) && (e != EINTR)) // only retry of interrupted or repeatable break; } } while (result == -1); #endif if (result == 1) { // data waiting, try to read if (enableDescLogging) NSLog(@"receiving data ..."); result = recv(_fd, _buf, _len, _flags); if (result == 0) return 0; // EOF else if (result == -1) { errorCode = errno; if (errorCode == EWOULDBLOCK) NSLog(@"WARNING: would block although descriptor was polled .."); } } else if (result == 0) { if (enableDescLogging) { NSLog(@"nonblock: recv on %i timed out after %i milliseconds ..", _fd, _timeout); } result = -2; } else result = -1; } return result; } int NGDescriptorSend (int _fd, const char *_buf, int _len, int _flags, int _timeout) { int errorCode; int result; result = send(_fd, _buf, _len, _flags); if (result == 0) return 0; // EOF errorCode = errno; if ((result == -1) && (errorCode == EWOULDBLOCK)) { // retry #if HAVE_POLL struct pollfd pfd; pfd.fd = _fd; pfd.events = POLLWRNORM; pfd.revents = 0; do { if ((result = poll(&pfd, 1, _timeout)) < 0) { errorCode = errno; if (errorCode == 0) { NSLog(@"%s: errno is 0, but return value of poll is <0 (%i) (retry) ?!", __PRETTY_FUNCTION__, result); continue; } if (errorCode != EINTR) // retry only if interrupted break; } } while (result < 0); #else struct timeval timeout; fd_set rSet; fd_set wSet; fd_set eSet; FD_ZERO(&rSet); FD_ZERO(&wSet); FD_ZERO(&eSet); FD_SET(_fd, &wSet); timeout.tv_sec = _timeout / 1000; timeout.tv_usec = _timeout * 1000 - timeout.tv_sec * 1000000; do { result = select(FD_SETSIZE, &rSet, &wSet, &eSet, &timeout); if (result == -1) { // error int e = errno; if ((e != EAGAIN) && (e != EINTR)) // only retry of interrupted or repeatable break; } } while (result == -1); #endif if (result == 1) { // data waiting, try to read result = send(_fd, _buf, _len, _flags); if (result == 0) return 0; // EOF } else if (result == 0) { NSLog(@"nonblock: send on %i timed out after %i milliseconds ..", _fd, _timeout); result = -2; } else result = -1; } return result; } // ******************** TTY ********************* /* Check whether the descriptor is associated to a terminal device. Get the name of the associated terminal device. */ BOOL NGDescriptorIsAtty(int _fd) { #if HAVE_ISATTY return isatty(_fd) == 1 ? YES : NO; #else return NO; #endif } NSString *NGDescriptorGetTtyName(int _fd) { #if HAVE_ISATTY if (isatty(_fd) != 1) // not connected to a terminal device ? return nil; #endif { #if HAVE_TTYNAME_R # ifndef sparc extern int ttyname_r(int, char*, size_t); # endif # ifdef _POSIX_PATH_MAX char namebuffer[_POSIX_PATH_MAX + 128]; # else char namebuffer[4096]; # endif if (ttyname_r(_fd, namebuffer, sizeof(namebuffer))) return [NSString stringWithCString:namebuffer]; #elif HAVE_TTYNAME char *result = NULL; NSString *str = nil; int errCode = 0; [systemLock lock]; { result = ttyname(_fd); errCode = errno; if (result) str = [NSString stringWithCString:result]; } [systemLock unlock]; if (str) return str; #endif } return nil; } #endif // WIN32 SOPE/sope-core/NGStreams/NGGZipStream.m0000644000000000000000000001256115004363604016517 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "common.h" #ifdef Assert #undef Assert #endif #include #ifndef DEF_MEM_LEVEL /* zutil.h */ # if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 # else # define DEF_MEM_LEVEL MAX_MEM_LEVEL # endif # define OS_CODE 0x07 /* TODO: probably need to adjust that ... */ #endif #undef Assert @implementation NGGZipStream - (id)initWithSource:(id)_source level:(int)_level { if ((self = [super initWithSource:_source])) { z_stream *zout; NSAssert1((_level >= NGGZipMinimalCompression && _level <= NGGZipMaximalCompression) || (_level == Z_DEFAULT_COMPRESSION), @"invalid compression level %i (0-9)", _level); self->outBufLen = 2048; #if LIB_FOUNDATION_LIBRARY self->outBuf = NSZoneMallocAtomic([self zone], self->outBufLen); self->outp = NSZoneMallocAtomic([self zone], sizeof(z_stream)); #else self->outBuf = NSZoneMalloc([self zone], self->outBufLen); self->outp = NSZoneMalloc([self zone], sizeof(z_stream)); #endif zout = self->outp; zout->zalloc = (alloc_func)NULL; zout->zfree = (free_func)NULL; zout->opaque = (voidpf)NULL; zout->next_out = self->outBuf; zout->avail_out = self->outBufLen; zout->next_in = Z_NULL; zout->avail_in = 0; self->crc = crc32(0L, Z_NULL, 0); if (deflateInit2(zout, _level, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0) != Z_OK) { NSLog(@"Could not init deflate .."); self = [self autorelease]; return nil; } } return self; } - (void)gcFinalize { [self close]; } - (void)dealloc { if (self->outBuf) NSZoneFree([self zone], self->outBuf); if (self->outp) NSZoneFree([self zone], self->outp); [self gcFinalize]; [super dealloc]; } /* headers */ - (void)writeGZipHeader { // gzip header char buf[10] = { 0x1f, 0x8b, // magic Z_DEFLATED, 0, // flags 0, 0, 0, 0, // time 0, OS_CODE // flags }; [self safeWriteBytes:buf count:10]; } static inline void putLong(NGGZipStream *self, uLong x) { int n; for (n = 0; n < 4; n++) { unsigned char c = (int)(x & 0xff); [self safeWriteBytes:&c count:1]; x >>= 8; } } - (void)writeGZipTrailer { putLong(self, self->crc); putLong(self, ((z_stream *)self->outp)->total_in); } /* primitives */ - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { // decoder [self notImplemented:_cmd]; return -1; } - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len { // encoder z_stream *zout = self->outp; if (!self->headerIsWritten) [self writeGZipHeader]; { // gz_write zout->next_in = (void*)_buf; zout->avail_in = _len; while (zout->avail_in > 0) { int errorCode; if (zout->avail_out == 0) { [self safeWriteBytes:self->outBuf count:self->outBufLen]; zout->next_out = self->outBuf; // reset buffer position zout->avail_out = self->outBufLen; } errorCode = deflate(self->outp, Z_NO_FLUSH); if (errorCode != Z_OK) { if (zout->state) deflateEnd(self->outp); [NGStreamException raiseWithStream:self format:@"could not deflate chunk !"]; } } self->crc = crc32(self->crc, _buf, _len); } return _len; } - (BOOL)safeWriteBytes:(const void *)_buf count:(unsigned)_len { // encoder // gzip writes are safe if ([self writeBytes:_buf count:_len] == NGStreamError) return NO; else return YES; } - (void)close { [self flush]; [self writeGZipTrailer]; if (((z_stream *)self->outp)->state) deflateEnd(self->outp); [super close]; } - (void)flush { int errorCode = Z_OK; z_stream *zout = self->outp; BOOL done = NO; zout->next_in = NULL; zout->avail_in = 0; // should be zero already anyway while (1) { int len = self->outBufLen - zout->avail_out; if (len > 0) { [self safeWriteBytes:self->outBuf count:len]; zout->next_out = self->outBuf; zout->avail_out = self->outBufLen; } if (done) break; errorCode = deflate(zout, Z_FINISH); // deflate has finished flushing only when it hasn't used up // all the available space in the output buffer: done = (zout->avail_out != 0 || errorCode == Z_STREAM_END); if (errorCode != Z_OK && errorCode != Z_STREAM_END) break; } if (errorCode != Z_STREAM_END) { if (zout->state) deflateEnd(zout); [NGStreamException raiseWithStream:self format:@"flush failed"]; } [super flush]; } @end SOPE/sope-core/NGStreams/NGFileStream.m0000644000000000000000000004212215004363604016521 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" #if HAVE_UNISTD_H || __APPLE__ # include #endif #if HAVE_SYS_STAT_H # include #endif #if HAVE_SYS_FCNTL_H # include #endif #if HAVE_FCNTL_H || __APPLE__ # include #endif #include #include #include #include #include #include #include "common.h" #import #if !defined(POLLRDNORM) # define POLLRDNORM POLLIN #endif // TODO: NGFileStream needs to be changed to operate without throwing // exceptions NGStreams_DECLARE NSString *NGFileReadOnly = @"r"; NGStreams_DECLARE NSString *NGFileWriteOnly = @"w"; NGStreams_DECLARE NSString *NGFileReadWrite = @"rw"; NGStreams_DECLARE NSString *NGFileAppend = @"a"; NGStreams_DECLARE NSString *NGFileReadAppend = @"ra"; static const int NGInvalidUnixDescriptor = -1; static const int NGFileCreationMask = 0666; // rw-rw-rw- @interface _NGConcreteFileStreamFileHandle : NGConcreteStreamFileHandle @end NGStreams_DECLARE id NGIn = nil; NGStreams_DECLARE id NGOut = nil; NGStreams_DECLARE id NGErr = nil; @implementation NGFileStream // stdio stream #if defined(__MINGW32__) - (id)__initWithInConsole { if ((self = [self init])) { self->systemPath = @"CONIN$"; self->streamMode = NGStreamMode_readWrite; self->fh = GetStdHandle(STD_INPUT_HANDLE); /* self->fh = CreateFile("CONIN$", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); */ } return self; } - (id)__initWithOutConsole { if ((self = [self init])) { DWORD written; self->systemPath = @"CONOUT$"; self->streamMode = NGStreamMode_readWrite; self->fh = GetStdHandle(STD_OUTPUT_HANDLE); /* self->fh = CreateFile("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); */ FlushFileBuffers(self->fh); } return self; } #else - (id)__initWithDescriptor:(int)_fd mode:(NGStreamMode)_mode { if ((self = [self init])) { self->fd = _fd; self->streamMode = _mode; } return self; } #endif void NGInitStdio(void) { static BOOL isInitialized = NO; if (!isInitialized) { NGFileStream *ti = nil, *to = nil, *te = nil; isInitialized = YES; #if defined(__MINGW32__) ti = [[NGFileStream alloc] __initWithInConsole]; to = [[NGFileStream alloc] __initWithOutConsole]; te = [to retain]; #else ti = [[NGFileStream alloc] __initWithDescriptor:0 mode:NGStreamMode_readOnly]; to = [[NGFileStream alloc] __initWithDescriptor:1 mode:NGStreamMode_writeOnly]; te = [[NGFileStream alloc] __initWithDescriptor:2 mode:NGStreamMode_writeOnly]; #endif NGIn = [[NGBufferedStream alloc] initWithSource:(id)ti]; NGOut = [[NGBufferedStream alloc] initWithSource:(id)to]; NGErr = [[NGBufferedStream alloc] initWithSource:(id)te]; [ti release]; ti = nil; [to release]; to = nil; [te release]; te = nil; } } + (void)_makeThreadSafe:(NSNotification *)_notification { NGLockingStream *li = nil, *lo = nil, *le = nil; if ([NGIn isKindOfClass:[NGLockingStream class]]) return; li = [[NGLockingStream alloc] initWithSource:(id)NGIn]; [NGIn release]; NGIn = li; lo = [[NGLockingStream alloc] initWithSource:(id)NGOut]; [NGOut release]; NGOut = lo; le = [[NGLockingStream alloc] initWithSource:(id)NGErr]; [NGErr release]; NGErr = le; } + (void)_flushForExit:(NSNotification *)_notification { //[NGIn flush]; [NGOut flush]; [NGErr flush]; } static void _flushForExit(void) { //[NGIn flush]; [NGOut flush]; [NGErr flush]; } + (void)initialize { BOOL isInitialized = NO; if (!isInitialized) { isInitialized = YES; if ([NSThread isMultiThreaded]) [self _makeThreadSafe:nil]; else { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_makeThreadSafe:) name:NSWillBecomeMultiThreadedNotification object:nil]; } atexit(_flushForExit); } } /* normal file stream */ - (id)init { if ((self = [super init])) { self->streamMode = NGStreamMode_undefined; self->systemPath = nil; self->markDelta = -1; self->handle = nil; #if defined(__MINGW32__) self->fh = INVALID_HANDLE_VALUE; #else self->fd = NGInvalidUnixDescriptor; #endif } return self; } - (id)initWithPath:(NSString *)_path { if ((self = [self init])) { self->systemPath = [_path copy]; } return self; } - (id)initWithFileHandle:(NSFileHandle *)_handle { if ((self = [self init])) { #if defined(__MINGW32__) self->fh = [_handle nativeHandle]; #else self->fd = [_handle fileDescriptor]; #endif } return self; } - (void)gcFinalize { if ([self isOpen]) { #if DEBUG && 0 NSLog(@"NGFileStream(gcFinalize): closing %@", self); #endif [self close]; } } - (void)dealloc { [self gcFinalize]; self->streamMode = NGStreamMode_undefined; [self->systemPath release]; self->systemPath = nil; self->handle = nil; [super dealloc]; } // opening - (BOOL)openInMode:(NSString *)_mode { // throws // NGUnknownStreamModeException when _mode is invalid // NGCouldNotOpenStreamException when the file could not be opened #if defined(__MINGW32__) DWORD openFlags; DWORD shareMode; if (self->fh != INVALID_HANDLE_VALUE) [self close]; // if stream is open, close and reopen if ([_mode isEqualToString:NGFileReadOnly]) { self->streamMode = NGStreamMode_readOnly; openFlags = GENERIC_READ; shareMode = FILE_SHARE_READ; } else if ([_mode isEqualToString:NGFileWriteOnly]) { self->streamMode = NGStreamMode_writeOnly; openFlags = GENERIC_WRITE; shareMode = FILE_SHARE_WRITE; } else if ([_mode isEqualToString:NGFileReadWrite]) { self->streamMode = NGStreamMode_readWrite; openFlags = GENERIC_READ | GENERIC_WRITE; shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; } else { [[[NGUnknownStreamModeException alloc] initWithStream:self mode:_mode] raise]; return NO; } self->fh = CreateFile([self->systemPath fileSystemRepresentation], openFlags, shareMode, NULL, OPEN_ALWAYS, // same as the Unix O_CREAT flag 0, // security flags ? NULL); if (self->fh == INVALID_HANDLE_VALUE) [NGCouldNotOpenStreamException raiseWithStream:self]; #else int openFlags; // flags passed to open() call if (self->fd != NGInvalidUnixDescriptor) [self close]; // if stream is open, close and reopen if ([_mode isEqualToString:NGFileReadOnly]) { self->streamMode = NGStreamMode_readOnly; openFlags = O_RDONLY; } else if ([_mode isEqualToString:NGFileWriteOnly]) { self->streamMode = NGStreamMode_writeOnly; openFlags = O_WRONLY | O_CREAT; } else if ([_mode isEqualToString:NGFileReadWrite]) { self->streamMode = NGStreamMode_readWrite; openFlags = O_RDWR | O_CREAT; } else if ([_mode isEqualToString:NGFileAppend]) { self->streamMode = NGStreamMode_writeOnly; openFlags = O_WRONLY | O_CREAT | O_APPEND; } else if ([_mode isEqualToString:NGFileReadAppend]) { self->streamMode = NGStreamMode_readWrite; openFlags = O_RDWR | O_CREAT | O_APPEND; } else { [[[NGUnknownStreamModeException alloc] initWithStream:self mode:_mode] raise]; return NO; } self->fd = open([self->systemPath fileSystemRepresentation], openFlags, NGFileCreationMask); if (self->fd == -1) { self->fd = NGInvalidUnixDescriptor; [NGCouldNotOpenStreamException raiseWithStream:self]; return NO; } #endif self->markDelta = -1; // not marked return YES; } - (BOOL)isOpen { #if defined(__MINGW32__) return (self->fh != INVALID_HANDLE_VALUE) ? YES : NO; #else return (self->fd != NGInvalidUnixDescriptor) ? YES : NO; #endif } // Foundation file handles - (void)resetFileHandle { // called by NSFileHandle on dealloc self->handle = nil; } - (NSFileHandle *)fileHandle { if (self->handle == nil) self->handle = [[_NGConcreteFileStreamFileHandle allocWithZone:[self zone]] initWithStream:self]; return [self->handle autorelease]; } #if defined(__MINGW32__) - (HANDLE)windowsFileHandle { return self->fh; } #endif - (int)fileDescriptor { #if defined(__MINGW32__) return (int)[self fileHandle]; #else return self->fd; #endif } // primitives static void _checkOpen(NGFileStream *self, NSString *_reason) { #if defined(__MINGW32__) if (self->fh == INVALID_HANDLE_VALUE) [NGStreamNotOpenException raiseWithStream:self reason:_reason]; #else if (self->fd == NGInvalidUnixDescriptor) [NGStreamNotOpenException raiseWithStream:self reason:_reason]; #endif } - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { // throws // NGWriteOnlyStreamException when the stream is not readable // NGStreamNotOpenException when the stream is not open // NGEndOfStreamException when the end of the stream is reached // NGStreamReadErrorException when the read call failed _checkOpen(self, @"tried to read from a file stream which is closed"); if (!NGCanReadInStreamMode(streamMode)) [NGWriteOnlyStreamException raiseWithStream:self]; { #if defined(__MINGW32__) DWORD readResult = 0; if (ReadFile(self->fh, _buf, _len, &readResult, NULL) == FALSE) { DWORD lastErr = GetLastError(); if (lastErr == ERROR_HANDLE_EOF) [NGEndOfStreamException raiseWithStream:self]; else [NGStreamReadErrorException raiseWithStream:self errorCode:lastErr]; } if (readResult == 0) [NGEndOfStreamException raiseWithStream:self]; #else int readResult; int retryCount = 0; do { readResult = read(self->fd, _buf, _len); if (readResult == 0) [NGEndOfStreamException raiseWithStream:self]; else if (readResult == -1) { int errCode = errno; if (errCode == EINTR) // system call was interrupted retryCount++; else [NGStreamReadErrorException raiseWithStream:self errorCode:errCode]; } } while ((readResult <= 0) && (retryCount < 10)); if (retryCount >= 10) [NGStreamReadErrorException raiseWithStream:self errorCode:EINTR]; #endif NSAssert(readResult > 0, @"invalid read method state"); // adjust mark if (self->markDelta != -1) self->markDelta += readResult; // increase delta return readResult; } } - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len { // throws // NGReadOnlyStreamException when the stream is not writeable // NGStreamNotOpenException when the stream is not open // NGStreamWriteErrorException when the write call failed _checkOpen(self, @"tried to write to a file stream which is closed"); if (!NGCanWriteInStreamMode(streamMode)) [NGReadOnlyStreamException raiseWithStream:self]; { #if defined(__MINGW32__) DWORD writeResult = 0; if (WriteFile(self->fh, _buf, _len, &writeResult, NULL) == FALSE) { DWORD errorCode = GetLastError(); switch (errorCode) { case ERROR_INVALID_HANDLE: [NGStreamWriteErrorException raiseWithStream:self reason:@"incorrect file handle"]; break; case ERROR_WRITE_PROTECT: [NGStreamWriteErrorException raiseWithStream:self reason:@"disk write protected"]; break; case ERROR_NOT_READY: [NGStreamWriteErrorException raiseWithStream:self reason:@"the drive is not ready"]; break; case ERROR_HANDLE_EOF: [NGStreamWriteErrorException raiseWithStream:self reason:@"reached end of file"]; break; case ERROR_DISK_FULL: [NGStreamWriteErrorException raiseWithStream:self reason:@"disk is full"]; break; default: [NGStreamWriteErrorException raiseWithStream:self errorCode:GetLastError()]; } NSLog(@"invalid program state, aborting"); abort(); } #else int writeResult; int retryCount = 0; do { writeResult = write(self->fd, _buf, _len); if (writeResult == -1) { int errCode = errno; if (errCode == EINTR) // system call was interrupted retryCount++; else [NGStreamWriteErrorException raiseWithStream:self errorCode:errno]; } } while ((writeResult == -1) && (retryCount < 10)); if (retryCount >= 10) [NGStreamWriteErrorException raiseWithStream:self errorCode:EINTR]; #endif return writeResult; } } - (BOOL)close { #if defined(__MINGW32__) if (self->fh == INVALID_HANDLE_VALUE) { NSLog(@"tried to close already closed stream %@", self); return YES; /* not signaled as an error .. */ } if (CloseHandle(self->fh) == FALSE) { [NGCouldNotCloseStreamException raiseWithStream:self]; return NO; } self->fh = INVALID_HANDLE_VALUE; #else if (self->fd == NGInvalidUnixDescriptor) { NSLog(@"tried to close already closed stream %@", self); return YES; /* not signaled as an error .. */ } if (close(self->fd) != 0) { [NGCouldNotCloseStreamException raiseWithStream:self]; return NO; } self->fd = NGInvalidUnixDescriptor; #endif self->markDelta = -1; return YES; } - (NGStreamMode)mode { return self->streamMode; } - (BOOL)isRootStream { return YES; } #if defined(__MINGW32__) - (BOOL)flush { if (self->fh != INVALID_HANDLE_VALUE) FlushFileBuffers(self->fh); return YES; } #endif // blocking #if defined(__MINGW32__) - (BOOL)wouldBlockInMode:(NGStreamMode)_mode { NSLog(@"%@ not supported in Windows environment !", NSStringFromSelector(_cmd)); return YES; } #else - (BOOL)wouldBlockInMode:(NGStreamMode)_mode { short events = 0; if (self->fd == NGInvalidUnixDescriptor) return NO; if (NGCanReadInStreamMode(_mode)) events |= POLLRDNORM; if (NGCanWriteInStreamMode(_mode)) events |= POLLWRNORM; // timeout of 0 means return immediatly return (NGPollDescriptor(self->fd, events, 0) == 1 ? NO : YES); } #endif // marking - (BOOL)mark { self->markDelta = 0; return YES; } - (BOOL)rewind { if (![self moveByOffset:-(self->markDelta)]) return NO; self->markDelta = -1; return YES; } - (BOOL)markSupported { return YES; } // NGPositionableStream - (BOOL)moveToLocation:(unsigned)_location { self->markDelta = -1; #if defined(__MINGW32__) if (SetFilePointer(self->fh, _location, NULL, FILE_BEGIN) == -1) { [NGStreamSeekErrorException raiseWithStream:self errorCode:GetLastError()]; return NO; } #else if (lseek(self->fd, _location, SEEK_SET) == -1) { [NGStreamSeekErrorException raiseWithStream:self errorCode:errno]; return NO; } #endif return YES; } - (BOOL)moveByOffset:(int)_delta { self->markDelta += _delta; #if defined(__MINGW32__) if (SetFilePointer(self->fh, _delta, NULL, FILE_CURRENT) == -1) { [NGStreamSeekErrorException raiseWithStream:self errorCode:GetLastError()]; return NO; } #else if (lseek(self->fd, _delta, SEEK_CUR) == -1) { [NGStreamSeekErrorException raiseWithStream:self errorCode:errno]; return NO; } #endif return YES; } /* description */ - (NSString *)description { return [NSString stringWithFormat: @"<%@[0x%p] path=%@ mode=%@>", NSStringFromClass([self class]), self, self->systemPath ? self->systemPath : (NSString *)@"nil", [self modeDescription]]; } @end /* NGFileStream */ @implementation _NGConcreteFileStreamFileHandle // accessors #if defined(__MINGW32__) - (HANDLE)fileHandle { return [(NGFileStream *)stream windowsFileHandle]; } #endif - (int)fileDescriptor { return [(NGFileStream *)stream fileDescriptor]; } @end SOPE/sope-core/NGStreams/NGCharBuffer.m0000644000000000000000000001144415004363604016500 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGCharBuffer.h" #include "common.h" typedef struct NGCharBufferLA { unichar character; char isEOF:1; char isFetched:1; } LA_NGCharBuffer; @implementation NGCharBuffer + (id)charBufferWithSource:(id)_source la:(int)_la { return [[[self alloc] initWithSource:_source la:_la] autorelease]; } - (id)initWithSource:(id)_source la:(int)_la { if ((self = [super initWithSource:_source])) { int size = 0; if (_la < 1) { [NSException raise:NSRangeException format:@"lookahead depth is less than one (%d)", _la]; } // Find first power of 2 >= to requested size for (size = 2; size < _la; size *=2); #if LIB_FOUNDATION_LIBRARY self->la = NSZoneMallocAtomic([self zone], sizeof(LA_NGCharBuffer) * size); #else self->la = NSZoneMalloc([self zone], sizeof(LA_NGCharBuffer) * size); #endif memset(self->la, 0, sizeof(LA_NGCharBuffer) * size); self->bufLen = size; self->sizeLessOne = self->bufLen - 1; self->headIdx = 0; self->wasEOF = NO; if ([self->source respondsToSelector:@selector(methodForSelector:)]) { self->readCharacter = (unichar (*)(id, SEL)) [(NSObject *)self->source methodForSelector:@selector(readCharacter)]; } } return self; } - (id)initWithSource:(id)_source { [self release]; [self doesNotRecognizeSelector:_cmd]; return nil; } - (id)init { [self release]; [self doesNotRecognizeSelector:_cmd]; return nil; } #if !LIB_FOUNDATION_BOEHM_GC - (void)dealloc { NSZoneFree([self zone], self->la); self->readCharacter = NULL; [super dealloc]; } #endif - (unichar)readCharacter { int character = [self la:0]; if (character < 1) [[[NGEndOfStreamException alloc] init] raise]; [self consume]; return character; } /* LA */ - (int)la:(int)_la { int result = -1; int idx = (_la + self->headIdx) & self->sizeLessOne; idx = *(&idx); if (_la > self->sizeLessOne) { [NSException raise:NSRangeException format:@"tried to look ahead too far (la=%d, max=%d)", _la, self->bufLen]; } if (self->wasEOF) { result = (!self->la[idx].isFetched || self->la[idx].isEOF) ? -1 : self->la[idx].character; } else { if (!self->la[idx].isFetched) { int i; *(&i) = 0; while ((i < _la) && (self->la[(self->headIdx + i) & self->sizeLessOne].isFetched)) i++; NS_DURING { while (i <= _la) { int ix = 0; unichar character = 0; if (self->readCharacter == NULL) character = [self->source readCharacter]; else { character = self->readCharacter(self->source, @selector(readCharacter)); } ix = (self->headIdx + i) & self->sizeLessOne; self->la[ix].character = character; self->la[ix].isFetched = 1; i++; } } NS_HANDLER { if ([localException isKindOfClass:[NGEndOfStreamException class]]) { while (i <= _la) { self->la[(self->headIdx + i) & self->sizeLessOne].isEOF = YES; i++; self->wasEOF = YES; } } else { [localException raise]; } } NS_ENDHANDLER; } result = (self->la[idx].isEOF) ? -1 : self->la[idx].character; } return result; } - (void)consume { int idx = self->headIdx & sizeLessOne; if (!(self->la[idx].isFetched)) [self la:0]; self->la[idx].isFetched = 0; self->headIdx++; } - (void)consume:(int)_cnt { while (_cnt > 0) { int idx = self->headIdx & sizeLessOne; if (!(self->la[idx].isFetched)) [self la:0]; self->la[idx].isFetched = 0; self->headIdx++; _cnt--; } } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"<%@[0x%p] source=%@ la=%d", NSStringFromClass([self class]), self, self->source, self->bufLen]; } @end /* NGCharBuffer */ SOPE/sope-core/NGStreams/NGDataStream.m0000644000000000000000000001740415004363604016520 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "common.h" // TODO: cache -bytes and -length of NSData for immutable data! @implementation NGDataStream + (id)dataStream { return [self streamWithData:[NSMutableData dataWithCapacity:1024]]; } + (id)dataStreamWithCapacity:(int)_capacity { return [self streamWithData:[NSMutableData dataWithCapacity:_capacity]]; } + (id)streamWithData:(NSData *)_data { return [[[self alloc] initWithData:_data] autorelease]; } - (id)initWithData:(NSData *)_data mode:(NGStreamMode)_mode { if ((self = [super init])) { self->data = [_data retain]; self->position = 0; if ([self->data respondsToSelector:@selector(methodForSelector:)] == YES) { self->dataLength = (unsigned int(*)(id, SEL)) [self->data methodForSelector:@selector(length)]; self->dataBytes = (const void*(*)(id, SEL)) [self->data methodForSelector:@selector(bytes)]; } else { self->dataLength = NULL; self->dataBytes = NULL; } self->streamMode = _mode; /* for read-only streams */ if (self->streamMode == NGStreamMode_readOnly) { self->bytes = [self->data bytes]; self->length = [self->data length]; } } return self; } - (id)initWithData:(NSData *)_data { NGStreamMode smode; smode = [data isKindOfClass:[NSMutableData class]] ? NGStreamMode_readWrite : NGStreamMode_readOnly; return [self initWithData:_data mode:smode]; } - (void)dealloc { [self->data release]; [self->lastException release]; [super dealloc]; } /* accessors */ /* NGTextInputStream */ - (NSException *)lastException { return self->lastException; } - (void)setLastException:(NSException *)_exception { ASSIGN(self->lastException, _exception); } - (void)resetLastException { [self->lastException release]; self->lastException = nil; } - (NSData *)data { return self->data; } - (unsigned)availableBytes { // returns number of available bytes register unsigned currentLength = 0; if (self->bytes == NULL) { currentLength = (self->dataLength == NULL) ? [self->data length] : self->dataLength(self->data, @selector(length)); } else currentLength = self->length; return (currentLength == position) ? 0 : (currentLength - position); } /* primitives */ - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { // throws // NGStreamNotOpenException when the stream is not open // NGEndOfStreamException when the end of the stream is reached register unsigned currentLength = 0; if (self->bytes == NULL) { currentLength = (self->dataLength == NULL) ? [self->data length] : self->dataLength(self->data, @selector(length)); } else currentLength = self->length; if (self->data == nil) { NSException *e; e = [NGStreamNotOpenException exceptionWithStream:self reason: @"tried to read from a data stream " @"which was closed"]; [self setLastException:e]; return NGStreamError; } if (currentLength == position) { [self setLastException: [NGEndOfStreamException exceptionWithStream:self]]; return NGStreamError; } { NSRange range; range.location = position; if ((position + _len) > currentLength) range.length = currentLength - position; else range.length = _len; [self->data getBytes:_buf range:range]; position += range.length; return range.length; } } - (int)readByte { register const unsigned char *p; register unsigned int currentLength = 0; int result = 0; if (self->bytes == NULL) { currentLength = (self->dataLength == NULL) ? [self->data length] : self->dataLength(self->data, @selector(length)); } else currentLength = self->length; if (currentLength == position) return -1; if (self->bytes == NULL) { p = (self->dataBytes == NULL) ? [self->data bytes] : self->dataBytes(self->data, @selector(bytes)); } else p = self->bytes; result = p[self->position]; self->position++; return result; } - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len { // throws // NGReadOnlyStreamException when the stream is not writeable // NGStreamNotOpenException when the stream is not open if (self->data == nil) { NSException *e; e = [NGStreamNotOpenException exceptionWithStream:self reason: @"tried to write to a data stream " @"which was closed"]; [self setLastException:e]; return NGStreamError; } if (!NGCanWriteInStreamMode(streamMode)) { NSException *e; e = [NGReadOnlyStreamException exceptionWithStream:self]; [self setLastException:e]; return NGStreamError; } [(NSMutableData *)self->data appendBytes:_buf length:_len]; return _len; } - (BOOL)close { ASSIGN(self->lastException, (id)nil); [self->data release]; self->data = nil; position = 0; streamMode = NGStreamMode_undefined; return YES; } - (NGStreamMode)mode { return streamMode; } - (BOOL)isRootStream { return YES; } // NGPositionableStream - (BOOL)moveToLocation:(unsigned)_location { position = _location; return YES; } - (BOOL)moveByOffset:(int)_delta { position += _delta; return YES; } /* blocking .. */ - (BOOL)wouldBlockInMode:(NGStreamMode)_mode { return NO; } - (id)retain { return [super retain]; } /* bytebuffer / lookahead API */ - (int)la:(unsigned)_la { register unsigned int currentLength, newpos; register const unsigned char *p; int result = 0; if (self->bytes == NULL) { currentLength = (self->dataLength == NULL) ? [self->data length] : self->dataLength(self->data, @selector(length)); } else currentLength = self->length; if (currentLength == self->position) // already at EOF return -1; newpos = (self->position + _la); if (newpos >= currentLength) return -1; /* a look into EOF */ if (self->bytes == NULL) { p = (self->dataBytes == NULL) ? [self->data bytes] : self->dataBytes(self->data, @selector(bytes)); } else p = self->bytes; result = p[newpos]; return result; } - (void)consume { // consume one byte register unsigned int currentLength = 0; if (self->bytes == NULL) { currentLength = (self->dataLength == NULL) ? [self->data length] : self->dataLength(self->data, @selector(length)); } else currentLength = self->length; if (currentLength == self->position) return; self->position++; // consume } - (void)consume:(unsigned)_cnt { // consume _cnt bytes register unsigned int currentLength = 0; if (self->bytes == NULL) { currentLength = (self->dataLength == NULL) ? [self->data length] : self->dataLength(self->data, @selector(length)); } else currentLength = self->length; if (currentLength == self->position) return; self->position += _cnt; // consume if (self->position > currentLength) self->position = currentLength; } @end /* NGDataStream */ SOPE/sope-core/NGStreams/NGCTextStream.m0000644000000000000000000002377215004363604016703 0ustar rootroot/* Copyright (C) 2000-2008 SKYRIX Software AG Copyright (C) 2007-2008 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include "common.h" static NSString *NGNewLineString = @"\n"; @interface _NGCTextStreamLineEnumerator : NSEnumerator { NGCTextStream *stream; } - (id)initWithTextStream:(NGCTextStream *)_stream; - (id)nextObject; @end NGStreams_DECLARE id NGTextIn = nil; NGStreams_DECLARE id NGTextOut = nil; NGStreams_DECLARE id NGTextErr = nil; @implementation NGCTextStream // stdio NGStreams_DECLARE void NGInitTextStdio(void) { static BOOL isInitialized = NO; if (!isInitialized) { isInitialized = YES; NGInitStdio(); NGTextIn = [(NGCTextStream *)[NGCTextStream alloc] initWithSource:(id)NGIn]; NGTextOut = [(NGCTextStream *)[NGCTextStream alloc] initWithSource:(id)NGOut]; NGTextErr = [(NGCTextStream *)[NGCTextStream alloc] initWithSource:(id)NGErr]; } } + (void)_flushForExit:(NSNotification *)_notification { // [NGTextIn flush]; [NGTextIn release]; NGTextIn = nil; [NGTextOut flush]; [NGTextOut release]; NGTextOut = nil; [NGTextErr flush]; [NGTextErr release]; NGTextErr = nil; } static void _flushAtExit(void) { // [NGTextIn flush]; [NGTextIn release]; NGTextIn = nil; [NGTextOut flush]; [NGTextOut release]; NGTextOut = nil; [NGTextErr flush]; [NGTextErr release]; NGTextErr = nil; } + (void)initialize { BOOL isInitialized = NO; if (!isInitialized) { isInitialized = YES; atexit(_flushAtExit); } } // system text stream + (id)textStreamWithInputSource:(id)_s { if (_s == nil) return nil; return [[(NGCTextStream *)[self alloc] initWithInputSource:_s] autorelease]; } + (id)textStreamWithOutputSource:(id)_s { if (_s == nil) return nil; return [[(NGCTextStream *)[self alloc] initWithOutputSource:_s] autorelease]; } + (id)textStreamWithSource:(id)_stream { if (_stream == nil) return nil; return [[(NGCTextStream *)[self alloc] initWithSource:_stream] autorelease]; } - (id)initWithSource:(id)_stream { if (_stream == nil) { [self release]; return nil; } if ((self = [super init]) != nil) { self->source = [_stream retain]; /* On MacOS 10.5 this is per default 30 aka MacOS Roman */ self->encoding = [NSString defaultCStringEncoding]; #ifdef __APPLE__ //# warning no selector caching on MacOSX ... #else /* check whether we are dealing with a proxy .. */ if ([source isKindOfClass:[NSObject class]]) { self->readBytes = (NGIOReadMethodType) [(NSObject *)source methodForSelector:@selector(readBytes:count:)]; self->writeBytes = (NGIOWriteMethodType) [(NSObject *)source methodForSelector:@selector(writeBytes:count:)]; self->flushBuffer = (BOOL (*)(id,SEL)) [(NSObject *)source methodForSelector:@selector(flush)]; } #endif } return self; } - (id)initWithInputSource:(id)_source { return [self initWithSource:(id)_source]; } - (id)initWithOutputSource:(id)_source { return [self initWithSource:(id)_source]; } - (void)dealloc { [self->source release]; self->readBytes = NULL; self->writeBytes = NULL; self->flushBuffer = NULL; [super dealloc]; } /* accessors */ - (id)source { return self->source; } - (int)fileDescriptor { return [(id)[self source] fileDescriptor]; } - (BOOL)isOpen { return [(id)[self source] isOpen]; } /* operations */ - (BOOL)close { return [self->source close]; } /* NGTextInputStream */ - (unichar)readCharacter { return [self readChar]; } - (unsigned char)readChar { unsigned char c; unsigned res; if (readBytes) { res = readBytes(self->source, @selector(readBytes:count:), &c, sizeof(unsigned char)); } else res = [self->source readBytes:&c count:sizeof(unsigned char)]; if (res == NGStreamError) { [self setLastException:[self->source lastException]]; return -1; } return c; } /* TODO: fix exception handling */ - (NSString *)readLineAsString { NGCharBuffer8 buffer = NULL; unsigned char c; *(&buffer) = NGCharBuffer8_new(128); NS_DURING { unsigned int res; if (readBytes) { do { res = self->readBytes(source, @selector(readBytes:count:), &c, sizeof(unsigned char)); if (res != 1) [[self->source lastException] raise]; if (c == '\r') { res = readBytes(source, @selector(readBytes:count:), &c, sizeof(unsigned char)); if (res != 1) [[self->source lastException] raise]; } if ((c != '\n') && (c != 0)) { NSAssert1(c != 0, @"tried to add '0' character to buffer '%s' ..", buffer->buffer); NGCharBuffer8_addChar(buffer, c); } } while ((c != '\n') && (c != 0)); } else { do { res = [self->source readBytes:&c count:sizeof(unsigned char)]; /* TODO: raises exception */ if (res != 1) [[self->source lastException] raise]; if (c == '\r') { res = [self->source readBytes:&c count:sizeof(unsigned char)]; if (res != 1) [[self->source lastException] raise]; } if ((c != '\n') && (c != 0)) NGCharBuffer8_addChar(buffer, c); } while ((c != '\n') && (c != 0)); } } NS_HANDLER { if ([localException isKindOfClass:[NGEndOfStreamException class]]) { if (buffer->length == 0) { NGCharBuffer8_dealloc(buffer); buffer = NULL; } } else [localException raise]; } NS_ENDHANDLER; return buffer ? NGCharBuffer8_makeStringAndDealloc(buffer) : (NSString *)nil; } - (NSEnumerator *)lineEnumerator { return [[[_NGCTextStreamLineEnumerator alloc] initWithTextStream:self] autorelease]; } /* NGTextOutputStream */ - (BOOL)writeCharacter:(unichar)_character { unsigned char c; unsigned res; if (_character > ((sizeof(unsigned char) * 256) - 1)) { // character is not in range of maximum system encoding [NSException raise:@"NGCTextStreamEncodingException" format: @"called writeCharacter: with character code (0x%X)" @" exceeding the maximum system character code (0x%X)", _character, (int)((sizeof(unsigned char) * 256) - 1)]; } c = _character; if (self->writeBytes != NULL) { res = self->writeBytes(self->source, @selector(writeBytes:count:), &c, sizeof(unsigned char)); } else res = [self->source writeBytes:&c count:sizeof(unsigned char)]; if (res == NGStreamError) { [self setLastException:[self->source lastException]]; return NO; } return YES; } - (BOOL)writeString:(NSString *)_string { unsigned char *str, *buf; unsigned toGo; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 || (GNUSTEP && OS_API_VERSION(100400,GS_API_LATEST)) NSData *d; if ((toGo = [_string lengthOfBytesUsingEncoding:self->encoding]) == 0) return YES; d = [_string dataUsingEncoding: self->encoding allowLossyConversion: NO]; if (!d) { NSLog(@"ERROR(%s): failed to extract data using encoding(%i)" @" from NSString: '%@'\n", __PRETTY_FUNCTION__, self->encoding, _string); return NO; } buf = str = calloc(toGo + 1, sizeof(unsigned char)); [d getBytes: str length: toGo]; str[toGo] = '\0'; #else if ((toGo = [_string cStringLength]) == 0) return YES; buf = str = calloc(toGo + 2, sizeof(unsigned char)); [_string getCString:(char *)str]; str[toGo] = '\0'; #endif NS_DURING { while (toGo > 0) { unsigned writeCount; writeCount = writeBytes ? writeBytes(source, @selector(writeBytes:count:), str, toGo) : [source writeBytes:str count:toGo]; if (writeCount == NGStreamError) [[self->source lastException] raise]; toGo -= writeCount; str += writeCount; } } NS_HANDLER { if (buf != NULL) { free(buf); buf = NULL; }; [localException raise]; } NS_ENDHANDLER; if (buf) { free(buf); buf = NULL; } return YES; } - (BOOL)flush { if (flushBuffer) return flushBuffer(self->source, @selector(flush)); else return [self->source flush]; } - (BOOL)writeNewline { if (![self writeString:NGNewLineString]) return NO; if (![self flush]) return NO; return YES; } - (void) setEncoding: (NSStringEncoding) theEncoding { self->encoding = theEncoding; } @end /* NGCTextStream */ @implementation _NGCTextStreamLineEnumerator - (id)initWithTextStream:(NGCTextStream *)_stream { self->stream = [_stream retain]; return self; } - (void)dealloc { [self->stream release]; [super dealloc]; } - (id)nextObject { id result; *(&result) = nil; NS_DURING { result = [self->stream readLineAsString]; } NS_HANDLER { if ([localException isKindOfClass:[NGEndOfStreamException class]]) result = nil; else [localException raise]; } NS_ENDHANDLER; return result; } @end /* _NGCTextStreamLineEnumerator */ SOPE/sope-core/NGStreams/libNGStreams.def0000644000000000000000000000375315004363604017104 0ustar rootrootEXPORTS NGPollDescriptor; NGGetDescriptorFlags; NGSetDescriptorFlags; NGAddDescriptorFlag; NGDescriptorSend; NGDescriptorRecv; NGDescriptorIsAtty; NGDescriptorGetTtyName; __objc_class_name_NGBase64Stream; __objc_class_name_NGBufferedStream; __objc_class_name_NGByteBuffer; __objc_class_name_NGByteCountStream; __objc_class_name_NGCTextStream; __objc_class_name_NGCharBuffer; __objc_class_name_NGConcreteStreamFileHandle; __objc_class_name_NGCouldNotCloseStreamException; __objc_class_name_NGCouldNotOpenStreamException; __objc_class_name_NGDataStream; __objc_class_name_NGEndOfStreamException; __objc_class_name_NGFileStream; __objc_class_name_NGFilterStream; __objc_class_name_NGFilterTextStream; __objc_class_name_NGIOAccessException; __objc_class_name_NGIOException; __objc_class_name_NGIOSearchAccessException; __objc_class_name_NGLockingStream; __objc_class_name_NGReadOnlyStreamException; __objc_class_name_NGStream; __objc_class_name_NGStreamCoder; __objc_class_name_NGStreamErrorException; __objc_class_name_NGStreamException; __objc_class_name_NGStreamModeException; __objc_class_name_NGStreamNotOpenException; __objc_class_name_NGStreamPipe; __objc_class_name_NGStreamPipe; __objc_class_name_NGStreamReadErrorException; __objc_class_name_NGStreamSeekErrorException; __objc_class_name_NGStreamWriteErrorException; __objc_class_name_NGStreams; __objc_class_name_NGStringTextStream; __objc_class_name_NGTextStream; __objc_class_name_NGUnknownStreamModeException; __objc_class_name_NGWriteOnlyStreamException; __objc_class_name__NGCTextStreamLineEnumerator; __objc_class_name__NGConcreteFileStreamFileHandle; NGStreamSerializeObjC NGStreamDeserializeObjC NGReadByteFromStream NGSafeReadBytesFromStream NGSafeWriteBytesToStream NGFileReadOnly NGFileWriteOnly NGFileReadWrite NGFileAppend NGFileReadAppend NGIn NGOut NGErr NGTextIn NGTextOut NGTextErr NGInitStdio NGInitTextStdio ;__objc_class_name__NGConcretePipeFileHandle; ;__objc_class_name_NGTaskStream; SOPE/sope-core/NGStreams/configure.in0000644000000000000000000000524315004363604016377 0ustar rootrootAC_PREREQ(2.4) AC_INIT(NGStream.m) # Determine the host, build, and target systems CC_TARGET=$target # use --target value for CC, not the canonical form AC_CANONICAL_SYSTEM AC_CONFIG_HEADER(config.h:config.h.in) AC_PREFIX_DEFAULT(/usr/local) # check for cross compilation if test "x$target" = "xNONE"; then set target $host fi if test "x$host" != "x$target"; then cross_defines="CROSS=-DCROSS_COMPILE" cross_compiling="yes" echo "cross compiling from $host to $target .." AC_CHECK_PROG(CC, "${CC_TARGET}-gcc", "${CC_TARGET}-gcc", gcc) AC_CHECK_PROG(RANLIB, "${CC_TARGET}-ranlib", "${CC_TARGET}-ranlib", ranlib) AC_CHECK_PROG(AR, "${CC_TARGET}-ar", "${CC_TARGET}-ar", ar) AC_CHECK_PROG(DLLTOOL, "${CC_TARGET}-dlltool", "${CC_TARGET}-dlltool", dlltool) CC=${CC_TARGET}-gcc LD=${CC_TARGET}-ld AR=${CC_TARGET}-ar RANLIB=${CC_TARGET}-ranlib else AC_CHECK_PROG(CC, "gcc", "gcc", gcc) AC_CHECK_PROG(RANLIB, "ranlib", "ranlib", ranlib) AC_CHECK_PROG(AR, "ar", "ar", ar) AC_CHECK_PROG(DLLTOOL, "dlltool", "dlltool", dlltool) fi changequote(,)dnl case "${host_cpu}" in i[45]86*) host_cpu=i386;; hppa1.1) host_cpu=hppa;; esac if test "x$cross_compiling" = "xyes"; then case "${target_cpu}" in i[45]86*) target_cpu=i386;; hppa1.1) target_cpu=hppa;; esac else target_cpu=${host_cpu} target_os=${host_os} target_vendor=${host_vendor} fi case "x${target_os}" in xfreebsd*) target_os=freebsd;; esac changequote([,])dnl # Assign the HOST variables for sharedlib.mak HOST=$host HOST_CPU=$host_cpu HOST_VENDOR=$host_vendor HOST_OS=$host_os TARGET=$target TARGET_CPU=$target_cpu TARGET_VENDOR=$target_vendor TARGET_OS=$target_os AC_CHECK_LIB(nsl, chown) AC_CHECK_LIB(socket, accept) AC_CHECK_LIB(wsock32) AC_CHECK_LIB(advapi32) AC_HEADER_DIRENT AC_HAVE_HEADERS(dir.h libc.h time.h stdlib.h memory.h string.h dnl strings.h sys/stat.h sys/fcntl.h fcntl.h dnl sys/vfs.h sys/statfs.h sys/statvfs.h dnl netinet/in.h windows.h winsock.h sys/socket.h dnl Windows32/Sockets.h pwd.h process.h grp.h sys/param.h dnl sys/file.h sys/errno.h sys/select.h sys/poll.h poll.h dnl sys/time.h sys/types.h dnl sys/ioctl.h sys/filio.h dnl netdb.h unistd.h unistd.h limits.h) AC_HEADER_SYS_WAIT AC_CHECK_FUNCS(memcpy getcwd kill poll isatty ttyname ttyname_r dnl gethostbyname_r gethostbyaddr_r gethostent_r) AC_FUNC_MMAP AC_FUNC_VFORK # uses AC_TRY_RUN if test "$cross_compiling" = yes; then echo "WARNING: cannot check for restartable system calls during cross compilation." else AC_SYS_RESTARTABLE_SYSCALLS fi AC_OUTPUT SOPE/sope-core/NGStreams/GNUmakefile0000644000000000000000000000531315004363604016136 0ustar rootroot# GNUstep makefile include ../../config.make include ../common.make include ./Version ifneq ($(frameworks),yes) LIBRARY_NAME = libNGStreams else FRAMEWORK_NAME = NGStreams endif libNGStreams_PCH_FILE = common.h libNGStreams_DLL_DEF = libNGStreams.def libNGStreams_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION) libNGStreams_INSTALL_DIR=$(SOPE_SYSLIBDIR) libNGStreams_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION) libNGStreams_HEADER_FILES_DIR = NGStreams libNGStreams_HEADER_FILES_INSTALL_DIR = /NGStreams libNGStreams_HEADER_FILES = \ NGStreamsDecls.h \ NGStreams.h \ NGStreamProtocols.h \ NGTextStreamProtocols.h \ NGBase64Stream.h \ NGBufferedStream.h \ NGByteCountStream.h \ NGCTextStream.h \ NGConcreteStreamFileHandle.h \ NGDataStream.h \ NGFileStream.h \ NGFilterStream.h \ NGFilterTextStream.h \ NGLockingStream.h \ NGStream.h \ NGStreamExceptions.h \ NGStringTextStream.h \ NGTextStream.h \ NGDescriptorFunctions.h \ NGStreamPipe.h \ NGByteBuffer.h \ NGCharBuffer.h \ NGTerminalSupport.h \ \ NGActiveSocket.h \ NGDatagramPacket.h \ NGDatagramSocket.h \ NGInternetSocketAddress.h \ NGInternetSocketDomain.h \ NGLocalSocketAddress.h \ NGLocalSocketDomain.h \ NGNet.h \ NGNetDecls.h \ NGNetUtilities.h \ NGPassiveSocket.h \ NGSocket.h \ NGSocketExceptions.h \ NGSocketProtocols.h \ \ NGGZipStream.h \ libNGStreams_OBJC_FILES = \ NGStreams.m \ NGBase64Stream.m \ NGBufferedStream.m \ NGByteCountStream.m \ NGCTextStream.m \ NGConcreteStreamFileHandle.m \ NGDataStream.m \ NGFileStream.m \ NGFilterStream.m \ NGFilterTextStream.m \ NGLockingStream.m \ NGStream.m \ NGStreamExceptions.m \ NGStringTextStream.m \ NGTextStream.m \ NGDescriptorFunctions.m \ NGStreamPipe.m \ NGByteBuffer.m \ NGCharBuffer.m \ NGTerminalSupport.m \ \ NGActiveSocket.m \ NGDatagramPacket.m \ NGDatagramSocket.m \ NGInternetSocketAddress.m \ NGInternetSocketDomain.m \ NGLocalSocketAddress.m \ NGLocalSocketDomain.m \ NGNetUtilities.m \ NGPassiveSocket.m \ NGSocket.m \ NGSocketExceptions.m \ \ NGGZipStream.m \ # framework support NGStreams_PCH_FILE = $(libNGStreams_PCH_FILE) NGStreams_HEADER_FILES_DIR = $(libNGStreams_HEADER_FILES_DIR) NGStreams_HEADER_FILES = $(libNGStreams_HEADER_FILES) NGStreams_OBJC_FILES = $(libNGStreams_OBJC_FILES) # building -include GNUmakefile.preamble ifneq ($(FHS_INSTALL_ROOT),) GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include endif ifneq ($(frameworks),yes) include $(GNUSTEP_MAKEFILES)/library.make else include $(GNUSTEP_MAKEFILES)/framework.make endif -include GNUmakefile.postamble SOPE/sope-core/NGStreams/configure0000755000000000000000000050444415004363604016004 0ustar rootroot#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.67. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software # Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= PACKAGE_URL= ac_unique_file="NGStream.m" ac_default_prefix=/usr/local # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_header_list= ac_subst_vars='LTLIBOBJS LIBOBJS EGREP GREP CPP OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS DLLTOOL AR RANLIB CC target_os target_vendor target_cpu target host_os host_vendor host_cpu host build_os build_vendor build_cpu build target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used" >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] --target=TARGET configure for building compilers for TARGET [HOST] _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.67 Copyright (C) 2010 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval "test \"\${$3+set}\"" = set; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_header_compile # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_func # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_type cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.67. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5 ; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi as_fn_append ac_header_list " stdlib.h" as_fn_append ac_header_list " unistd.h" as_fn_append ac_header_list " sys/param.h" # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Determine the host, build, and target systems CC_TARGET=$target # use --target value for CC, not the canonical form ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if test "${ac_cv_build+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5 ;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if test "${ac_cv_host+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5 ;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 $as_echo_n "checking target system type... " >&6; } if test "${ac_cv_target+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "x$target_alias" = x; then ac_cv_target=$ac_cv_host else ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 $as_echo "$ac_cv_target" >&6; } case $ac_cv_target in *-*-*) ;; *) as_fn_error $? "invalid value of canonical target" "$LINENO" 5 ;; esac target=$ac_cv_target ac_save_IFS=$IFS; IFS='-' set x $ac_cv_target shift target_cpu=$1 target_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: target_os=$* IFS=$ac_save_IFS case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac # The aliases save the names the user supplied, while $host etc. # will get canonicalized. test -n "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- ac_config_headers="$ac_config_headers config.h:config.h.in" # check for cross compilation if test "x$target" = "xNONE"; then set target $host fi if test "x$host" != "x$target"; then cross_defines="CROSS=-DCROSS_COMPILE" cross_compiling="yes" echo "cross compiling from $host to $target .." # Extract the first word of ""${CC_TARGET}-gcc"", so it can be a program name with args. set dummy "${CC_TARGET}-gcc"; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC=""${CC_TARGET}-gcc"" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_CC" && ac_cv_prog_CC="gcc" fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of ""${CC_TARGET}-ranlib"", so it can be a program name with args. set dummy "${CC_TARGET}-ranlib"; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_RANLIB+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB=""${CC_TARGET}-ranlib"" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB="ranlib" fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of ""${CC_TARGET}-ar"", so it can be a program name with args. set dummy "${CC_TARGET}-ar"; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_AR+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AR=""${CC_TARGET}-ar"" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="ar" fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of ""${CC_TARGET}-dlltool"", so it can be a program name with args. set dummy "${CC_TARGET}-dlltool"; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_DLLTOOL+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_DLLTOOL=""${CC_TARGET}-dlltool"" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_DLLTOOL" && ac_cv_prog_DLLTOOL="dlltool" fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi CC=${CC_TARGET}-gcc LD=${CC_TARGET}-ld AR=${CC_TARGET}-ar RANLIB=${CC_TARGET}-ranlib else # Extract the first word of ""gcc"", so it can be a program name with args. set dummy "gcc"; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC=""gcc"" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_CC" && ac_cv_prog_CC="gcc" fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of ""ranlib"", so it can be a program name with args. set dummy "ranlib"; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_RANLIB+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB=""ranlib"" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB="ranlib" fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of ""ar"", so it can be a program name with args. set dummy "ar"; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_AR+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AR=""ar"" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="ar" fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of ""dlltool"", so it can be a program name with args. set dummy "dlltool"; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_DLLTOOL+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_DLLTOOL=""dlltool"" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_DLLTOOL" && ac_cv_prog_DLLTOOL="dlltool" fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi case "${host_cpu}" in i[45]86*) host_cpu=i386;; hppa1.1) host_cpu=hppa;; esac if test "x$cross_compiling" = "xyes"; then case "${target_cpu}" in i[45]86*) target_cpu=i386;; hppa1.1) target_cpu=hppa;; esac else target_cpu=${host_cpu} target_os=${host_os} target_vendor=${host_vendor} fi case "x${target_os}" in xfreebsd*) target_os=freebsd;; esac # Assign the HOST variables for sharedlib.mak HOST=$host HOST_CPU=$host_cpu HOST_VENDOR=$host_vendor HOST_OS=$host_os TARGET=$target TARGET_CPU=$target_cpu TARGET_VENDOR=$target_vendor TARGET_OS=$target_os ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5 ; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5 ; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5 ; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5 ; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if test "${ac_cv_objext+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5 ; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for chown in -lnsl" >&5 $as_echo_n "checking for chown in -lnsl... " >&6; } if test "${ac_cv_lib_nsl_chown+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char chown (); int main () { return chown (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_nsl_chown=yes else ac_cv_lib_nsl_chown=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_chown" >&5 $as_echo "$ac_cv_lib_nsl_chown" >&6; } if test "x$ac_cv_lib_nsl_chown" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBNSL 1 _ACEOF LIBS="-lnsl $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for accept in -lsocket" >&5 $as_echo_n "checking for accept in -lsocket... " >&6; } if test "${ac_cv_lib_socket_accept+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char accept (); int main () { return accept (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_accept=yes else ac_cv_lib_socket_accept=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_accept" >&5 $as_echo "$ac_cv_lib_socket_accept" >&6; } if test "x$ac_cv_lib_socket_accept" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBSOCKET 1 _ACEOF LIBS="-lsocket $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for in -lwsock32" >&5 $as_echo_n "checking for in -lwsock32... " >&6; } if test "${ac_cv_lib_wsock32_+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lwsock32 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char (); int main () { return (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_wsock32_=yes else ac_cv_lib_wsock32_=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_wsock32_" >&5 $as_echo "$ac_cv_lib_wsock32_" >&6; } if test "x$ac_cv_lib_wsock32_" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBWSOCK32 1 _ACEOF LIBS="-lwsock32 $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for in -ladvapi32" >&5 $as_echo_n "checking for in -ladvapi32... " >&6; } if test "${ac_cv_lib_advapi32_+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ladvapi32 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char (); int main () { return (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_advapi32_=yes else ac_cv_lib_advapi32_=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_advapi32_" >&5 $as_echo "$ac_cv_lib_advapi32_" >&6; } if test "x$ac_cv_lib_advapi32_" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBADVAPI32 1 _ACEOF LIBS="-ladvapi32 $LIBS" fi ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 $as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } if eval "test \"\${$as_ac_Header+set}\"" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include <$ac_hdr> int main () { if ((DIR *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$as_ac_Header=yes" else eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$as_ac_Header { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF ac_header_dirent=$ac_hdr; break fi done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if test "${ac_cv_search_opendir+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' dir; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if test "${ac_cv_search_opendir+set}" = set; then : break fi done if test "${ac_cv_search_opendir+set}" = set; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if test "${ac_cv_search_opendir+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' x; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if test "${ac_cv_search_opendir+set}" = set; then : break fi done if test "${ac_cv_search_opendir+set}" = set; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5 ; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if test "${ac_cv_path_GREP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if test "${ac_cv_path_EGREP+set}" = set; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if test "${ac_cv_header_stdc+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dir.h libc.h time.h stdlib.h memory.h string.h strings.h sys/stat.h sys/fcntl.h fcntl.h sys/vfs.h sys/statfs.h sys/statvfs.h netinet/in.h windows.h winsock.h sys/socket.h Windows32/Sockets.h pwd.h process.h grp.h sys/param.h sys/file.h sys/errno.h sys/select.h sys/poll.h poll.h sys/time.h sys/types.h sys/ioctl.h sys/filio.h netdb.h unistd.h unistd.h limits.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5 $as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; } if test "${ac_cv_header_sys_wait_h+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif int main () { int s; wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_sys_wait_h=yes else ac_cv_header_sys_wait_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5 $as_echo "$ac_cv_header_sys_wait_h" >&6; } if test $ac_cv_header_sys_wait_h = yes; then $as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h fi for ac_func in memcpy getcwd kill poll isatty ttyname ttyname_r gethostbyname_r gethostbyaddr_r gethostent_r do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in $ac_header_list do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in getpagesize do : ac_fn_c_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize" if test "x$ac_cv_func_getpagesize" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETPAGESIZE 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working mmap" >&5 $as_echo_n "checking for working mmap... " >&6; } if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_mmap_fixed_mapped=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default /* malloc might have been renamed as rpl_malloc. */ #undef malloc /* Thanks to Mike Haertel and Jim Avera for this test. Here is a matrix of mmap possibilities: mmap private not fixed mmap private fixed at somewhere currently unmapped mmap private fixed at somewhere already mapped mmap shared not fixed mmap shared fixed at somewhere currently unmapped mmap shared fixed at somewhere already mapped For private mappings, we should verify that changes cannot be read() back from the file, nor mmap's back from the file at a different address. (There have been systems where private was not correctly implemented like the infamous i386 svr4.0, and systems where the VM page cache was not coherent with the file system buffer cache like early versions of FreeBSD and possibly contemporary NetBSD.) For shared mappings, we should conversely verify that changes get propagated back to all the places they're supposed to be. Grep wants private fixed already mapped. The main things grep needs to know about mmap are: * does it exist and is it safe to write into the mmap'd area * how to use it (BSD variants) */ #include #include #if !defined STDC_HEADERS && !defined HAVE_STDLIB_H char *malloc (); #endif /* This mess was copied from the GNU getpagesize.h. */ #ifndef HAVE_GETPAGESIZE # ifdef _SC_PAGESIZE # define getpagesize() sysconf(_SC_PAGESIZE) # else /* no _SC_PAGESIZE */ # ifdef HAVE_SYS_PARAM_H # include # ifdef EXEC_PAGESIZE # define getpagesize() EXEC_PAGESIZE # else /* no EXEC_PAGESIZE */ # ifdef NBPG # define getpagesize() NBPG * CLSIZE # ifndef CLSIZE # define CLSIZE 1 # endif /* no CLSIZE */ # else /* no NBPG */ # ifdef NBPC # define getpagesize() NBPC # else /* no NBPC */ # ifdef PAGESIZE # define getpagesize() PAGESIZE # endif /* PAGESIZE */ # endif /* no NBPC */ # endif /* no NBPG */ # endif /* no EXEC_PAGESIZE */ # else /* no HAVE_SYS_PARAM_H */ # define getpagesize() 8192 /* punt totally */ # endif /* no HAVE_SYS_PARAM_H */ # endif /* no _SC_PAGESIZE */ #endif /* no HAVE_GETPAGESIZE */ int main () { char *data, *data2, *data3; const char *cdata2; int i, pagesize; int fd, fd2; pagesize = getpagesize (); /* First, make a file with some known garbage in it. */ data = (char *) malloc (pagesize); if (!data) return 1; for (i = 0; i < pagesize; ++i) *(data + i) = rand (); umask (0); fd = creat ("conftest.mmap", 0600); if (fd < 0) return 2; if (write (fd, data, pagesize) != pagesize) return 3; close (fd); /* Next, check that the tail of a page is zero-filled. File must have non-zero length, otherwise we risk SIGBUS for entire page. */ fd2 = open ("conftest.txt", O_RDWR | O_CREAT | O_TRUNC, 0600); if (fd2 < 0) return 4; cdata2 = ""; if (write (fd2, cdata2, 1) != 1) return 5; data2 = (char *) mmap (0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0L); if (data2 == MAP_FAILED) return 6; for (i = 0; i < pagesize; ++i) if (*(data2 + i)) return 7; close (fd2); if (munmap (data2, pagesize)) return 8; /* Next, try to mmap the file at a fixed address which already has something else allocated at it. If we can, also make sure that we see the same garbage. */ fd = open ("conftest.mmap", O_RDWR); if (fd < 0) return 9; if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0L)) return 10; for (i = 0; i < pagesize; ++i) if (*(data + i) != *(data2 + i)) return 11; /* Finally, make sure that changes to the mapped area do not percolate back to the file as seen by read(). (This is a bug on some variants of i386 svr4.0.) */ for (i = 0; i < pagesize; ++i) *(data2 + i) = *(data2 + i) + 1; data3 = (char *) malloc (pagesize); if (!data3) return 12; if (read (fd, data3, pagesize) != pagesize) return 13; for (i = 0; i < pagesize; ++i) if (*(data + i) != *(data3 + i)) return 14; close (fd); return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_mmap_fixed_mapped=yes else ac_cv_func_mmap_fixed_mapped=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_mmap_fixed_mapped" >&5 $as_echo "$ac_cv_func_mmap_fixed_mapped" >&6; } if test $ac_cv_func_mmap_fixed_mapped = yes; then $as_echo "#define HAVE_MMAP 1" >>confdefs.h fi rm -f conftest.mmap conftest.txt ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = x""yes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi for ac_header in vfork.h do : ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default" if test "x$ac_cv_header_vfork_h" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VFORK_H 1 _ACEOF fi done for ac_func in fork vfork do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test "x$ac_cv_func_fork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5 $as_echo_n "checking for working fork... " >&6; } if test "${ac_cv_func_fork_works+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_fork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* By Ruediger Kuhlmann. */ return fork () < 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_fork_works=yes else ac_cv_func_fork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5 $as_echo "$ac_cv_func_fork_works" >&6; } else ac_cv_func_fork_works=$ac_cv_func_fork fi if test "x$ac_cv_func_fork_works" = xcross; then case $host in *-*-amigaos* | *-*-msdosdjgpp*) # Override, as these systems have only a dummy fork() stub ac_cv_func_fork_works=no ;; *) ac_cv_func_fork_works=yes ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} fi ac_cv_func_vfork_works=$ac_cv_func_vfork if test "x$ac_cv_func_vfork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5 $as_echo_n "checking for working vfork... " >&6; } if test "${ac_cv_func_vfork_works+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_vfork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Thanks to Paul Eggert for this test. */ $ac_includes_default #include #ifdef HAVE_VFORK_H # include #endif /* On some sparc systems, changes by the child to local and incoming argument registers are propagated back to the parent. The compiler is told about this with #include , but some compilers (e.g. gcc -O) don't grok . Test for this by using a static variable whose address is put into a register that is clobbered by the vfork. */ static void #ifdef __cplusplus sparc_address_test (int arg) # else sparc_address_test (arg) int arg; #endif { static pid_t child; if (!child) { child = vfork (); if (child < 0) { perror ("vfork"); _exit(2); } if (!child) { arg = getpid(); write(-1, "", 0); _exit (arg); } } } int main () { pid_t parent = getpid (); pid_t child; sparc_address_test (0); child = vfork (); if (child == 0) { /* Here is another test for sparc vfork register problems. This test uses lots of local variables, at least as many local variables as main has allocated so far including compiler temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should reuse the register of parent for one of the local variables, since it will think that parent can't possibly be used any more in this routine. Assigning to the local variable will thus munge parent in the parent process. */ pid_t p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); /* Convince the compiler that p..p7 are live; otherwise, it might use the same hardware register for all 8 local variables. */ if (p != p1 || p != p2 || p != p3 || p != p4 || p != p5 || p != p6 || p != p7) _exit(1); /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent from child file descriptors. If the child closes a descriptor before it execs or exits, this munges the parent's descriptor as well. Test for this by closing stdout in the child. */ _exit(close(fileno(stdout)) != 0); } else { int status; struct stat st; while (wait(&status) != child) ; return ( /* Was there some problem with vforking? */ child < 0 /* Did the child fail? (This shouldn't happen.) */ || status /* Did the vfork/compiler bug occur? */ || parent != getpid() /* Did the file descriptor bug occur? */ || fstat(fileno(stdout), &st) != 0 ); } } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_vfork_works=yes else ac_cv_func_vfork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5 $as_echo "$ac_cv_func_vfork_works" >&6; } fi; if test "x$ac_cv_func_fork_works" = xcross; then ac_cv_func_vfork_works=$ac_cv_func_vfork { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} fi if test "x$ac_cv_func_vfork_works" = xyes; then $as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h else $as_echo "#define vfork fork" >>confdefs.h fi if test "x$ac_cv_func_fork_works" = xyes; then $as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h fi # uses AC_TRY_RUN if test "$cross_compiling" = yes; then echo "WARNING: cannot check for restartable system calls during cross compilation." else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for restartable system calls" >&5 $as_echo_n "checking for restartable system calls... " >&6; } if test "${ac_cv_sys_restartable_syscalls+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5 ; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Exit 0 (true) if wait returns something other than -1, i.e. the pid of the child, which means that wait was restarted after getting the signal. */ $ac_includes_default #include #ifdef HAVE_SYS_WAIT_H # include #endif /* Some platforms explicitly require an extern "C" signal handler when using C++. */ #ifdef __cplusplus extern "C" void ucatch (int dummy) { } #else void ucatch (dummy) int dummy; { } #endif int main () { int i = fork (), status; if (i == 0) { sleep (3); kill (getppid (), SIGINT); sleep (3); return 0; } signal (SIGINT, ucatch); status = wait (&i); if (status == -1) wait (&i); return status == -1; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_sys_restartable_syscalls=yes else ac_cv_sys_restartable_syscalls=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_restartable_syscalls" >&5 $as_echo "$ac_cv_sys_restartable_syscalls" >&6; } if test $ac_cv_sys_restartable_syscalls = yes; then $as_echo "#define HAVE_RESTARTABLE_SYSCALLS 1" >>confdefs.h fi fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.67. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration headers: $config_headers Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.67, with options \\"\$ac_cs_config\\" Copyright (C) 2010 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h:config.h.in" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_t=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_t"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" } >"$tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi SOPE/sope-core/NGStreams/NGFilterStream.m0000644000000000000000000001036515004363604017073 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "common.h" @implementation NGFilterStream + (id)filterWithInputSource:(id)_s { return [[(NGFilterStream *)[self alloc] initWithInputSource:_s] autorelease]; } + (id)filterWithOutputSource:(id)_s { return [[(NGFilterStream *)[self alloc] initWithOutputSource:_s] autorelease]; } + (id)filterWithSource:(id)_s { return [[(NGFilterStream *)[self alloc] initWithSource:_s] autorelease]; } - (id)init { return [self initWithSource:nil]; } - (id)initWithSource:(id)_source { if ((self = [super init])) { self->source = [_source retain]; if ([source isKindOfClass:[NSObject class]]) { self->readBytes = (NGIOReadMethodType) [(NSObject *)self->source methodForSelector:@selector(readBytes:count:)]; self->writeBytes = (NGIOWriteMethodType) [(NSObject *)self->source methodForSelector:@selector(writeBytes:count:)]; } } return self; } - (id)initWithInputSource:(id)_source { if ((self = [super init])) { self->source = [_source retain]; if ([source isKindOfClass:[NSObject class]]) { self->readBytes = (NGIOReadMethodType) [(NSObject *)self->source methodForSelector:@selector(readBytes:count:)]; } } return self; } - (id)initWithOutputSource:(id)_source { if ((self = [super init])) { self->source = [_source retain]; if ([source isKindOfClass:[NSObject class]]) { self->writeBytes = (NGIOWriteMethodType) [(NSObject *)self->source methodForSelector:@selector(writeBytes:count:)]; } } return self; } - (void)dealloc { [self->source release]; self->readBytes = NULL; self->writeBytes = NULL; [super dealloc]; } /* accessors */ - (id)inputStream { return [self source]; } - (id)outputStream { return [self source]; } - (id)source { return self->source; } /* primitives */ - (NSException *)lastException { return [self->source lastException]; } - (void)resetLastException { [self->source resetLastException]; } - (void)setLastException:(NSException *)_exception { [self->source setLastException:_exception]; } - (BOOL)isOpen { return [self->source isOpen]; } - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { if (self->readBytes) return (unsigned)readBytes(self->source, _cmd, _buf, _len); else return [self->source readBytes:_buf count:_len]; } - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len { if (self->writeBytes) return (unsigned)writeBytes(self->source, _cmd, _buf, _len); else return [self->source writeBytes:_buf count:_len]; } - (BOOL)flush { return [self->source flush]; } - (BOOL)close { return [((NGStream *)self->source) close]; } - (NGStreamMode)mode { return [(NGStream *)self->source mode]; } - (BOOL)isRootStream { return NO; } // all other things are forward - (void)forwardInvocation:(NSInvocation *)_invocation { if ([self->source respondsToSelector:[_invocation selector]]) { [_invocation setTarget:self->source]; [_invocation invoke]; } else [self doesNotRecognizeSelector:[_invocation selector]]; } /* description */ - (NSString *)description { return [NSString stringWithFormat: @"<%@[0x%p] source=%@ mode=%@>", NSStringFromClass([self class]), self, self->source ? (id)self->source : (id)@"nil", [self modeDescription]]; } @end /* NGFilterStream */ SOPE/sope-core/NGStreams/config.sub0000755000000000000000000010344515004363604016054 0ustar rootroot#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 # Free Software Foundation, Inc. timestamp='2010-01-22' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file 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., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, 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. # Please send patches to . Submit a context # diff and a properly formatted GNU ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nios | nios2 \ | ns16k | ns32k \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | ubicom32 \ | v850 | v850e \ | we32k \ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | picochip) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile-* | tilegx-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze) basic_machine=microblaze-xilinx ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tic55x | c55x*) basic_machine=tic55x-unknown os=-coff ;; tic6x | c6x*) basic_machine=tic6x-unknown os=-coff ;; # This must be matched before tile*. tilegx*) basic_machine=tilegx-unknown os=-linux-gnu ;; tile*) basic_machine=tile-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: SOPE/sope-core/NGStreams/NGStreamPipe.m0000644000000000000000000001164315004363604016543 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" #include "common.h" #include "NGStreamPipe.h" #include "NGFileStream.h" #include "NGBufferedStream.h" #if defined(WIN32) @implementation NGStreamPipe @end #else static const int NGInvalidUnixDescriptor = -1; @interface _NGConcretePipeFileHandle : NSFileHandle { @public int *fd; } - (id)initWithDescriptor:(int *)_fd; @end @interface NGFileStream(PrivateMethods) - (id)__initWithDescriptor:(int)_fd mode:(NGStreamMode)_mode; @end @implementation NGStreamPipe + (id)pipe { return [[[self alloc] init] autorelease]; } - (id)init { if (pipe(self->fildes) == -1) { NSLog (@"pipe() system call failed: %s", strerror (errno)); self = [self autorelease]; return nil; } return self; } - (void)gcFinalize { [self close]; } - (void)dealloc { [self gcFinalize]; [self->fhIn release]; [self->fhOut release]; [super dealloc]; } - (NSFileHandle *)fileHandleForReading { if (self->fhIn == nil) { self->fhIn = [[_NGConcretePipeFileHandle alloc] initWithDescriptor:&(self->fildes[0])]; } return self->fhIn; } - (NSFileHandle *)fileHandleForWriting { if (self->fhOut == nil) { self->fhOut = [[_NGConcretePipeFileHandle alloc] initWithDescriptor:&(self->fildes[1])]; } return self->fhOut; } - (id)streamForReading { return self; } - (id)streamForWriting { return self; } - (NSException *)lastException { return nil; } /* NGInputStream */ - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { int readResult; if (self->fildes[0] == NGInvalidUnixDescriptor) { [NGStreamReadErrorException raiseWithStream:self reason:@"read end of pipe is closed"]; } readResult = read(self->fildes[0], _buf, _len); if (readResult == 0) [NGEndOfStreamException raiseWithStream:self]; else if (readResult == -1) [NGStreamReadErrorException raiseWithStream:self errorCode:errno]; return readResult; } - (BOOL)safeReadBytes:(void *)_buf count:(unsigned)_len { return NGSafeReadBytesFromStream(self, _buf, _len); } /* marks */ - (BOOL)mark { NSLog(@"WARNING: called mark on a stream which doesn't support marking !"); return NO; } - (BOOL)rewind { [NGStreamException raiseWithStream:self reason:@"marking not supported"]; return NO; } - (BOOL)markSupported { return NO; } /* NGOutputStream */ - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len { int writeResult; if (self->fildes[1] == NGInvalidUnixDescriptor) { [NGStreamWriteErrorException raiseWithStream:self reason:@"write end of pipe is closed"]; } writeResult = write(self->fildes[1], _buf, _len); if (writeResult == -1) [NGStreamWriteErrorException raiseWithStream:self errorCode:errno]; return writeResult; } - (BOOL)safeWriteBytes:(const void *)_buf count:(unsigned)_len { return NGSafeWriteBytesToStream(self, _buf, _len); } - (BOOL)flush { return YES; } /* NGStream */ - (BOOL)close { if (self->fildes[0] != NGInvalidUnixDescriptor) close(self->fildes[0]); if (self->fildes[1] != NGInvalidUnixDescriptor) close(self->fildes[1]); return YES; } - (NGStreamMode)mode { NGStreamMode mode = NGStreamMode_undefined; if (self->fildes[0] != NGInvalidUnixDescriptor) mode |= NGStreamMode_readOnly; if (self->fildes[1] != NGInvalidUnixDescriptor) mode |= NGStreamMode_writeOnly; return mode; } // NGByteSequenceStream - (int)readByte { return NGReadByteFromStream(self); } // Extensions - (BOOL)isOpen { return (self->fildes[0] == NGInvalidUnixDescriptor) && (self->fildes[1] == NGInvalidUnixDescriptor) ? NO : YES; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"<0x%p[%@]: in=%i out=%i>", self, NSStringFromClass([self class]), self->fildes[0], self->fildes[1]]; } @end /* NGStreamPipe */ @implementation _NGConcretePipeFileHandle - (id)initWithDescriptor:(int *)_fd { self->fd = _fd; return self; } - (int)fileDescriptor { return *(self->fd); } - (void)closeFile { close(*(self->fd)); *(self->fd) = NGInvalidUnixDescriptor; } @end #endif /* WIN32 */ SOPE/sope-core/NGStreams/ChangeLog0000644000000000000000000003553315004363604015645 0ustar rootroot2010-01-28 Wolfgang Sourdeau * NGActiveSocket.m (-safeReadBytes:count:): explicitly make use of [NGEndOfStreamException alloc] when allocating localException, since the init method is only present in that class and this may cause a crash on rare occasions. 2010-01-25 Wolfgang Sourdeau * NGCTextStream.m (-writeString:): use getCString:maxLength:encoding: on GNUstep too to avoid a possible segfault in GNUstep's handling of cStringLength. 2009-11-11 Wolfgang Sourdeau * NGActiveSocket.m (+socketPair): removed the domain: parameter as only AF_LOCAL is permitted. Assign a default instance of NGLocalSocketAddress to the sockets to "declare" the sockets as connected. * NGActiveSocket.m (-setSendTimeout, -setReceiveTimeout): make use of those methods to actually configure the timeouts on the socket objects (via setsockopt and SO_RCVTIMEO and SO_SNDTIMEO). 2009-03-24 Wolfgang Sourdeau * GNUmakefile.preamble: add machine-type to include path (eg i386) (v4.7.57) 2008-02-09 Helge Hess * NGCTextStream.m: fixed -writeString: on MacOS > 10.4, use -maximumLengthOfBytesUsingEncoding: (v4.7.56) 2007-12-03 Helge Hess * NGCTextStream.m: replaced usage of getCString on MacOS > 10.4 (v4.7.55) * NGTextStream.m: do not use exception handlers in combination with varargs on MacOS >10.5 (v4.7.54) 2007-08-09 Wolfgang Sourdeau * NGInternetSocketAddress.m: properly convert ports returned by getservbyname() to host byteorder prior calling -initWithPort:onHost: (fixes OGo bug #1896) (v4.7.53) 2007-08-07 Marcus Mueller * NGInternetSocketAddress.m: do not define USE_GETHOSTBYNAME_R on FreeBSD (although HAVE_GETHOSTBYNAME_R is defined). It appears gethostbyname() is thread safe on FreeBSD and there are 3 API versions of gethostbyname_r(), which isn't worth the hassle to check in this case. Changed code to consequently use USE_GETHOSTBYNAME_R. (v4.7.52) 2006-07-04 Helge Hess * 64bit fixes (v4.5.51) 2006-07-03 Helge Hess * use %p for pointer formats, fixed gcc 4.1 warnings (v4.5.50) 2005-08-10 Helge Hess * reorganized inclusion to support frameworks (v4.5.49) 2005-05-03 Helge Hess * NGSocket.m (SockAddrLenType): fixed a Tiger warning (v4.5.48) 2005-04-24 Helge Hess * v4.5.47 * fixed some gcc 4.0 warnings * NGCTextStream.m, NGFileStream.m: do not flush input streams 2004-11-07 Helge Hess * NGStreams.xcode: properly link against libssl/libcrypto and set HAVE_OPENSSL=1, this enables SSL support on MacOSX 2004-10-04 Marcus Mueller * NGStreams.xcode: updated to the current build version 2004-09-29 Helge Hess * NGInternetSocketAddress.m: _fillAddress() does not throw an exception, just returns it. Improved -description (v4.3.46) 2004-09-06 Helge Hess * NGByteBuffer.m, NGLocalSocketAddress.m, NGCharBuffer.m: fixed exception handling to be the same on all Foundation libraries (v4.3.45) 2004-08-29 Helge Hess * added hack to install the project in FHS locations - the library, its headers, the tools and the resources will be installed in FHS_INSTALL_ROOT if specified (eg make FHS_INSTALL_ROOT=/usr/local) (v4.3.44) 2004-08-29 Marcus Mueller * NGStreams.xcode: various fixes for project settings 2004-08-27 Helge Hess * GNUmakefile.postamble: do not automatically run autoconf to update configure (the configure checked in should work fine on all platforms) (v4.3.43) 2004-08-23 Marcus Mueller * added new Xcode project 2004-08-20 Helge Hess * moved to SOPE 4.3 (v4.3.42) 2004-07-22 Helge Hess * NGLocalSocketAddress.m: fixed a gcc 3.4 warning (v4.2.41) 2004-07-05 Helge Hess * GNUmakefile.preamble: added missing library lookup path to EOControl, this fixes OGo bug #820 (v4.2.40) 2004-06-09 Helge Hess * GNUmakefile.preamble: added prebinding (v4.2.39) 2004-05-05 Marcus Mueller * GNUmakefile.preamble: added support for building with GNUSTEP_BUILD_DIR environment variable set for recent gnustep-make package. (v4.2.38) 2004-02-11 Helge Hess * GNUmakefile.preamble: define OPENSSL_NO_KRB5 to keep Fedora and RH9 happy on compilation (v4.2.37) 2004-02-11 Helge Hess * GNUmakefile: enable SSL per default (this adds OpenSSL-devel as a prerequisite unless you compile with ssl=no) (v4.2.36) 2004-02-10 Helge Hess * NGCTextStream.m, NGConcreteStreamFileHandle.m, NGFilterStream.m, NGFilterTextStream.m: fixed minor compilation warnings on OSX (v4.2.35) 2004-01-25 Helge Hess * v4.2.34 * NGDataStream.m: optimized processing for readonly streams (only call -length and -bytes on the data object in the beginning) - this gives us about 100ms when parsing 1000 IMAP4 headers (about 3-4% speedup) * NGDataStream.m: added method to open a datastream in read-only mode even with NSMutableData objects (allows for optimizations in the stream) 2004-01-24 Helge Hess * v4.2.33 * NGBufferedStream.m, NGByteBuffer.m: avoid creation of buffered stream if the source is an NGDataStream (no buffering needed ;-), do not create buffer streams when no source stream is passed in * NGDataStream.m: NGDataStream objects can now add as byte buffers on their own - which removes a lot of unncessary overhead when parsing NSData (this gives a speedup of about 10% when parsing IMAP4 mail headers) 2004-01-19 Helge Hess * NGDataStream.m: properly return last-exception (always returned nil!) - could have side-effects (v4.2.32) 2004-01-12 Helge Hess * NGDataStream.m: subminor cleanups (v4.2.31) 2003-11-30 Helge Hess * configure.in: patched to use GNUSTEP_MAKEFILES (as suggested by chunsj@embian.com) (v4.2.30) 2003-11-09 Helge Hess * NGActiveSocket.m, NGFilterStream.m, NGStreamCoder.m: minor tweaks for MacOSX (v4.2.29) 2003-10-13 Helge Hess * GNUmakefile, GNUmakefile.postamble: removed NGStream+serialization, NGActiveSocket+serialization from compilation - those files should be removed completely as they aren't used anywhere (v4.2.28) 2003-09-07 Marcus Mueller * NGLocalSocketAddress.m, NGLocalSocketDomain.m: include if __FreeBSD__ is defined. This will currently affect FreeBSD 4.x only. (v4.2.27) 2003-09-06 Helge Hess * various fixes to warnings on MacOSX (v4.2.26) 2003-09-06 Marcus Mueller * configure.in: truncate target_os to "freebsd" on FreeBSD 2003-09-01 Helge Hess * v4.2.25 * fixes for MacOSX * GNUmakefile.postamble: do not generate config.h on MacOSX, use the preconfigured on in the macosx subdir 2003-07-28 Helge Hess * small cleanups to the included headers to improve gstep-base compatibility (v4.2.24) 2003-07-20 Helge Hess * NGGZipStream.m: removed dependency on zutil.h (v4.2.23) 2003-05-26 Helge Hess * updated MacOSX support, removed dependencies on FoundationExt (v4.2.22) 2003-05-15 Helge Hess * NGByteBuffer.m: fixed the last signed/unsigned warnings, smaller cleanups to -la: (v4.2.21) 2003-05-14 Helge Hess * v4.2.20 * fixed some more gcc 3.3 (signed/unsigned) warnings * NGInternetSocketAddress.m: some change ? * removed several gcc 3.3 warnings 2003-01-30 Helge Hess * NGSocket.m: allocate sockets in the NGInternetSocketDomain by default (v4.2.19) 2003-01-20 Helge Hess * replaced some RETAIN macros (v4.2.18) 2003-01-14 Helge Hess * NGPassiveSocket.m, NGInternetSocketDomain.m: small code cleanups (v4.2.17) 2003-01-07 Helge Hess * moved testsock.m to skyrix-core-42/samples/ * GNUmakefile: added optional SSL activation (using ssl=yes) * v4.2.16 * changes for improved compilation on MacOSX, replaced RETAIN macros with methods Mon Dec 30 13:51:15 2002 Helge Hess * v4.2.15 * NGStreams/NGStreams.h: do not include NGStream+serialization.h * NGStreams/NGNet.h: do not include NGActiveSocket+serialization.h * NGByteBuffer.m: fixed a gcc 3.2 warning Fri Dec 27 10:50:56 2002 Helge Hess * GNUmakefile: removed NGStreamCoder from library * testsock.m: rewritten to use a tool class * NGStreamCoder.m: fixed some gcc 3.2 compiler warnings * NGStreams/NGStreams.h: does not include NGStreamCoder.h * fixed Copyright headers in most files (v4.2.14) 2002-11-01 Helge Hess * NGDescriptorFunctions.m: added some debugging/logging (new default NGLogDescriptorRecv) (v4.2.13) 2002-09-30 Helge Hess * testsock.m: added various tests * NGLockingStream.m, NGDataStream.m, NGFileStream.m, NGByteBuffer.m: removed compilation warnings * NGCTextStream.m: do not create a text stream if the source stream is nil ... * started support for OpenSSL sockets (v4.2.12) 2002-08-30 Helge Hess * NGInternetSocketAddress.m: fixed a compilation bug on hosts which are have gethostbyaddr_r() but are not Linux (eg Solaris) (v4.2.11) Thu Aug 29 16:46:25 2002 Jan Reichmann * v4.2.10 * NGBase64Stream.m, NGConcreteStreamFileHandle.m, NGStream.m: fixed 'char-buffer in Exception Handler scope' bug 2002-08-28 Helge Hess * some tweaks to support OSX Jaguar (v4.2.9) 2002-08-15 Helge Hess * NGFileStream.m: do not log, if the filestream is closed on deallocation (v4.2.8) Wed Aug 14 09:49:05 2002 Bjoern Stierand * NGNetUtilities.m (NGSocketAddressFromString): allows definition of kernel bound addresses using 'host:auto' or '*:auto' (v4.2.7) 2002-07-08 Helge Hess * v4.2.6 [extracted from cvs] * fixed a major retain cycle between stream exceptions and streams (lastException ptr). In the case of datastreams this lead to huge memory consumption if the stream reached EOF (the datastream was never released and the whole data kept in memory, most notably this resulted in a leaking MIME parser) => fixes SuSE bug 16845 * added DESIGN document (small ;-) Fri Jun 26 10:40:05 2002 Helge Hess * NGLocalSocketAddress.h: small fix for MacOSX Fri May 31 16:08:56 2002 Jan41 Reichmann * NGCTextStream.m, NGByteBuffer.m, NGActiveSocket.m, NGBufferedStream.m: remove NSLogs * NGDataStream.*: add exception-handling (raise version) * NGStreamExceptions.*: add +exceptionWithStream methods Tue May 21 12:26:03 2002 Helge Hess * NGActiveSocket.m: fixed a small exception related problem with +socketConnectedToAddress: ... v4.2.5 [extracted from cvs] Fri May 17 14:49:21 2002 Helge Hess * added NGGZipStream from NGZlib Mon Apr 29 13:46:11 2002 Helge Hess * NGByteBuffer.m: modified to support the new exception-less IO ... Tue Apr 23 12:32:23 2002 Helge Hess * NGActiveSocket.m: do not throw exception if connect failed (rather set the last exception ...) Thu Mar 14 13:39:10 2002 Helge Hess * NGActiveSocket.m: marks itself as shut down, if the errno says so * NGStream.m(NGSafe...): fixed exception handling * NGActiveSocket.m(safeWriteBytes:length:): added IMP cache, fixed exception handling bug ... * NGBufferedStream.m: added flush buffer size check Wed Mar 13 17:24:47 2002 Helge Hess * NGCTextStream.m: added new exception handling * NGTextStream.m: added +version, added lastException * NGActiveSocket.m: does not throw exceptions in -read.. and -write.. Mon Mar 4 11:05:54 2002 Helge Hess * NGActiveSocket.m: throws less exceptions (uses -lastException,retval) Mon Feb 25 18:43:13 2002 Helge Hess * NGBufferedStream.m: checks return codes Thu Feb 21 12:04:16 2002 Helge Hess * NGStreamExceptions.m: added -raiseOnStream:... Wed Feb 20 13:30:44 2002 Helge Hess * everything reworked not to throw exceptions ... Fri Dec 7 14:35:47 2001 Jan41 Reichmann * NGByteBuffer.m: add profiling Mon Oct 8 17:47:01 2001 Helge Hess * NGLocalSocketAddress.m, NGPassiveSocket.m: better Linux-bug support ;-) (local sock addresses with length=2, as given by accept()) Thu Oct 4 11:15:34 2001 Helge Hess * NGInternetSocketAddress.m: fixed recursion bug Thu Aug 9 14:14:17 2001 Helge Hess * removed all NGUrl related stuff Thu Aug 9 14:00:04 2001 Helge Hess * moved URL escaping to NGExtensions * NGFileStream.m: added -initWithPath: Tue May 15 19:05:45 2001 Helge Hess * NGActiveSocket.m: added max-retry count (20) for writeBytes: with errno==0 Wed May 9 19:22:43 2001 Joerg Grimm * NGActiveSocket.m: check for errno=0 if writeResult<0 Mon Feb 26 11:13:12 2001 Helge Hess * NGActiveSocket.m: added more errno=0-on-fail checking Fri Feb 23 21:40:40 2001 Helge Hess * NGActiveSocket.m: check for errno=0 if result<0 * NGDescriptorFunctions.m: check for errno=0 if result<0 Tue Jan 30 19:50:13 2001 Helge Hess * NGUrl.m: modified URL encoding/decoding stuff to use unsigned char Mon Sep 18 10:47:41 2000 Helge Hess * NGCTextStream.m: fixed bug in -writeString Tue Jun 13 19:40:41 2000 Helge Hess * NGUrl.m, NGFileUrl.m: doesn't use stack-based buffers anymore Fri Jun 9 17:38:27 2000 Helge Hess * GNUmakefile: added -Wall Tue Feb 29 17:08:45 2000 Helge Hess * MOF3 import SOPE/sope-core/NGStreams/common.h0000644000000000000000000000612615004363604015530 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_common_H__ #define __NGStreams_common_H__ // common include files #include // configuration #include "config.h" #if defined(WIN32) # include # include #endif #if LIB_FOUNDATION_BOEHM_GC # include #endif #ifdef GNU_RUNTIME #if __GNU_LIBOBJC__ >= 20100911 # include #else # include # include # include #endif #endif #if WITH_FOUNDATION_EXT #if NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY # import # import # import # import # import # import # import #endif #endif #if !LIB_FOUNDATION_LIBRARY && !NeXT_Foundation_LIBRARY # define NSWillBecomeMultiThreadedNotification NSBecomingMultiThreaded #endif #ifndef ASSIGN # define ASSIGN(object, value) \ ({id __object = (id)object; \ id __value = (id)value; \ if (__value != __object) { if (__value) [__value retain]; \ if (__object) [__object release]; \ object = __value;}}) #endif #include /* system config */ #if !defined(__CYGWIN32__) # ifdef HAVE_WINDOWS_H # include # endif # ifdef HAVE_WINSOCK_H # include # endif #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #if HAVE_SYS_TYPES_H # include #endif #ifndef __MINGW32__ # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #ifdef HAVE_NETDB_H # include #endif #if !defined(WIN32) || defined(__CYGWIN32__) # include # include # include #endif #ifndef AF_LOCAL # define AF_LOCAL AF_UNIX #endif #if !defined(SHUT_RD) # define SHUT_RD 0 #endif #if !defined(SHUT_WR) # define SHUT_WR 1 #endif #if !defined(SHUT_RDWR) # define SHUT_RDWR 2 #endif // local common's #include @interface NSObject(OSXHacks) - (void)subclassResponsibility:(SEL)_acmd; - (void)notImplemented:(SEL)_acmd; @end #endif /* __NGStreams_common_H__ */ SOPE/sope-core/NGStreams/NGDatagramSocket.m0000644000000000000000000002154715004363604017367 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if defined(__APPLE__) # include # include #endif #include #include #include #include "NGDatagramSocket.h" #include "NGDatagramPacket.h" #include "NGSocketExceptions.h" #include "NGSocket+private.h" #include "common.h" #if !defined(POLLRDNORM) # define POLLRDNORM POLLIN #endif NSString *NGSocketTimedOutNotificationName = @"NGSocketTimedOutNotification"; @interface NGSocket(privateMethods) - (void)_createSocketInDomain:(int)_domain; - (void)setOption:(int)_option level:(int)_level value:(void *)_value len:(int)_len; - (void)setOption:(int)_option value:(void *)_value len:(int)_len; - (void)getOption:(int)_option level:(int)_level value:(void *)_val len:(int *)_len; - (void)getOption:(int)_option value:(void *)_value len:(int *)_len; @end //static const int NGMaxTimeout = (int)-1; static const NSTimeInterval NGNoTimeout = 0.0; @implementation NGDatagramSocket #if !defined(WIN32) || defined(__CYGWIN32__) + (BOOL)socketPair:(id[2])_pair { int fds[2]; NGLocalSocketDomain *domain; _pair[0] = nil; _pair[1] = nil; domain = [NGLocalSocketDomain domain]; if (socketpair([domain socketDomain], SOCK_DGRAM, [domain protocol], fds) == 0) { NGDatagramSocket *s1 = nil; NGDatagramSocket *s2 = nil; s1 = [[self alloc] _initWithDomain:domain descriptor:fds[0]]; s2 = [[self alloc] _initWithDomain:domain descriptor:fds[1]]; s1 = AUTORELEASE(s1); s2 = AUTORELEASE(s2); if ((s1 != nil) && (s2 != nil)) { _pair[0] = s1; _pair[1] = s2; return YES; } else return NO; } else { int e = errno; NSString *reason = nil; switch (e) { case EACCES: reason = @"Not allowed to create socket of this type"; break; case ENOMEM: reason = @"Could not create socket: Insufficient user memory available"; break; case EPROTONOSUPPORT: reason = @"The protocol is not supported by the address family or " @"implementation"; break; case EPROTOTYPE: reason = @"The socket type is not supported by the protocol"; break; case EMFILE: reason = @"Could not create socket: descriptor table is full"; break; case EOPNOTSUPP: reason = @"The specified protocol does not permit creation of socket " @"pairs"; break; default: reason = [NSString stringWithFormat:@"Could not create socketpair: %s", strerror(e)]; break; } [[[NGCouldNotCreateSocketException alloc] initWithReason:reason domain:domain] raise]; return NO; } } #endif + (id)socketBoundToAddress:(id)_address { volatile id sock = [[self alloc] initWithDomain:[_address domain]]; if (sock != nil) { sock = AUTORELEASE(sock); [sock bindToAddress:_address]; } return sock; } - (id)initWithDomain:(id)_domain { // designated initializer if ((self = [super initWithDomain:_domain])) { [self setMaxPacketSize:2048]; [self setPacketFactory:(id)[NGDatagramPacket class]]; self->udpFlags.isConnected = NO; } return self; } // accessors - (void)setMaxPacketSize:(int)_maxPacketSize { self->maxPacketSize = _maxPacketSize; } - (int)maxPacketSize { return self->maxPacketSize; } - (void)setPacketFactory:(id)_factory { ASSIGN(self->packetFactory, _factory); } - (id)packetFactory { return self->packetFactory; } - (int)socketType { return SOCK_DGRAM; } - (BOOL)isConnected { return self->udpFlags.isConnected; } // polling - (BOOL)wouldBlockInMode:(NGStreamMode)_mode { short events = 0; if (fd == NGInvalidSocketDescriptor) return NO; if (NGCanReadInStreamMode(_mode)) events |= POLLRDNORM; if (NGCanWriteInStreamMode(_mode)) events |= POLLWRNORM; // timeout of 0 means return immediatly return (NGPollDescriptor([self fileDescriptor], events, 0) == 1 ? NO : YES); } // sending - (void)primarySendPacket:(id)_packet { NSAssert([_packet receiver], @"packet has no destination !"); sendto(self->fd, // socket [[_packet data] bytes], [[_packet data] length], 0, // flags [[_packet receiver] internalAddressRepresentation], [[_packet receiver] addressRepresentationSize]); if (!self->flags.isBound) // was not explictly bound, so get local address [self kernelBoundAddress]; [_packet setSender:[self localAddress]]; } - (BOOL)sendPacket:(id)_packet timeout:(NSTimeInterval)_to { if (_to > NGNoTimeout) { int result = NGPollDescriptor([self fileDescriptor], POLLWRNORM, (int)(_to * 1000.0)); if (result == 0) { // timeout [[NSNotificationCenter defaultCenter] postNotificationName:NGSocketTimedOutNotificationName object:self]; return NO; } else if (result < 0) { [[[NGSocketException alloc] initWithReason:@"error during poll on UDP socket"] raise]; return NO; } // else receive packet .. } [self primarySendPacket:_packet]; return YES; } - (BOOL)sendPacket:(id)_packet { return [self sendPacket:_packet timeout:NGNoTimeout]; } // receiving - (id)primaryReceivePacketWithMaxSize:(int)_maxSize { id remote = nil; id packet = nil; char buffer[_maxSize]; size_t size; unsigned int len = [[self domain] addressRepresentationSize]; char data[len + 2]; size = recvfrom(self->fd, buffer, _maxSize, 0, // flags (void *)data, &len); remote = [[self domain] addressWithRepresentation:(void *)data size:len]; if (!self->flags.isBound) // was not explictly bound, so get local address [self kernelBoundAddress]; packet = [[self packetFactory] packetWithBytes:buffer size:size]; [packet setReceiver:[self localAddress]]; [packet setSender:remote]; return packet; } - (id)receivePacketWithMaxSize:(int)_size timeout:(NSTimeInterval)_to { if (_to > NGNoTimeout) { int result = NGPollDescriptor([self fileDescriptor], POLLRDNORM, (int)(_to * 1000.0)); if (result == 0) { // timeout [[NSNotificationCenter defaultCenter] postNotificationName:NGSocketTimedOutNotificationName object:self]; return nil; } else if (result < 0) { [[[NGSocketException alloc] initWithReason:@"error during poll on UDP socket"] raise]; } // else receive packet .. } return [self primaryReceivePacketWithMaxSize:_size]; } - (id)receivePacketWithTimeout:(NSTimeInterval)_timeout { return [self receivePacketWithMaxSize:[self maxPacketSize] timeout:_timeout]; } - (id)receivePacketWithMaxSize:(int)_maxPacketSize { return [self receivePacketWithMaxSize:_maxPacketSize timeout:NGNoTimeout]; } - (id)receivePacket { return [self receivePacketWithMaxSize:[self maxPacketSize] timeout:NGNoTimeout]; } // ************************* options ************************* static int i_yes = 1; static int i_no = 0; static inline void setBoolOption(id self, int _option, BOOL _flag) { [self setOption:_option level:SOL_SOCKET value:(_flag ? &i_yes : &i_no) len:4]; } static inline BOOL getBoolOption(id self, int _option) { int value, len; [self getOption:_option level:SOL_SOCKET value:&value len:&len]; return (value ? YES : NO); } - (void)setBroadcast:(BOOL)_flag { setBoolOption(self, SO_BROADCAST, _flag); } - (BOOL)doesBroadcast { return getBoolOption(self, SO_BROADCAST); } // aborts, only supported for TCP - (void)setDebug:(BOOL)_flag { [self doesNotRecognizeSelector:_cmd]; } - (BOOL)doesDebug { [self doesNotRecognizeSelector:_cmd]; return NO; } @end SOPE/sope-core/NGStreams/NGStreamExceptions.m0000644000000000000000000001663015004363604017770 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #include "NGStreamExceptions.h" @interface NSObject(setLastException) - (void)setLastException:(NSException *)_exception; @end @implementation NGIOException - (id)init { self = [super initWithName:NSStringFromClass([self class]) reason:@"an IO exception occured" userInfo:nil]; return self; } - (id)initWithReason:(NSString *)_reason { self = [super initWithName:NSStringFromClass([self class]) reason:_reason userInfo:nil]; return self; } + (void)raiseWithReason:(NSString *)_reason { [[[self alloc] initWithReason:_reason] raise]; } + (void)raiseOnStream:(id)_stream reason:(NSString *)_reason { NGIOException *e; e = [[self alloc] initWithReason:_reason]; if (_stream) { if ([_stream respondsToSelector:@selector(setLastException:)]) { [_stream setLastException:e]; [e release]; return; } } [e raise]; } + (void)raiseOnStream:(id)_stream { [self raiseOnStream:_stream reason:nil]; } @end /* NGIOException */ @implementation NGStreamException - (NSString *)defaultReason { return @"a stream exception occured"; } - (id)init { return [self initWithStream:nil reason:[self defaultReason]]; } - (id)initWithStream:(id)_stream { return [self initWithStream:_stream reason:[self defaultReason]]; } - (id)initWithStream:(id)_stream format:(NSString *)_format,... { NSString *tmp = nil; va_list ap; va_start(ap, _format); tmp = [[NSString alloc] initWithFormat:_format arguments:ap]; va_end(ap); self = [self initWithStream:_stream reason:tmp]; [tmp release]; return self; } - (id)initWithStream:(id)_stream reason:(NSString *)_reason { NSDictionary *ui = nil; ui = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:errno], @"errno", [NSString stringWithCString:strerror(errno)], @"error", [NSValue valueWithNonretainedObject:_stream], @"stream", nil]; self = [super initWithName:NSStringFromClass([self class]) reason:_reason userInfo:ui]; if (self) { self->streamPointer = [[NSValue valueWithNonretainedObject:_stream] retain]; } return self; } + (id)exceptionWithStream:(id)_stream { return [[self alloc] initWithStream:_stream]; } + (id)exceptionWithStream:(id)_stream reason:(NSString *)_reason { return [[self alloc] initWithStream:_stream reason:_reason]; } + (void)raiseWithStream:(id)_stream { [[[self alloc] initWithStream:_stream] raise]; } + (void)raiseWithStream:(id)_stream reason:(NSString *)_reason { [[[self alloc] initWithStream:_stream reason:_reason] raise]; } + (void)raiseWithStream:(id)_stream format:(NSString *)_format,... { NSString *tmp = nil; va_list ap; va_start(ap, _format); tmp = [[NSString alloc] initWithFormat:_format arguments:ap]; va_end(ap); tmp = [tmp autorelease]; [[[self alloc] initWithStream:_stream reason:tmp] raise]; } - (void)dealloc { [self->streamPointer release]; [super dealloc]; } @end /* NGStreamException */ // ******************** NGEndOfStreamException ******************** @implementation NGEndOfStreamException - (id)initWithStream:(id)_stream { return [self initWithStream:_stream readCount:0 safeCount:0 data:nil]; } - (id)initWithStream:(id)_stream readCount:(unsigned)_readCount safeCount:(unsigned)_safeCount data:(NSData *)_data { NSString *tmp; tmp = [NSString stringWithFormat:@"reached end of stream %@", _stream]; if ((self = [super initWithStream:_stream reason:tmp])) { self->readCount = _readCount; self->safeCount = _safeCount; self->data = [_data retain]; } return self; } - (void)dealloc { [self->data release]; [super dealloc]; } /* accessors */ - (NSData *)readBytes { return self->data; } @end /* NGEndOfStreamException */ // ******************** open state exceptions ********************* @implementation NGCouldNotOpenStreamException - (NSString *)defaultReason { return @"could not open stream"; } @end @implementation NGCouldNotCloseStreamException - (NSString *)defaultReason { return @"could not close stream"; } @end @implementation NGStreamNotOpenException - (NSString *)defaultReason { return @"stream is not open"; } @end // ******************** NGStreamErrors **************************** @implementation NGStreamErrorException - (id)initWithStream:(id)_stream errorCode:(int)_code { NSString *tmp = nil; tmp = [NSString stringWithFormat:@"stream error occured, errno=%i error=%s", _code, strerror(_code)]; if ((self = [self initWithStream:_stream reason:tmp])) { osErrorCode = _code; } tmp = nil; return self; } + (void)raiseWithStream:(id)_stream errorCode:(int)_code { [[[self alloc] initWithStream:_stream errorCode:_code] raise]; } - (int)operationSystemErrorCode { return osErrorCode; } - (NSString *)operatingSystemError { return [NSString stringWithCString:strerror(osErrorCode)]; } @end /* NGStreamErrorException */ @implementation NGStreamReadErrorException - (NSString *)defaultReason { return @"read error on stream"; } @end /* NGStreamReadErrorException */ @implementation NGStreamWriteErrorException - (NSString *)defaultReason { return @"write error on stream"; } @end /* NGStreamWriteErrorException */ @implementation NGStreamSeekErrorException - (NSString *)defaultReason { return @"seek error on stream"; } @end // ******************** NGStreamModeExceptions ******************** @implementation NGStreamModeException - (NSString *)defaultReason { return @"stream mode failure"; } @end @implementation NGUnknownStreamModeException - (NSString *)defaultReason { return @"unknow stream mode"; } - (id)initWithStream:(id)_stream mode:(NSString *)_streamMode { if ((self = [super initWithStream:_stream format:@"unknown stream mode: %@", _streamMode])) { streamMode = [_streamMode copy]; } return self; } - (void)dealloc { [self->streamMode release]; [super dealloc]; } @end /* NGUnknownStreamModeException */ @implementation NGReadOnlyStreamException - (NSString *)defaultReason { return @"stream is read only"; } @end /* NGReadOnlyStreamException */ @implementation NGWriteOnlyStreamException - (NSString *)defaultReason { return @"stream is write only"; } @end /* NGWriteOnlyStreamException */ // ******************** NGIOAccessException ****************** @implementation NGIOAccessException @end @implementation NGIOSearchAccessException @end SOPE/sope-core/NGStreams/NGByteBuffer.m0000644000000000000000000002131415004363604016523 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGByteBuffer.h" #include "common.h" #include typedef struct NGByteBufferLA { unsigned char byte; char isEOF:1; char isFetched:1; } LA_NGByteBuffer; @implementation NGByteBuffer static BOOL ProfileByteBuffer = NO; static Class DataStreamClass = Nil; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; static BOOL didInit = NO; if (didInit) return; didInit = YES; ProfileByteBuffer = [ud boolForKey:@"ProfileByteBufferEnabled"]; DataStreamClass = NSClassFromString(@"NGDataStream"); } + (NSInteger)version { return [super version] + 1; } + (id)byteBufferWithSource:(id)_source la:(unsigned)_la { if (_source == nil) return nil; if (*(Class *)_source == DataStreamClass) return _source; return [[[self alloc] initWithSource:_source la:_la] autorelease]; } - (id)initWithSource:(id)_source la:(unsigned)_la { if (_source == nil) { [self release]; return nil; } if (*(Class *)_source == DataStreamClass) { [self release]; return (id)[_source retain]; } if ((self = [super initWithSource:_source])) { unsigned size = 0; if (_la < 1) { [NSException raise:NSRangeException format:@"lookahead depth is less than one (%d)", _la]; } // Find first power of 2 >= to requested size for (size = 2; size < _la; size *=2); self->la = malloc(sizeof(LA_NGByteBuffer) * size + 4); memset(self->la, 0, sizeof(LA_NGByteBuffer) * size); self->bufLen = size; self->sizeLessOne = self->bufLen - 1; self->headIdx = 0; self->wasEOF = NO; if ([self->source respondsToSelector:@selector(methodForSelector:)]) { self->readByte = (int(*)(id, SEL)) [(NSObject *)self->source methodForSelector:@selector(readByte)]; } if ([self respondsToSelector:@selector(methodForSelector:)]) { self->laFunction = (int(*)(id, SEL, unsigned)) [(NSObject *)self methodForSelector:@selector(la:)]; } } return self; } - (id)init { [self release]; [self doesNotRecognizeSelector:_cmd]; return nil; } - (id)initWithSource:(id)_source { [self release]; [self doesNotRecognizeSelector:_cmd]; return nil; } - (id)initWithInputSource:(id)_source { [self release]; [self doesNotRecognizeSelector:_cmd]; return nil; } - (id)initWithOutputSource:(id)_source { [self release]; [self doesNotRecognizeSelector:_cmd]; return nil; } - (void)dealloc { if (self->la) free(self->la); [super dealloc]; } /* operations */ - (int)readByte { int byte = (self->laFunction == NULL) ? [self la:0] : self->laFunction(self, @selector(la:), 0); [self consume]; return byte; } - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { if (_len == 0) return 0; if (!(self->la[(self->headIdx & self->sizeLessOne)].isFetched)) { int byte = [self readByte]; if (byte == -1) [NGEndOfStreamException raiseWithStream:self->source]; ((char *)_buf)[0] = byte; return 1; } else { unsigned cnt = 0; int idxCnt = self->headIdx & sizeLessOne; unsigned char buffer[self->bufLen]; while (self->la[idxCnt].isFetched && cnt < _len && cnt < bufLen) { buffer[cnt] = self->la[idxCnt].byte; cnt++; idxCnt = (cnt + self->headIdx) & sizeLessOne; } memcpy(_buf, buffer, cnt); [self consume:cnt]; return cnt; } return 0; } - (int)la:(unsigned)_la { // TODO: huge method, should be split up volatile unsigned result, idx; unsigned i = 0; result = -1; *(&idx) = (_la + self->headIdx) & self->sizeLessOne; if (_la > self->sizeLessOne) { [NSException raise:NSRangeException format:@"tried to look ahead too far (la=%d, max=%d)", _la, self->bufLen]; } if (self->wasEOF) { result = (!self->la[idx].isFetched || self->la[idx].isEOF) ? -1 : self->la[idx].byte; return result; } if (self->la[idx].isFetched) { result = (self->la[idx].isEOF) ? -1 : self->la[idx].byte; return result; } *(&i) = 0; for (i = 0; i < _la && self->la[(self->headIdx + i) & self->sizeLessOne].isFetched; i++); /* If we should read more than 5 bytes, we take the time costs of an exception handler */ if ((_la - i + 1) <= 5) { while (i <= _la) { #if DEBUG struct timeval tv; double ti = 0.0; #endif int byte = 0; #if DEBUG if (ProfileByteBuffer) { gettimeofday(&tv, NULL); ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0); } #endif byte = (self->readByte == NULL) ? [self->source readByte] : (int)self->readByte(self->source, @selector(readByte)); #if DEBUG if (ProfileByteBuffer) { gettimeofday(&tv, NULL); ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0) - ti; if (ti > 0.01) { fprintf(stderr, "[%s] : time " "needed: %4.4fs\n", __PRETTY_FUNCTION__, ti < 0.0 ? -1.0 : ti); } } #endif if (byte == -1) { // EOF was reached self->wasEOF = YES; break; } else { int ix = (self->headIdx + i) & self->sizeLessOne; self->la[ix].byte = byte; self->la[ix].isFetched = 1; } i++; } } else { BOOL readStream = YES; NSException *exc = nil; while (readStream) { int cntReadBytes = 0; int cnt = 0; int desiredBytes = _la - i+1; char *tmpBuffer; // TODO: check whether malloc is used for sufficiently large blocks! tmpBuffer = malloc(desiredBytes + 2); //NSLog(@"Reading %d %d %d bytes...", desiredBytes, _la, i); cntReadBytes = (self->readBytes == NULL) ? [self->source readBytes:tmpBuffer count:desiredBytes] : self->readBytes(self->source, @selector(readBytes:count:), tmpBuffer, desiredBytes); if (cntReadBytes == NGStreamError) { exc = [[self->source lastException] retain]; break; } else { if (cntReadBytes == desiredBytes) readStream = NO; cnt = 0; while (cntReadBytes > 0) { int ix = (self->headIdx + i) & self->sizeLessOne; self->la[ix].byte = tmpBuffer[cnt]; self->la[ix].isFetched = 1; i++; cnt++; cntReadBytes--; } } if (tmpBuffer) free(tmpBuffer); } if (exc) { if (![exc isKindOfClass:[NGEndOfStreamException class]]) { [self setLastException:exc]; return NGStreamError; } self->wasEOF = YES; } } if (self->wasEOF) { while (i <= _la) { self->la[(self->headIdx + i) & self->sizeLessOne].isEOF = YES; i++; } } result = (self->la[idx].isEOF) ? -1 : self->la[idx].byte; return result; } - (void)consume { int idx = self->headIdx & sizeLessOne; if (!(self->la[idx].isFetched)) { (self->laFunction == NULL) ? [self la:0] : self->laFunction(self, @selector(la:), 0); } self->la[idx].isFetched = 0; self->headIdx++; } - (void)consume:(unsigned)_cnt { while (_cnt > 0) { int idx = self->headIdx & sizeLessOne; if (!(self->la[idx].isFetched)) (self->laFunction == NULL) ? [self la:0] : self->laFunction(self, @selector(la:), 0); self->la[idx].isFetched = 0; self->headIdx++; _cnt--; } } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if (self->source) [ms appendFormat:@" source=%@", self->source]; [ms appendFormat:@" mode=%@", [self modeDescription]]; [ms appendFormat:@" la=%d", self->bufLen]; [ms appendString:@">"]; return ms; } @end /* NGByteBuffer */ SOPE/sope-core/NGStreams/NGConcreteStreamFileHandle.m0000644000000000000000000001304715004363604021324 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include "common.h" @interface NGStream(FileHandleReset) - (void)resetFileHandle; @end @implementation NGConcreteStreamFileHandle - (id)initWithStream:(id)_stream { if ((self = [super init])) { self->stream = [_stream retain]; } return self; } - (void)dealloc { if ([stream respondsToSelector:@selector(resetFileHandle)]) [(NGStream *)self->stream resetFileHandle]; [self->stream release]; [super dealloc]; } // accessors - (id)stream { return self->stream; } /* NSFileHandle operations */ - (void)closeFile { [self->stream close]; } - (int)fileDescriptor { if ([self->stream respondsToSelector:@selector(fileDescriptor)]) return [(id)self->stream fileDescriptor]; else { [self subclassResponsibility:_cmd]; return -1; } } /* buffering */ - (void)synchronizeFile { [self->stream flush]; } /* reading */ - (NSData *)readDataOfLength:(unsigned int)_length { char *buffer; NSData *data; *(&buffer) = NGMallocAtomic(_length); *(&data) = nil; NS_DURING { [stream safeReadBytes:buffer count:_length]; data = [[NSData alloc] initWithBytes:buffer length:_length]; } NS_HANDLER { if ([localException isKindOfClass:[NGEndOfStreamException class]]) { data = [(NGEndOfStreamException *)localException readBytes]; data = data ? [data retain] : [[NSData alloc] init]; } else { if (buffer) { NGFree(buffer); buffer = NULL; } [localException raise]; } } NS_ENDHANDLER; if (buffer) { NGFree(buffer); buffer = NULL; } return [data autorelease]; } - (NSData *)readDataToEndOfFile { NGBufferedStream *bs; NSMutableData *data; char buf[2048]; *(&data) = [NSMutableData dataWithCapacity:2048]; *(&bs) = [self->stream isKindOfClass:[NGBufferedStream class]] ? (id)[self->stream retain] : [(NGBufferedStream *)[NGBufferedStream alloc] initWithSource:self->stream]; NS_DURING { while (1 == 1) { unsigned got = [bs readBytes:buf count:2048]; [data appendBytes:buf length:got]; } } NS_HANDLER { if (![localException isKindOfClass:[NGEndOfStreamException class]]) { [bs release]; bs = nil; [localException raise]; } } NS_ENDHANDLER; [bs release]; bs = nil; return data; } - (NSData *)availableData { NSLog(@"NGConcreteStreamFileHandle(availableData) not implemented"); [self notImplemented:_cmd]; return nil; } /* writing */ - (void)writeData:(NSData *)_data { [self->stream safeWriteBytes:[_data bytes] count:[_data length]]; } /* seeking */ - (unsigned long long)seekToEndOfFile { NSLog(@"NGConcreteStreamFileHandle(seekToEndOfFile) not implemented"); [self notImplemented:_cmd]; return 0; } - (void)seekToFileOffset:(unsigned long long)_offset { [(id)stream moveToLocation:_offset]; } - (unsigned long long)offsetInFile { NSLog(@"_NGConcreteFileStreamFileHandle(offsetInFile:) not implemented, abort"); [self notImplemented:_cmd]; return 0; } /* asynchronous operations */ - (void)acceptConnectionInBackgroundAndNotify { NSLog(@"NGConcreteStreamFileHandle(acceptConnectionInBackgroundAndNotify) " @"not implemented"); [self notImplemented:_cmd]; } - (void)acceptConnectionInBackgroundAndNotifyForModes:(NSArray *)_modes { NSLog(@"NGConcreteStreamFileHandle(acceptConnectionInBackgroundAndNotifyForModes:) " @"not implemented"); [self notImplemented:_cmd]; } - (void)readInBackgroundAndNotify { NSLog(@"NGConcreteStreamFileHandle(readInBackgroundAndNotify) not implemented"); [self notImplemented:_cmd]; } - (void)readInBackgroundAndNotifyForModes:(NSArray *)_modes { NSLog(@"NGConcreteStreamFileHandle(readInBackgroundAndNotifyForModes:) " @"not implemented"); [self notImplemented:_cmd]; } - (void)readToEndOfFileInBackgroundAndNotify { NSLog(@"NGConcreteStreamFileHandle(readToEndOfFileInBackgroundAndNotify)" @"not implemented"); [self notImplemented:_cmd]; } - (void)readToEndOfFileInBackgroundAndNotifyForModes:(NSArray *)_modes { NSLog(@"NGConcreteStreamFileHandle(" @"readToEndOfFileInBackgroundAndNotifyForModes:)" @"not implemented"); [self notImplemented:_cmd]; } - (void)waitForDataInBackgroundAndNotify { NSLog(@"NGConcreteStreamFileHandle(" @"waitForDataInBackgroundAndNotify)" @"not implemented"); [self notImplemented:_cmd]; } - (void)waitForDataInBackgroundAndNotifyForModes:(NSArray *)_modes { NSLog(@"NGConcreteStreamFileHandle(" @"waitForDataInBackgroundAndNotifyForModes:)" @"not implemented"); [self notImplemented:_cmd]; } @end /* NGConcreteStreamFileHandle */ SOPE/sope-core/NGStreams/NGByteCountStream.m0000644000000000000000000000541215004363604017557 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "common.h" @implementation NGByteCountStream + (id)byteCounterForStream:(id)_stream byte:(unsigned char)_byte { return [[[self alloc] initWithSource:_stream byte:_byte] autorelease]; } - (id)initWithSource:(id)_source byte:(unsigned char)_byte { if ((self = [super initWithSource:_source])) { [self setByteToCount:_byte]; } return self; } - (id)initWithSource:(id)_source { return [self initWithSource:_source byte:'\n']; } // accessors - (void)setByteToCount:(unsigned char)_byte { if (_byte != byteToCount) { byteReadCount = 0; byteWriteCount = 0; byteToCount = _byte; } } - (unsigned char)byteToCount { return byteToCount; } - (unsigned)readCount { return byteReadCount; } - (unsigned)writeCount { return byteWriteCount; } - (unsigned)totalReadCount { return totalReadCount; } - (unsigned)totalWriteCount { return totalWriteCount; } // operations - (void)resetCounters { totalReadCount = 0; totalWriteCount = 0; byteReadCount = 0; byteWriteCount = 0; } // primitives - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { unsigned result; result = (readBytes != NULL) ? readBytes(source, _cmd, _buf, _len) : [source readBytes:_buf count:_len]; totalReadCount += result; { NSInteger len; register unsigned char *byteBuffer = _buf; for (len = result - 1; len >= 0; len--, byteBuffer++) { if (*byteBuffer == byteToCount) byteReadCount++; } } return result; } - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len { unsigned result; result = (writeBytes != NULL) ? writeBytes(source, _cmd, _buf, _len) : [source writeBytes:_buf count:_len]; totalWriteCount += result; { NSInteger len; register unsigned char *byteBuffer = (unsigned char *)_buf; for (len = result - 1; len >= 0; len--, byteBuffer++) { if (*byteBuffer == byteToCount) byteWriteCount++; } } return result; } @end SOPE/sope-core/NGStreams/NGStreams-Info.plist0000644000000000000000000000134415004363604017675 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable NGStreams CFBundleGetInfoString CFBundleIdentifier org.OpenGroupware.SOPE.core.NGStreams CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType FMWK CFBundleShortVersionString CFBundleSignature ???? CFBundleVersion 4.5 SOPE/sope-core/NGStreams/NGStream.m0000644000000000000000000001524415004363604015726 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "common.h" @implementation NGStream /* primitives */ - (void)setLastException:(NSException *)_exception { [_exception raise]; } - (NSException *)lastException { return nil; } - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { [self subclassResponsibility:_cmd]; return 0; } - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len { [self subclassResponsibility:_cmd]; return 0; } - (BOOL)flush { return YES; } - (BOOL)close { return YES; } - (NGStreamMode)mode { [self subclassResponsibility:_cmd]; return 0; } - (BOOL)isRootStream { [self subclassResponsibility:_cmd]; return NO; } // methods method which write exactly _len bytes - (BOOL)safeReadBytes:(void *)_buf count:(unsigned)_len { return NGSafeReadBytesFromStream(self, _buf, _len); } - (BOOL)safeWriteBytes:(const void *)_buf count:(unsigned)_len { return NGSafeWriteBytesToStream(self, _buf, _len); } /* marking */ - (BOOL)mark { NSLog(@"WARNING: called mark on a stream which doesn't support marking !"); return NO; } - (BOOL)rewind { [NGStreamException raiseWithStream:self reason:@"marking not supported"]; return NO; } - (BOOL)markSupported { return NO; } /* convenience methods */ - (int)readByte { return NGReadByteFromStream(self); } /* description */ - (NSString *)modeDescription { NSString *result = @"unknown"; switch ([self mode]) { case NGStreamMode_undefined: result = @"undefined"; break; case NGStreamMode_readOnly: result = @"r"; break; case NGStreamMode_writeOnly: result = @"w"; break; case NGStreamMode_readWrite: result = @"rw"; break; default: [NGUnknownStreamModeException raiseWithStream:self]; break; } return result; } - (NSString *)description { return [NSString stringWithFormat: @"<%@[0x%p] mode=%@>", NSStringFromClass([self class]), self, [self modeDescription]]; } @end /* NGStream */ @implementation NGStream(DataMethods) - (NSData *)readDataOfLength:(unsigned int)_length { unsigned readCount; char buf[_length]; if (_length == 0) return [NSData data]; readCount = [self readBytes:buf count:_length]; if (readCount == NGStreamError) return nil; return [NSData dataWithBytes:buf length:readCount]; } - (NSData *)safeReadDataOfLength:(unsigned int)_length { char buf[_length]; if (_length == 0) return [NSData data]; if (![self safeReadBytes:buf count:_length]) return nil; return [NSData dataWithBytes:buf length:_length]; } - (unsigned int)writeData:(NSData *)_data { return [self writeBytes:[_data bytes] count:[_data length]]; } - (BOOL)safeWriteData:(NSData *)_data { return [self safeWriteBytes:[_data bytes] count:[_data length]]; } @end /* NGStream(DataMethods) */ // concrete implementations as functions int NGReadByteFromStream(id _stream) { volatile int result = -1; unsigned char c; NS_DURING { int l; l = [_stream readBytes:&c count:sizeof(unsigned char)]; if (l == NGStreamError) { NSException *e = [(id)_stream lastException]; if ([e isKindOfClass:[NGEndOfStreamException class]]) *(&result) = -1; else [e raise]; } else *(&result) = c; } NS_HANDLER { if ([localException isKindOfClass:[NGEndOfStreamException class]]) *(&result) = -1; else [localException raise]; } NS_ENDHANDLER; return result; } BOOL NGSafeReadBytesFromStream(id _in, void *_buf, unsigned _len){ volatile int toBeRead; volatile int readResult; volatile NGIOReadMethodType readBytes; *(&toBeRead) = _len; readBytes = (NGIOReadMethodType) [(NSObject *)_in methodForSelector:@selector(readBytes:count:)]; NS_DURING { void *pos = _buf; while (YES) { *(&readResult) = (unsigned)readBytes(_in, @selector(readBytes:count:), pos, toBeRead); if (readResult == NGStreamError) { /* TODO: improve exception handling ... */ [[(id)_in lastException] raise]; } else if (readResult == toBeRead) { // all bytes were read successfully, return break; } if (readResult < 1) { [NSException raise:NSInternalInconsistencyException format:@"readBytes:count: returned a value < 1"]; } toBeRead -= readResult; pos += readResult; } } NS_HANDLER { if ([localException isKindOfClass:[NGEndOfStreamException class]]) { [[[NGEndOfStreamException alloc] initWithStream:(id)_in readCount:(_len - toBeRead) safeCount:_len data:[NSData dataWithBytes:_buf length:(_len - toBeRead)]] raise]; } else { [localException raise]; } } NS_ENDHANDLER; return YES; } BOOL NGSafeWriteBytesToStream(id _o,const void *_b,unsigned _l) { int toBeWritten = _l; int writeResult; void *pos = (void *)_b; NGIOWriteMethodType writeBytes; writeBytes = (NGIOWriteMethodType) [(NSObject *)_o methodForSelector:@selector(writeBytes:count:)]; while (YES) { writeResult = (int)writeBytes(_o, @selector(writeBytes:count:), pos, toBeWritten); if (writeResult == NGStreamError) { /* remember number of written bytes ??? */ return NO; } else if (writeResult == toBeWritten) { // all bytes were written successfully, return break; } if (writeResult < 1) { [NSException raise:NSInternalInconsistencyException format:@"writeBytes:count: returned a value<1 in %@", _o]; } toBeWritten -= writeResult; pos += writeResult; } return YES; } SOPE/sope-core/NGStreams/COPYING0000644000000000000000000006130315004363604015120 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-core/NGStreams/fhs.make0000644000000000000000000000174415004363604015507 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) FHS_INCLUDE_DIR=$(FHS_INSTALL_ROOT)/include/ FHS_BIN_DIR=$(FHS_INSTALL_ROOT)/bin/ ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib64/ else FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib/ endif fhs-header-dirs :: $(MKDIRS) $(FHS_INCLUDE_DIR)$(libNGStreams_HEADER_FILES_INSTALL_DIR) move-headers-to-fhs :: fhs-header-dirs @echo "moving headers to $(FHS_INCLUDE_DIR) .." mv $(GNUSTEP_HEADERS)$(libNGStreams_HEADER_FILES_INSTALL_DIR)/*.h \ $(FHS_INCLUDE_DIR)$(libNGStreams_HEADER_FILES_INSTALL_DIR)/ NONFHS_LIBDIR="$(GNUSTEP_LIBRARIES)/$(GNUSTEP_TARGET_LDIR)/" NONFHS_LIBNAME="$(LIBRARY_NAME)$(LIBRARY_NAME_SUFFIX)$(SHARED_LIBEXT)" move-libs-to-fhs :: @echo "moving libs to $(FHS_LIB_DIR) .." mv $(NONFHS_LIBDIR)/$(NONFHS_LIBNAME)* $(FHS_LIB_DIR)/ move-to-fhs :: move-headers-to-fhs move-libs-to-fhs after-install :: move-to-fhs endif SOPE/sope-core/NGStreams/NGInternetSocketDomain.m0000644000000000000000000001107615004363604020563 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGInternetSocketDomain.h" #include "NGInternetSocketAddress.h" #include "common.h" #ifndef __MINGW32__ # include #endif @implementation NGInternetSocketDomain static NGInternetSocketDomain *domain = nil; + (void)initialize { if (domain == nil) domain = [[NGInternetSocketDomain alloc] init]; } + (id)domain { return domain; } /* NGSocketDomain */ - (id)addressWithRepresentation:(void *)_data size:(unsigned int)_size { NGInternetSocketAddress *address = nil; if ((unsigned int)[self addressRepresentationSize] != _size) { NSLog(@"%@: invalid address size %i ..", NSStringFromSelector(_cmd), _size); return nil; } address = [[NGInternetSocketAddress allocWithZone:[self zone]] initWithDomain:self internalRepresentation:_data size:_size]; return [address autorelease]; } - (BOOL)prepareAddress:(id)_address forBindWithSocket:(id)_socket { // nothing to prepare return YES; } - (BOOL)cleanupAddress:(id)_address afterCloseOfSocket:(id)_socket { // nothing to cleanup return YES; } - (int)socketDomain { return AF_INET; } - (int)addressRepresentationSize { return sizeof(struct sockaddr_in); } - (int)protocol { return 0; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { /* domain objects are immutable, just retain on copy */ return [self retain]; } /* NSCoding */ - (void)encodeWithCoder:(NSCoder *)_encoder { } - (id)initWithCoder:(NSCoder *)_decoder { [self release]; self = nil; return [domain retain]; } - (id)awakeAfterUsingCoder:(NSCoder *)_decoder { if (self != domain) { [self release]; self = nil; return [domain retain]; } else return self; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"", self]; } @end /* NGInternetSocketDomain */ @implementation NGInternetSocketDomain6 static NGInternetSocketDomain6 *domain6 = nil; + (void)initialize { if (domain6 == nil) domain6 = [[NGInternetSocketDomain6 alloc] init]; } + (id)domain { return domain6; } /* NGSocketDomain */ - (id)addressWithRepresentation:(void *)_data size:(unsigned int)_size { NGInternetSocketAddress *address = nil; if ((unsigned int)[self addressRepresentationSize] != _size) { NSLog(@"%@: invalid address size %i ..", NSStringFromSelector(_cmd), _size); return nil; } address = [[NGInternetSocketAddress allocWithZone:[self zone]] initWithDomain:self internalRepresentation:_data size:_size]; return [address autorelease]; } - (BOOL)prepareAddress:(id)_address forBindWithSocket:(id)_socket { // nothing to prepare return YES; } - (BOOL)cleanupAddress:(id)_address afterCloseOfSocket:(id)_socket { // nothing to cleanup return YES; } - (int)socketDomain { return AF_INET6; } - (int)addressRepresentationSize { return sizeof(struct sockaddr_in6); } - (int)protocol { return 0; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { /* domain objects are immutable, just retain on copy */ return [self retain]; } /* NSCoding */ - (void)encodeWithCoder:(NSCoder *)_encoder { } - (id)initWithCoder:(NSCoder *)_decoder { [self release]; self = nil; return [domain6 retain]; } - (id)awakeAfterUsingCoder:(NSCoder *)_decoder { if (self != domain6) { [self release]; self = nil; return [domain6 retain]; } else return self; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"", self]; } @end /* NGInternetSocketDomain */SOPE/sope-core/NGStreams/README0000644000000000000000000000666215004363604014754 0ustar rootrootSKYRiX IO Streaming Library =========================== Introduction ============ This library contains Objective-C classes to access files and network sockets using a java.io like streaming mechanism. It also abstracts the Unix socket API (that is, we have extensible classes for socket domains, addresses etc) TODO ==== Should we remove serialization ? It's not available with Jaguar (MacOSX 10.2) anymore. Currently is turned off on Jaguar. Removed functionality ===================== Removed in 4.1, available in MOF3: NGUrl related things ... idn't make much sense anymore, now that Foundation has NSURL Defaults: ========= ProfileByteBufferEnabled = NO; Protocols ========= NGSerializer NGActiveSocket NGPositionableStream NGDatagramPacket NGSocketAddress NGSocketDomain Class Hierachy ============== NSObject NGStream < NGStream, NGByteSequenceStream > (serialization) NGFileStream < NGPositionableStream > NGDataStream < NGPositionableStream > NGTaskStream NGFilterStream NGBase64Stream NGBufferedStream NGByteBuffer NGByteCountStream NGLockingStream NGSocket < NGSocket > NGActiveSocket < NGActiveSocket > (serialization) < NGSerializer > NGPassiveSocket < NGPassiveSocket > NGDatagramSocket NGTextStream < NGExtendedTextStream > NGStringTextStream NGCTextStream NGFilterTextStream NGCharBuffer NGDatagramPacket < NGDatagramPacket > NGInternetSocketAddress < NSCopying, NSCoding, NGSocketAddress > NGInternetSocketDomain < NSCoding, NSCopying, NGSocketDomain > NGLocalSocketAddress < NSCopying, NGSocketAddress > NGLocalSocketDomain < NSCopying, NSCoding, NGSocketDomain > NSFileHandle NGConcreteStreamFileHandle NSCoder NGStreamCoder < NSObjCTypeSerializationCallBack > NSPipe NGStreamPipe < NGStream, NGByteSequenceStream > Exceptions ========== NSException NGIOException NGStreamException NGEndOfStreamException NGSocketShutdownException NGSocketShutdownDuringReadException NGSocketShutdownDuringWriteException NGSocketTimedOutException NGSocketConnectionResetException NGCouldNotOpenStreamException NGCouldNotCloseStreamException NGStreamNotOpenException NGStreamErrorException NGStreamReadErrorException NGStreamWriteErrorException NGStreamSeekErrorException NGStreamModeException NGUnknownStreamModeException NGReadOnlyStreamException NGWriteOnlyStreamException NGIOAccessException NGIOSearchAccessException NGSocketException NGCouldNotResolveHostNameException NGDidNotFindServiceException NGInvalidSocketDomainException NGCouldNotCreateSocketException NGSocketBindException NGSocketAlreadyBoundException NGCouldNotBindSocketException NGSocketConnectException NGSocketNotConnectedException NGSocketAlreadyConnectedException NGCouldNotConnectException NGSocketIsAlreadyListeningException NGCouldNotListenException NGCouldNotAcceptException NGSocketOptionException NGCouldNotSetSocketOptionException NGCouldNotGetSocketOptionException SOPE/sope-core/NGStreams/NGTaskStream.m0000644000000000000000000000422315004363604016544 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" #include "common.h" #include "NGTaskStream.h" @implementation NGTaskStream - (id)initWithPath:(NSString *)_executable arguments:(NSArray *)_args environment:(NSDictionary *)_env { return nil; } - (void)dealloc { [super dealloc]; } /* state */ - (BOOL)isOpen { return [self->task isRunning]; } /* primitives */ - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { return NGStreamError; } - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len { return NGStreamError; } - (BOOL)close { if (![self isOpen]) { NSLog(@"tried to close already closed stream %@", self); return NO; } [self->task terminate]; return YES; } - (NGStreamMode)mode { return NGStreamMode_readWrite; } - (BOOL)isRootStream { return YES; } /* marking */ - (BOOL)mark { NSLog(@"WARNING: called mark on a stream which doesn't support marking !"); return NO; } - (BOOL)rewind { [[[NGStreamException alloc] initWithStream:self reason:@"marking not supported"] raise]; return NO; } - (BOOL)markSupported { return -1; } /* description */ - (NSString *)description { return [NSString stringWithFormat: @"<%@[0x%p] task=%@ mode=%@>", NSStringFromClass([self class]), (unsigned)self, self->task, [self modeDescription]]; } @end /* NGTaskStream */ SOPE/sope-core/NGStreams/config.h.in0000644000000000000000000001344015004363604016107 0ustar rootroot#ifndef __config_h__ #define __config_h__ /* Define if system calls automatically restart after interruption by a signal. */ #undef HAVE_RESTARTABLE_SYSCALLS /* Define if you have the gethostbyname_r function. */ #undef HAVE_GETHOSTBYNAME_R /* Define if you have the gethostbyaddr_r function. */ #undef HAVE_GETHOSTBYADDR_R /* Define if you have the gethostent_r function. */ #undef HAVE_GETHOSTENT_R /* Define if you have posix mmap function. */ #undef HAVE_MMAP /* Define if you have the getcwd function */ #undef HAVE_GETCWD /* Define if you have the getuid function */ #undef HAVE_GETUID /* Define if you have the getpwnam function */ #undef HAVE_GETPWNAM /* Define if you have the getpwuid function */ #undef HAVE_GETPWUID /* Define if you have the kill function */ #undef HAVE_KILL /* Define if you have the statvfs function */ #undef HAVE_STATVFS /* Define if you have the poll function */ #undef HAVE_POLL /* Define if you have the chown function */ #undef HAVE_CHOWN /* Define if you have the symlink function */ #undef HAVE_SYMLINK /* Define if you have the readlink function */ #undef HAVE_READLINK /* Define if you have the fsync function */ #undef HAVE_FSYNC /* Define if you have the opendir family of functions */ #undef HAVE_OPENDIR /* Define if you have the isatty function */ #undef HAVE_ISATTY /* Define if you have the ttyname function */ #undef HAVE_TTYNAME /* Define if you have the ttyname_r function */ #undef HAVE_TTYNAME_R /* Define if you have the header file. */ #undef HAVE_STRING_H /* Define if you have the header file. */ #undef HAVE_STRINGS_H /* Define if you have the header file */ #undef HAVE_MEMORY_H /* Define if you have the header file. */ #undef HAVE_STDLIB_H /* Define if you have the header file. */ #undef HAVE_LIMITS_H /* Define if you have the header file. */ #undef HAVE_LIBC_H /* Define if you have the header file */ #undef HAVE_SYS_STAT_H /* Define if you have the header file */ #undef HAVE_SYS_FCNTL_H /* Define if you have the header file */ #undef HAVE_FCNTL_H /* Define if you have the header file */ #undef HAVE_SYS_VFS_H /* Define if you have the header file */ #undef HAVE_SYS_STATFS_H /* Define if you have the header file */ #undef HAVE_SYS_STATVFS_H /* Define if you have the header file */ #undef HAVE_POLL_H /* Define if you have the header file */ #undef HAVE_SYS_POLL_H /* Define if you have the header file */ #undef HAVE_SYS_SOCKET_H /* Define if you have the header file */ #undef HAVE_UNISTD_H /* Define if you have the header file */ #undef HAVE_SYS_IOCTL_H /* Define if you have the header file */ #undef HAVE_SYS_FILIO_H /* Define if you have the header file */ #undef HAVE_NETINET_IN_H /* Define if you have the header file */ #undef HAVE_NETDB_H /* Define if you have the header file */ #undef HAVE_WINDOWS_H /* Define if you have the header file */ #undef HAVE_WINSOCK_H /* Define if you have the header file */ #undef HAVE_WINDOWS32_SOCKETS_H /* Define if you have the header file */ #undef HAVE_PWD_H /* Define if you have the header file */ #undef HAVE_PROCESS_H /* Define if you have the header file */ #undef HAVE_GRP_H /* Define if you have the header file */ #undef HAVE_SYS_FILE_H /* Define if you have the header file */ #undef HAVE_SYS_SELECT_H /* Define if you have the header file */ #undef HAVE_TIME_H /* Define if you have the header file */ #undef HAVE_SYS_TIME_H /* Define if you have the header file */ #undef HAVE_SYS_TYPES_H /* Define if you have the header file */ #undef HAVE_UTIME_H /* Define if you have the header file */ #undef HAVE_SYS_ERRNO_H /* Define if sys/wait.h is POSIX compatible */ #undef HAVE_SYS_WAIT_H /* Define this if you have the header file */ #undef HAVE_VFORK_H /* Define for vfork in case it's not defined */ #undef vfork /* Define for pid_t in case it's not defined */ #undef pid_t /* The following macros deal with directory entries. */ #undef HAVE_DIRENT_H #undef HAVE_SYS_NDIR_H #undef HAVE_SYS_DIR_H #undef HAVE_NDIR_H #undef HAVE_DIR_H /* The structure alignment as determined by configure */ #define STRUCT_ALIGNMENT @STRUCT_ALIGNMENT@ /* The name of the target platform, obtained by configure */ #define TARGET_PLATFORM "@host@" /* define POLL constants */ #if HAVE_POLL_H # include #endif #if HAVE_SYS_POLL_H # include #endif #ifndef POLLIN # ifdef HAVE_POLL # warning "manually declared POLLIN=1 .." # endif # define POLLIN 1 #endif #ifndef POLLOUT # ifdef HAVE_POLL # warning "manually declared POLLOUT=2 .." # endif # define POLLOUT 2 #endif #ifndef POLLERR # ifdef HAVE_POLL # warning "manually declared POLLERR=4 .." # endif # define POLLERR 4 #endif #ifndef POLLRDNORM # ifdef linux # define POLLRDNORM POLLIN # else /* !linux */ # ifdef POLLIN # ifdef HAVE_POLL # warning "manually declared POLLRDNORM=POLLIN .." # endif # define POLLRDNORM POLLIN # else # ifdef HAVE_POLL # warning "manually declared POLLRDNORM .." # endif # define POLLRDNORM 1 # endif # endif /* !linux */ #endif #ifndef POLLWRNORM # ifdef linux # define POLLWRNORM POLLOUT # else /* !linux */ # ifdef POLLOUT # ifdef HAVE_POLL # warning "manually declared POLLWRNORM=POLLOUT .." # endif # define POLLWRNORM POLLOUT # else # ifdef HAVE_POLL # warning "manually declared POLLWRNORM .." # endif # define POLLWRNORM 2 # endif # endif /* !linux */ #endif #endif /* __config_h__ */ SOPE/sope-core/NGStreams/GNUmakefile.postamble0000644000000000000000000000062015004363604020117 0ustar rootroot# compilation settings before-all :: config.status after-distclean:: rm -f config.cache config.log config.status config.h config.mak config.h config.status : config.h.in configure ./configure ifneq ($(GNUSTEP_TARGET_OS),cygwin32) configure : configure.in #autoconf configure.in > configure echo "configure.in seems to have changed, you might want to rerun autoconf" chmod +x configure endif SOPE/sope-core/NGStreams/NGFilterTextStream.m0000644000000000000000000000253415004363604017737 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "common.h" @implementation NGFilterTextStream + (id)textFilterWithSource:(id)_s { return [[(NGFilterTextStream *)[self alloc] initWithSource:_s] autorelease]; } - (id)initWithSource:(id)_source { if ((self = [super init])) { self->source = [_source retain]; } return self; } - (id)init { return [self initWithSource:nil]; } - (void)dealloc { [self->source release]; [super dealloc]; } /* accessors */ - (id)source { return self->source; } @end /* NGFilterTextStream */ SOPE/sope-core/NGStreams/NGActiveSocket+serialization.m0000644000000000000000000000627015004363604021727 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGActiveSocket+serialization.h" #include "common.h" @implementation NGActiveSocket(serialization) // serialization - (void)serializeChar:(char)_value { NGStreamSerializeObjC(self, &_value, @encode(char), nil); } - (void)serializeShort:(short)_value { NGStreamSerializeObjC(self, &_value, @encode(short), nil); } - (void)serializeInt:(int)_value { NGStreamSerializeObjC(self, &_value, @encode(int), nil); } - (void)serializeLong:(long)_value { NGStreamSerializeObjC(self, &_value, @encode(long), nil); } - (void)serializeFloat:(float)_value { NGStreamSerializeObjC(self, &_value, @encode(float), nil); } - (void)serializeDouble:(double)_value { NGStreamSerializeObjC(self, &_value, @encode(double), nil); } - (void)serializeLongLong:(long long)_value { NGStreamSerializeObjC(self, &_value, @encode(long long), nil); } - (void)serializeCString:(const char *)_value { NGStreamSerializeObjC(self, &_value, @encode(char *), nil); } #if USE_SERIALIZER - (void)serializeDataAt:(const void*)_value ofObjCType:(const char*)_type context:(id)_callback { NGStreamSerializeObjC(self, _value, _type, _callback); } #endif // deserialization - (char)deserializeChar { char c; NGStreamDeserializeObjC(self, &c, @encode(char), nil); return c; } - (short)deserializeShort { short s; NGStreamDeserializeObjC(self, &s, @encode(short), nil); return s; } - (int)deserializeInt { int i; NGStreamDeserializeObjC(self, &i, @encode(int), nil); return i; } - (long)deserializeLong { long l; NGStreamDeserializeObjC(self, &l, @encode(long), nil); return l; } - (float)deserializeFloat { float f; NGStreamDeserializeObjC(self, &f, @encode(float), nil); return f; } - (double)deserializeDouble { double d; NGStreamDeserializeObjC(self, &d, @encode(double), nil); return d; } - (long long)deserializeLongLong { long long l; NGStreamDeserializeObjC(self, &l, @encode(long long), nil); return l; } - (char *)deserializeCString { char *result = NULL; NGStreamDeserializeObjC(self, &result, @encode(char *), nil); return result; } #if USE_SERIALIZER - (void)deserializeDataAt:(void *)_value ofObjCType:(const char *)_type context:(id)_callback { NGStreamDeserializeObjC(self, _value, _type, _callback); } #endif @end /* NGActiveSocket(serialization) */ void __link_NGActiveSocket_serialization(void) { __link_NGActiveSocket_serialization(); } SOPE/sope-core/NGStreams/NGStream+serialization.m0000644000000000000000000002261115004363604020573 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" #if !defined(WIN32) # if HAVE_SYS_TYPES_H # include # endif # if HAVE_SYS_SOCKET_H # include # endif # if HAVE_NETINET_IN_H # include # endif # include #endif #include "common.h" #include "NGStream+serialization.h" #if NeXT_RUNTIME # include #endif @implementation NGStream(serialization) // serialization - (void)serializeChar:(char)_value { NGStreamSerializeObjC(self, &_value, @encode(char), nil); } - (void)serializeShort:(short)_value { NGStreamSerializeObjC(self, &_value, @encode(short), nil); } - (void)serializeInt:(int)_value { NGStreamSerializeObjC(self, &_value, @encode(int), nil); } - (void)serializeLong:(long)_value { NGStreamSerializeObjC(self, &_value, @encode(long), nil); } - (void)serializeFloat:(float)_value { NGStreamSerializeObjC(self, &_value, @encode(float), nil); } - (void)serializeDouble:(double)_value { NGStreamSerializeObjC(self, &_value, @encode(double), nil); } - (void)serializeLongLong:(long long)_value { NGStreamSerializeObjC(self, &_value, @encode(long long), nil); } - (void)serializeCString:(const char *)_value { NGStreamSerializeObjC(self, &_value, @encode(char *), nil); } #if USE_SERIALIZER - (void)serializeDataAt:(const void*)_value ofObjCType:(const char*)_type context:(id)_callback { NGStreamSerializeObjC(self, _value, _type, _callback); } #endif // deserialization - (char)deserializeChar { char c; NGStreamDeserializeObjC(self, &c, @encode(char), nil); return c; } - (short)deserializeShort { short s; NGStreamDeserializeObjC(self, &s, @encode(short), nil); return s; } - (int)deserializeInt { int i; NGStreamDeserializeObjC(self, &i, @encode(int), nil); return i; } - (long)deserializeLong { long l; NGStreamDeserializeObjC(self, &l, @encode(long), nil); return l; } - (float)deserializeFloat { float f; NGStreamDeserializeObjC(self, &f, @encode(float), nil); return f; } - (double)deserializeDouble { double d; NGStreamDeserializeObjC(self, &d, @encode(double), nil); return d; } - (long long)deserializeLongLong { long long l; NGStreamDeserializeObjC(self, &l, @encode(long long), nil); return l; } - (char *)deserializeCString { char *result = NULL; NGStreamDeserializeObjC(self, &result, @encode(char *), nil); return result; } #if USE_SERIALIZER - (void)deserializeDataAt:(void *)_value ofObjCType:(const char *)_type context:(id)_callback { NGStreamDeserializeObjC(self, _value, _type, _callback); } #endif @end void NGStreamSerializeObjC(id self, const void *_value, const char *_type, #if USE_SERIALIZER id _callback #else id _callback #endif ) { switch (*_type) { case _C_ID: case _C_CLASS: [_callback serializeObjectAt:(id *)_value ofObjCType:_type intoData:(NSMutableData *)self]; break; case _C_CHARPTR: { const char *cstr = *(char **)_value; int len = cstr ? (int)strlen(cstr) : -1; NGStreamSerializeObjC(self, &len, @encode(int), _callback); if (cstr) [self safeWriteBytes:cstr count:len]; break; } case _C_ARY_B: { int i, offset, itemSize, count; count = atoi(_type + 1); // skip '[' and get dimension while (isdigit((int)*++_type)) ; // skip '[' and dimension itemSize = objc_sizeof_type(_type); for (i = offset = 0; i < count; i++, offset += itemSize) NGStreamSerializeObjC(self, (char *)_value + offset, _type, _callback); break; } case _C_STRUCT_B: { int offset = 0; while ((*_type != _C_STRUCT_E) && (*_type++ != '=')) ; // skip '=' while (YES) { NGStreamSerializeObjC(self, (char *)_value + offset, _type, _callback); offset += objc_sizeof_type(_type); _type = objc_skip_typespec(_type); if (*_type != _C_STRUCT_E) { int align, remainder; align = objc_alignof_type(_type); if ((remainder = offset % align)) offset += align - remainder; } else // done with structure break; } break; } case _C_PTR: NGStreamSerializeObjC(self, *(char **)_value, _type + 1, _callback); break; case _C_CHR: case _C_UCHR: [self safeWriteBytes:_value count:1]; break; case _C_SHT: case _C_USHT: { short netValue = htons(*(short *)_value); [self safeWriteBytes:&netValue count:2]; break; } case _C_INT: case _C_UINT: { int netValue = htonl(*(int *)_value); [self safeWriteBytes:&netValue count:4]; break; } case _C_LNG: case _C_ULNG: { long netValue = htonl(*(long *)_value); [self safeWriteBytes:&netValue count:sizeof(long)]; break; } case _C_FLT: { union fconv { float value; unsigned long ul; } fc; fc.value = *(float *)_value; fc.ul = htonl(fc.ul); [self safeWriteBytes:&fc count:sizeof(unsigned long)]; break; } case _C_DBL: { [self safeWriteBytes:_value count:8]; break; } default: NSCAssert1(0, @"unsupported C type %s ..", _type); break; } } void NGStreamDeserializeObjC(id self, void *_value, const char *_type, #if USE_SERIALIZER id _callback #else id _callback #endif ) { if ((_value == NULL) || (_type == NULL)) return; switch (*_type) { case _C_ID: case _C_CLASS: [_callback deserializeObjectAt:(id *)_value ofObjCType:_type fromData:(NSData *)self atCursor:0]; break; case _C_CHARPTR: { // malloced C-string int len = -1; NGStreamDeserializeObjC(self, &len, @encode(int), _callback); if (len == -1) // NULL-string *(char **)_value = NULL; else { char *result = NULL; #if LIB_FOUNDATION_LIBRARY result = NSZoneMallocAtomic(NULL, len + 1); #else result = NSZoneMalloc(NULL, len + 1); #endif result[len] = '\0'; if (len > 0) [self safeReadBytes:result count:len]; *(char **)_value = result; } break; } case _C_ARY_B: { int i, offset, itemSize, count; count = atoi(_type + 1); // skip '[' and get dimension while (isdigit((int)*++_type)) ; // skip '[' and dimension itemSize = objc_sizeof_type(_type); for (i = offset = 0; i < count; i++, offset += itemSize) NGStreamDeserializeObjC(self, (char *)_value + offset, _type, _callback); break; } case _C_STRUCT_B: { int offset = 0; while ((*_type != _C_STRUCT_E) && (*_type++ != '=')) ; // skip '=' while (YES) { NGStreamDeserializeObjC(self, (char *)_value + offset, _type, _callback); offset += objc_sizeof_type(_type); _type = objc_skip_typespec(_type); if (*_type != _C_STRUCT_E) { int align, remainder; align = objc_alignof_type(_type); if ((remainder = offset % align)) offset += align - remainder; } else // done with structure break; } break; } case _C_PTR: { // skip '^', type of the value the ptr points to void *result = NULL; result = NSZoneMalloc(NULL, objc_sizeof_type(_type + 1)); NGStreamDeserializeObjC(self, result, _type + 1, _callback); *(char **)_value = result; result = NULL; break; } case _C_CHR: case _C_UCHR: [self safeReadBytes:_value count:1]; break; case _C_SHT: case _C_USHT: [self safeReadBytes:_value count:2]; *(short *)_value = ntohs(*(short *)_value); break; case _C_INT: case _C_UINT: [self safeReadBytes:_value count:4]; *(int *)_value = ntohl(*(int *)_value); break; case _C_LNG: case _C_ULNG: [self safeReadBytes:_value count:4]; *(long *)_value = ntohl(*(long *)_value); break; case _C_FLT: { [self safeReadBytes:_value count:4]; *(long *)_value = ntohl(*(long *)_value); break; } case _C_DBL: { [self safeReadBytes:_value count:8]; break; } default: NSLog(@"unsupported C type %s ..", _type); break; } } void __link_NGStream_serialization(void) { __link_NGStream_serialization(); } SOPE/sope-core/NGStreams/NGStreamCoder.m0000644000000000000000000010212315004363604016674 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" #include "common.h" #include "NGStreamCoder.h" #include "NGStream+serialization.h" #if APPLE_RUNTIME || NeXT_RUNTIME # include #endif #define FINAL static inline extern id nil_method(id, SEL, ...); /* Debugging topics: encoder decoder */ typedef unsigned char NGTagType; #define REFERENCE 128 #define VALUE 127 static unsigned __NGHashPointer(void *table, const void *anObject) { return (unsigned)((long)anObject / 4); } static BOOL __NGComparePointers(void *table, const void *anObject1, const void *anObject2) { return anObject1 == anObject2 ? YES : NO; } static void __NGRetainObjects(void *table, const void *anObject) { (void)[(NSObject*)anObject retain]; } static void __NGReleaseObjects(void *table, void *anObject) { [(NSObject*)anObject release]; } static NSString* __NGDescribePointers(void *table, const void *anObject) { return [NSString stringWithFormat:@"%p", anObject]; } static NSMapTableKeyCallBacks NGIdentityObjectMapKeyCallbacks = { (unsigned(*)(NSMapTable *, const void *)) __NGHashPointer, (BOOL(*)(NSMapTable *, const void *, const void *))__NGComparePointers, (void (*)(NSMapTable *, const void *anObject)) __NGRetainObjects, (void (*)(NSMapTable *, void *anObject)) __NGReleaseObjects, (NSString *(*)(NSMapTable *, const void *)) __NGDescribePointers, (const void *)NULL }; static const char *NGCoderSignature = "MDlink NGStreamCoder"; static int NGCoderVersion = 1100; @implementation NGStreamCoder static NSMapTable *classToAliasMappings = NULL; // archive name => decoded name + (void)initialize { BOOL isInitialized = NO; if (!isInitialized) { isInitialized = YES; classToAliasMappings = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 19); } } + (id)coderWithStream:(id)_stream { return AUTORELEASE([[self alloc] initWithStream:_stream]); } - (id)initWithStream:(id)_stream mode:(NGStreamMode)_mode { if ((self = [super init])) { self->stream = [_stream retain]; self->classForCoder = @selector(classForCoder); self->replObjectForCoder = @selector(replacementObjectForCoder:); if ([self->stream isKindOfClass:[NSObject class]]) { self->readIMP = (NGIOSafeReadMethodType) [(NSObject*)self->stream methodForSelector:@selector(safeReadBytes:count:)]; self->writeIMP = (NGIOSafeWriteMethodType) [(NSObject*)self->stream methodForSelector:@selector(safeWriteBytes:count:)]; } if (NGCanReadInStreamMode(_mode)) { // setup decoder self->inObjects = NSCreateMapTable(NSIntMapKeyCallBacks, NSObjectMapValueCallBacks, 119); self->inClasses = NSCreateMapTable(NSIntMapKeyCallBacks, NSObjectMapValueCallBacks, 19); self->inPointers = NSCreateMapTable(NSIntMapKeyCallBacks, NSIntMapValueCallBacks, 19); self->inClassAlias = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 19); self->inClassVersions = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 19); } if (NGCanWriteInStreamMode(_mode)) { // setup encoder self->outObjects = NSCreateHashTable(NSNonOwnedPointerHashCallBacks, 119); self->outConditionals = NSCreateHashTable(NSNonOwnedPointerHashCallBacks, 119); self->outPointers = NSCreateHashTable(NSNonOwnedPointerHashCallBacks, 0); self->replacements = NSCreateMapTable(NGIdentityObjectMapKeyCallbacks, NSObjectMapValueCallBacks, 19); } } return self; } - (id)init { return [self initWithStream:nil mode:NGStreamMode_undefined]; } - (id)initWithStream:(id)_stream { return [self initWithStream:_stream mode:[_stream mode]]; } - (void)dealloc { // release encoding restreams if (self->outObjects) { NSFreeHashTable(self->outObjects); self->outObjects = NULL; } if (self->outConditionals) { NSFreeHashTable(self->outConditionals); self->outConditionals = NULL; } if (self->outPointers) { NSFreeHashTable(self->outPointers); self->outPointers = NULL; } if (self->replacements) { NSFreeMapTable(self->replacements); self->replacements = NULL; } // release decoding restreams if (self->inObjects) { NSFreeMapTable(self->inObjects); self->inObjects = NULL; } if (self->inClasses) { NSFreeMapTable(self->inClasses); self->inClasses = NULL; } if (self->inPointers) { NSFreeMapTable(self->inPointers); self->inPointers = NULL; } if (self->inClassAlias) { NSFreeMapTable(self->inClassAlias); self->inClassAlias = NULL; } if (self->inClassVersions) { NSFreeMapTable(self->inClassVersions); self->inClassVersions = NULL; } [self->stream release]; self->stream = nil; [super dealloc]; } /* accessors */ - (id)stream { return self->stream; } - (NSString *)coderSignature { return [NSString stringWithCString:NGCoderSignature]; } - (int)coderVersion { return NGCoderVersion; } - (unsigned int)systemVersion { return self->inArchiverVersion; } // misc FINAL BOOL isBaseType(const char *_type) { switch (*_type) { case _C_CHR: case _C_UCHR: case _C_SHT: case _C_USHT: case _C_INT: case _C_UINT: case _C_LNG: case _C_ULNG: case _C_FLT: case _C_DBL: return YES; default: return NO; } } FINAL BOOL isReferenceTag(NGTagType _tag) { return (_tag & REFERENCE) ? YES : NO; } FINAL NGTagType tagValue(NGTagType _tag) { return _tag & VALUE; // mask out bit 8 } FINAL int _archiveIdOfObject(NGStreamCoder *self, id _object) { return (_object == nil) ? 0 : (int)_object; } FINAL int _archiveIdOfClass(NGStreamCoder *self, Class _class) { return _archiveIdOfObject(self, _class); } // primitive encoding FINAL void _writeBytes(NGStreamCoder *self, const void *_bytes, unsigned _len); FINAL void _writeTag (NGStreamCoder *self, NGTagType _tag); FINAL void _writeChar (NGStreamCoder *self, char _value); FINAL void _writeShort(NGStreamCoder *self, short _value); FINAL void _writeInt (NGStreamCoder *self, int _value); FINAL void _writeLong (NGStreamCoder *self, long _value); FINAL void _writeFloat(NGStreamCoder *self, float _value); FINAL void _writeCString(NGStreamCoder *self, const char *_value); FINAL void _writeObjC(NGStreamCoder *self, const void *_value, const char *_type); // primitive decoding FINAL void _readBytes(NGStreamCoder *self, void *_bytes, unsigned _len); FINAL NGTagType _readTag(NGStreamCoder *self); FINAL char _readChar (NGStreamCoder *self); FINAL short _readShort(NGStreamCoder *self); FINAL int _readInt (NGStreamCoder *self); FINAL long _readLong (NGStreamCoder *self); FINAL float _readFloat(NGStreamCoder *self); FINAL char *_readCString(NGStreamCoder *self); FINAL void _readObjC(NGStreamCoder *self, void *_value, const char *_type); // -------------------- encoding -------------------- - (void)beginEncoding { self->traceMode = NO; self->encodingRoot = YES; } - (void)endEncoding { NSResetHashTable(self->outObjects); NSResetHashTable(self->outConditionals); NSResetHashTable(self->outPointers); NSResetMapTable(self->replacements); self->traceMode = NO; self->encodingRoot = NO; } - (void)writeArchiveHeader { if (self->didWriteHeader == NO) { _writeCString(self, [[self coderSignature] cString]); _writeInt(self, [self coderVersion]); self->didWriteHeader = YES; } } - (void)writeArchiveTrailer { } - (void)traceObjectsWithRoot:(id)_root { // encoding pass 1 NS_DURING { self->traceMode = YES; [self encodeObject:_root]; } NS_HANDLER { self->traceMode = NO; NSResetHashTable(self->outObjects); [localException raise]; } NS_ENDHANDLER; self->traceMode = NO; NSResetHashTable(self->outObjects); } - (void)encodeObjectsWithRoot:(id)_root { // encoding pass 2 [self encodeObject:_root]; } - (void)encodeRootObject:(id)_object { NSAutoreleasePool *pool = [[NSAutoreleasePool allocWithZone:[self zone]] init]; [self beginEncoding]; NS_DURING { /* * Prepare for writing the graph objects for which `rootObject' is the root * node. The algorithm consists from two passes. In the first pass it * determines the nodes so-called 'conditionals' - the nodes encoded *only* * with -encodeConditionalObject:. They represent nodes that are not * related directly to the graph. In the second pass objects are encoded * normally, except for the conditional objects which are encoded as nil. */ // pass1: start tracing for conditionals [self traceObjectsWithRoot:_object]; // pass2: start writing [self writeArchiveHeader]; [self encodeObjectsWithRoot:_object]; [self writeArchiveTrailer]; } NS_HANDLER { [self endEncoding]; // release resources [localException raise]; } NS_ENDHANDLER; [self endEncoding]; // release resources [pool release]; pool = nil; } - (void)encodeConditionalObject:(id)_object { if (self->traceMode) { // pass 1 /* * This is the first pass of the determining the conditionals * algorithm. We traverse the graph and insert into the `conditionals' * set. In the second pass all objects that are still in this set will * be encoded as nil when they receive -encodeConditionalObject:. An * object is removed from this set when it receives -encodeObject:. */ if (_object) { if (NSHashGet(self->outObjects, _object)) // object isn't conditional any more .. (was stored using encodeObject:) ; else if (NSHashGet(self->outConditionals, _object)) // object is already stored as conditional ; else // insert object in conditionals set NSHashInsert(self->outConditionals, _object); } } else { // pass 2 BOOL isConditional; isConditional = (NSHashGet(self->outConditionals, _object) != nil); // If anObject is still in the `conditionals' set, it is encoded as nil. [self encodeObject:isConditional ? nil : _object]; } } - (void)_traceObject:(id)_object { if (_object == nil) // don't trace nil objects .. return; if (NSHashGet(self->outObjects, _object) == nil) { // object wasn't traced yet // Look-up the object in the `conditionals' set. If the object is // there, then remove it because it is no longer a conditional one. if (NSHashGet(self->outConditionals, _object)) { // object was marked conditional .. NSHashRemove(self->outConditionals, _object); } // mark object as traced NSHashInsert(self->outObjects, _object); if (object_is_instance(_object)) { Class archiveClass = Nil; id replacement = nil; replacement = [_object performSelector:self->replObjectForCoder withObject:self]; if (replacement != _object) { NSMapInsert(self->replacements, _object, replacement); _object = replacement; } if (object_is_instance(_object)) { archiveClass = [_object performSelector:self->classForCoder withObject:self]; } [self encodeObject:archiveClass]; [_object encodeWithCoder:self]; } else { // there are no class-variables .. } } } - (void)_encodeObject:(id)_object { NGTagType tag; int archiveId = _archiveIdOfObject(self, _object); tag = object_is_instance(_object) ? _C_ID : _C_CLASS; if (_object == nil) { // nil object #if 0 NSLog(@"encoding nil reference .."); #endif _writeTag(self, tag | REFERENCE); _writeInt(self, archiveId); } else if (NSHashGet(self->outObjects, _object)) { // object was already written #if 0 if (tag == _C_CLASS) { NSLog(@"encoding reference to class <%s> ..", class_get_class_name(_object)); } else { NSLog(@"encoding reference to object 0x%p<%s> ..", _object, class_get_class_name(*(Class *)_object)); } #endif _writeTag(self, tag | REFERENCE); _writeInt(self, archiveId); } else { // mark object as written NSHashInsert(self->outObjects, _object); #if 0 if (tag == _C_CLASS) { // a class object NSLog( @"encoding class %s:%i ..", class_get_class_name(_object), [_object version]); } else { NSLog(@"encoding object 0x%p<%s> ..", _object, class_get_class_name(*(Class *)_object)); } #endif _writeTag(self, tag); _writeInt(self, archiveId); if (tag == _C_CLASS) { // a class object _writeCString(self, class_get_class_name(_object)); _writeInt(self, [_object version]); } else { Class archiveClass = Nil; id replacement = nil; replacement = NSMapGet(self->replacements, _object); if (replacement) _object = replacement; /* _object = [_object performSelector:self->replObjectForCoder withObject:self]; */ archiveClass = [_object performSelector:self->classForCoder withObject:self]; // class of replacement NSAssert(archiveClass, @"no archive class found .."); [self encodeObject:archiveClass]; [_object encodeWithCoder:self]; } } } - (void)encodeObject:(id)_object { if (self->encodingRoot) { [self encodeValueOfObjCType:object_is_instance(_object) ? "@" : "#" at:&_object]; } else { [self encodeRootObject:_object]; } } - (void)_traceValueOfObjCType:(const char *)_type at:(const void *)_value { #if 0 NSLog(@"tracing value of ObjC-type '%s'", _type); #endif switch (*_type) { case _C_ID: case _C_CLASS: [self _traceObject:*(id *)_value]; break; case _C_ARY_B: { int count = atoi(_type + 1); // eg '[15I' => count = 15 const char *itemType = _type; while(isdigit((int)*(++itemType))) ; // skip dimension [self encodeArrayOfObjCType:itemType count:count at:_value]; break; } case _C_STRUCT_B: { // C-structure begin '{' int offset = 0; while ((*_type != _C_STRUCT_E) && (*_type++ != '=')); // skip "=" while (YES) { [self encodeValueOfObjCType:_type at:((char *)_value) + offset]; offset += objc_sizeof_type(_type); _type = objc_skip_typespec(_type); if(*_type != _C_STRUCT_E) { // C-structure end '}' int align, remainder; align = objc_alignof_type(_type); if((remainder = offset % align)) offset += (align - remainder); } else break; } break; } } } - (void)_encodeValueOfObjCType:(const char *)_type at:(const void *)_value { switch (*_type) { case _C_ID: case _C_CLASS: // ?? Write another tag just to be possible to read using the // ?? decodeObject method. (Otherwise a lookahead would be required) // ?? _writeTag(self, *_type); [self _encodeObject:*(id *)_value]; break; case _C_ARY_B: { int count = atoi(_type + 1); // eg '[15I' => count = 15 const char *itemType = _type; while(isdigit((int)*(++itemType))) ; // skip dimension // Write another tag just to be possible to read using the // decodeArrayOfObjCType:count:at: method. _writeTag(self, _C_ARY_B); [self encodeArrayOfObjCType:itemType count:count at:_value]; break; } case _C_STRUCT_B: { // C-structure begin '{' int offset = 0; _writeTag(self, '{'); while ((*_type != _C_STRUCT_E) && (*_type++ != '=')); // skip "=" while (YES) { [self encodeValueOfObjCType:_type at:((char *)_value) + offset]; offset += objc_sizeof_type(_type); _type = objc_skip_typespec(_type); if(*_type != _C_STRUCT_E) { // C-structure end '}' int align, remainder; align = objc_alignof_type(_type); if((remainder = offset % align)) offset += (align - remainder); } else break; } break; } case _C_SEL: _writeTag(self, _C_SEL); _writeCString(self, (*(SEL *)_value) ? sel_getName(*(SEL *)_value) : NULL); break; case _C_PTR: _writeTag(self, *_type); _writeObjC(self, *(char **)_value, _type + 1); break; case _C_CHARPTR: _writeTag(self, *_type); _writeObjC(self, _value, _type); break; case _C_CHR: case _C_UCHR: case _C_SHT: case _C_USHT: case _C_INT: case _C_UINT: case _C_LNG: case _C_ULNG: case _C_FLT: case _C_DBL: _writeTag(self, *_type); _writeObjC(self, _value, _type); break; default: NSLog(@"unsupported C type '%s' ..", _type); break; } } - (void)encodeValueOfObjCType:(const char *)_type at:(const void *)_value { if (self->traceMode) [self _traceValueOfObjCType:_type at:_value]; else { if (self->didWriteHeader == NO) [self writeArchiveHeader]; [self _encodeValueOfObjCType:_type at:_value]; } } - (void)encodeArrayOfObjCType:(const char *)_type count:(unsigned int)_count at:(const void *)_array { if ((self->didWriteHeader == NO) && (self->traceMode == NO)) [self writeArchiveHeader]; // array header if (self->traceMode == NO) { // nothing is written during trace-mode _writeTag(self, _C_ARY_B); _writeInt(self, _count); } // Optimize writing arrays of elementary types. If such an array has to // be written, write the type and then the elements of array. if ((*_type == _C_ID) || (*_type == _C_CLASS)) { // object array int i; if (self->traceMode == NO) _writeTag(self, *_type); // object array for (i = 0; i < _count; i++) [self encodeObject:((id *)_array)[i]]; } else if ((*_type == _C_CHR) || (*_type == _C_UCHR)) { // byte array if (self->traceMode == NO) { // write base type tag _writeTag(self, *_type); // write buffer _writeBytes(self, _array, _count); } } else if (isBaseType(_type)) { if (self->traceMode == NO) { unsigned offset, itemSize = objc_sizeof_type(_type); int i; // write base type tag _writeTag(self, *_type); // write contents for (i = offset = 0; i < _count; i++, offset += itemSize) _writeObjC(self, (char *)_array + offset, _type); } } else { // encoded using normal method IMP encodeValue = NULL; unsigned offset, itemSize = objc_sizeof_type(_type); int i; encodeValue = [self methodForSelector:@selector(encodeValueOfObjCType:at:)]; for (i = offset = 0; i < _count; i++, offset += itemSize) { encodeValue(self, @selector(encodeValueOfObjCType:at:), (char *)_array + offset, _type); } } } // -------------------- decoding -------------------- - (void)decodeArchiveHeader { if (self->didReadHeader == NO) { char *archiver = _readCString(self); self->inArchiverVersion = _readInt(self); if (strcmp(archiver, [[self coderSignature] cString])) { NSLog(@"WARNING: used a different archiver (signature %s:%i)", archiver, [self systemVersion]); } else if ([self systemVersion] != [self coderVersion]) { NSLog(@"WARNING: used a different archiver version " @"(archiver=%i, unarchiver=%i)", [self systemVersion], [self coderVersion]); } if (archiver) { NGFree(archiver); archiver = NULL; } self->didReadHeader = YES; } } - (void)beginDecoding { #if 0 NSLog(@"start decoding .."); #endif [self decodeArchiveHeader]; } - (void)endDecoding { #if 0 NSLog(@"finish decoding .."); #endif NSResetMapTable(self->inObjects); NSResetMapTable(self->inClasses); NSResetMapTable(self->inPointers); NSResetMapTable(self->inClassAlias); NSResetMapTable(self->inClassVersions); } - (Class)_decodeClass:(BOOL)_isReference { int archiveId = _readInt(self); Class result = Nil; if (_isReference) { result = (Class)NSMapGet(self->inClasses, (void *)archiveId); if (result == Nil) { NSLog(@"did not find class for archive-id %i", archiveId); } } else { NSString *name = NULL; int version = 0; name = [NSString stringWithCString:_readCString(self)]; version = _readInt(self); if (name == nil) { [NSException raise:NSInconsistentArchiveException format:@"did not find class name"]; } { // check whether the class is to be replaced NSString *newName = NSMapGet(self->inClassAlias, name); if (newName) name = newName; else { newName = NSMapGet(classToAliasMappings, name); if (newName) name = newName; } } result = NSClassFromString(name); #if 0 NSLog(@"decoded class %@:%i (result=%@).", name, version, result); #endif NSAssert([result version] == version, @"class versions do not match .."); NSMapInsert(self->inClasses, (void *)archiveId, result); } NSAssert(result, @"class may not be Nil .."); return result; } - (id)_decodeObject:(BOOL)_isReference { // this method returns a retained object ! int archiveId = _readInt(self); id result = nil; if (archiveId == 0) // nil object or unused conditional object return nil; if (_isReference) { result = [(id)NSMapGet(self->inObjects, (void *)archiveId) retain]; } else { Class class = Nil; id replacement = nil; // decode class info [self decodeValueOfObjCType:"#" at:&class]; NSAssert(class, @"invalid class .."); result = [class allocWithZone:self->objectZone]; NSMapInsert(self->inObjects, (void *)archiveId, result); replacement = [result initWithCoder:self]; if (replacement != result) { replacement = [replacement retain]; NSMapRemove(self->inObjects, result); result = replacement; NSMapInsert(self->inObjects, (void *)archiveId, result); [replacement release]; } replacement = [result awakeAfterUsingCoder:self]; if (replacement != result) { replacement = [replacement retain]; NSMapRemove(self->inObjects, result); result = replacement; NSMapInsert(self->inObjects, (void *)archiveId, result); [replacement release]; } } NSAssert([result retainCount] > 0, @"invalid retain count .."); return result; } - (id)decodeObject { id result = nil; [self decodeValueOfObjCType:"@" at:&result]; // result is retained return [result autorelease]; } - (void)decodeValueOfObjCType:(const char *)_type at:(void *)_value { BOOL startedDecoding = NO; NGTagType tag = 0; BOOL isReference = NO; if (self->decodingRoot == NO) { self->decodingRoot = YES; startedDecoding = YES; [self beginDecoding]; } tag = _readTag(self); isReference = isReferenceTag(tag); tag = tagValue(tag); switch (tag) { case _C_ID: NSAssert((*_type == _C_ID) || (*_type == _C_CLASS), @"invalid type .."); *(id *)_value = [self _decodeObject:isReference]; break; case _C_CLASS: NSAssert((*_type == _C_ID) || (*_type == _C_CLASS), @"invalid type .."); *(Class *)_value = [self _decodeClass:isReference]; break; case _C_ARY_B: { int count = atoi(_type + 1); // eg '[15I' => count = 15 const char *itemType = _type; NSAssert(*_type == _C_ARY_B, @"invalid type .."); while(isdigit((int)*(++itemType))) ; // skip dimension [self decodeArrayOfObjCType:itemType count:count at:_value]; break; } case _C_STRUCT_B: { int offset = 0; NSAssert(*_type == _C_STRUCT_B, @"invalid type .."); while ((*_type != _C_STRUCT_E) && (*_type++ != '=')); // skip "=" while (YES) { [self decodeValueOfObjCType:_type at:((char *)_value) + offset]; offset += objc_sizeof_type(_type); _type = objc_skip_typespec(_type); if(*_type != _C_STRUCT_E) { // C-structure end '}' int align, remainder; align = objc_alignof_type(_type); if((remainder = offset % align)) offset += (align - remainder); } else break; } break; } case _C_SEL: { char *name = NULL; NSAssert(*_type == tag, @"invalid type .."); _readObjC(self, &name, @encode(char *)); *(SEL *)_value = name ? sel_registerName(name) : NULL; NGFree(name); name = NULL; } case _C_PTR: _readObjC(self, *(char **)_value, _type + 1); // skip '^' break; case _C_CHARPTR: case _C_CHR: case _C_UCHR: case _C_SHT: case _C_USHT: case _C_INT: case _C_UINT: case _C_LNG: case _C_ULNG: case _C_FLT: case _C_DBL: NSAssert(*_type == tag, @"invalid type .."); _readObjC(self, _value, _type); break; default: NSAssert2(0, @"unsupported tag '%c', type %s ..", tag, _type); break; } if (startedDecoding) { [self endDecoding]; self->decodingRoot = NO; } } - (void)decodeArrayOfObjCType:(const char *)_type count:(unsigned int)_count at:(void *)_array { BOOL startedDecoding = NO; NGTagType tag = _readTag(self); int count = _readInt(self); if (self->decodingRoot == NO) { self->decodingRoot = YES; startedDecoding = YES; [self beginDecoding]; } #if 0 NSLog(@"decoding array[%i/%i] of ObjC-type '%s' array-tag='%c'", _count, count, _type, tag); #endif NSAssert(tag == _C_ARY_B, @"invalid type .."); NSAssert(count == _count, @"invalid array size .."); // Arrays of elementary types are written optimized: the type is written // then the elements of array follow. if ((*_type == _C_ID) || (*_type == _C_CLASS)) { // object array int i; #if 0 NSLog(@"decoding object-array[%i] type='%s'", _count, _type); #endif tag = _readTag(self); // object array NSAssert(tag == *_type, @"invalid array element type .."); for (i = 0; i < _count; i++) ((id *)_array)[i] = [self decodeObject]; } else if ((*_type == _C_CHR) || (*_type == _C_UCHR)) { // byte array tag = _readTag(self); NSAssert((tag == _C_CHR) || (tag == _C_UCHR), @"invalid byte array type .."); #if 0 NSLog(@"decoding byte-array[%i] type='%s' tag='%c'", _count, _type, tag); #endif // read buffer _readBytes(self, _array, _count); } else if (isBaseType(_type)) { unsigned offset, itemSize = objc_sizeof_type(_type); int i; tag = _readTag(self); NSAssert(tag == *_type, @"invalid array base type .."); for (i = offset = 0; i < _count; i++, offset += itemSize) _readObjC(self, (char *)_array + offset, _type); } else { IMP decodeValue = NULL; unsigned offset, itemSize = objc_sizeof_type(_type); int i; decodeValue = [self methodForSelector:@selector(decodeValueOfObjCType:at:)]; for (i = offset = 0; i < count; i++, offset += itemSize) { decodeValue(self, @selector(decodeValueOfObjCType:at:), (char *)_array + offset, _type); } } if (startedDecoding) { [self endDecoding]; self->decodingRoot = NO; } } // Substituting One Class for Another + (NSString *)classNameDecodedForArchiveClassName:(NSString *)nameInArchive { NSString *className = NSMapGet(classToAliasMappings, nameInArchive); return className ? className : nameInArchive; } + (void)decodeClassName:(NSString *)nameInArchive asClassName:(NSString *)trueName { NSMapInsert(classToAliasMappings, nameInArchive, trueName); } - (NSString *)classNameDecodedForArchiveClassName:(NSString *)_nameInArchive { NSString *className = NSMapGet(self->inClassAlias, _nameInArchive); return className ? className : _nameInArchive; } - (void)decodeClassName:(NSString *)nameInArchive asClassName:(NSString *)trueName { NSMapInsert(self->inClassAlias, nameInArchive, trueName); } // ******************** primitives ******************** // encoding FINAL void _writeBytes(NGStreamCoder *self, const void *_bytes, unsigned _len) { NSCAssert(self->traceMode == NO, @"nothing can be written during trace-mode .."); self->writeIMP ? self->writeIMP(self->stream, @selector(safeWriteBytes:count:), _bytes, _len) : [self->stream safeWriteBytes:_bytes count:_len]; } FINAL void _writeTag(NGStreamCoder *self, NGTagType _tag) { NSCAssert(self, @"invalid self .."); #if 0 NSLog(@"write tag '%s%c'", isReferenceTag(_tag) ? "&" : "", tagValue(_tag)); #endif [self->stream serializeChar:_tag]; } FINAL void _writeChar(NGStreamCoder *self, char _value) { [self->stream serializeChar:_value]; } FINAL void _writeShort(NGStreamCoder *self, short _value) { [self->stream serializeShort:_value]; } FINAL void _writeInt(NGStreamCoder *self, int _value) { [self->stream serializeInt:_value]; } FINAL void _writeLong(NGStreamCoder *self, long _value) { [self->stream serializeLong:_value]; } FINAL void _writeFloat(NGStreamCoder *self, float _value) { [self->stream serializeFloat:_value]; } FINAL void _writeCString(NGStreamCoder *self, const char *_value) { [(id)self->stream serializeDataAt:&_value ofObjCType:@encode(char *) context:self]; } FINAL void _writeObjC(NGStreamCoder *self, const void *_value, const char *_type) { if ((_value == NULL) || (_type == NULL)) return; if (self->traceMode) { // no need to track base-types in trace-mode switch (*_type) { case _C_ID: case _C_CLASS: case _C_CHARPTR: case _C_ARY_B: case _C_STRUCT_B: case _C_PTR: [(id)self->stream serializeDataAt:_value ofObjCType:_type context:self]; break; default: break; } } else { [(id)self->stream serializeDataAt:_value ofObjCType:_type context:self]; } } // decoding FINAL void _readBytes(NGStreamCoder *self, void *_bytes, unsigned _len) { self->readIMP ? self->readIMP(self->stream, @selector(safeReadBytes:count:), _bytes, _len) : [self->stream safeReadBytes:_bytes count:_len]; } FINAL NGTagType _readTag(NGStreamCoder *self) { return [self->stream deserializeChar]; } FINAL char _readChar(NGStreamCoder *self) { return [self->stream deserializeChar]; } FINAL short _readShort(NGStreamCoder *self) { return [self->stream deserializeShort]; } FINAL int _readInt(NGStreamCoder *self) { return [self->stream deserializeInt]; } FINAL long _readLong (NGStreamCoder *self) { return [self->stream deserializeLong]; } FINAL float _readFloat(NGStreamCoder *self) { return [self->stream deserializeFloat]; } FINAL char *_readCString(NGStreamCoder *self) { char *result = NULL; [(id)self->stream deserializeDataAt:&result ofObjCType:@encode(char *) context:self]; return result; } FINAL void _readObjC(NGStreamCoder *self, void *_value, const char *_type) { [(id)self->stream deserializeDataAt:_value ofObjCType:_type context:(id)self]; } // NSObjCTypeSerializationCallBack - (void)serializeObjectAt:(id *)_object ofObjCType:(const char *)_type intoData:(NSMutableData *)_data { switch (*_type) { case _C_ID: case _C_CLASS: if (self->traceMode) [self _traceObject:*_object]; else [self _encodeObject:*_object]; break; default: abort(); break; } } - (void)deserializeObjectAt:(id *)_object ofObjCType:(const char *)_type fromData:(NSData *)_data atCursor:(unsigned int *)_cursor { NGTagType tag = 0; BOOL isReference = NO; tag = _readTag(self); isReference = isReferenceTag(tag); tag = tagValue(tag); switch (*_type) { case _C_ID: NSAssert((*_type == _C_ID) || (*_type == _C_CLASS), @"invalid type .."); break; *_object = [self _decodeObject:isReference]; break; case _C_CLASS: NSAssert((*_type == _C_ID) || (*_type == _C_CLASS), @"invalid type .."); *_object = [self _decodeClass:isReference]; break; default: abort(); break; } } @end SOPE/sope-core/NGStreams/Version0000644000000000000000000000004515004363604015431 0ustar rootroot# version file SUBMINOR_VERSION:=57 SOPE/sope-core/NGStreams/NGStreams.m0000644000000000000000000000164115004363604016105 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include @implementation NGStreams - (void)_staticLinkClasses { } - (void)_staticLinkModules { } @end /* NGStreams */ SOPE/sope-core/NGStreams/NGInternetSocketAddress.m0000644000000000000000000004030415004363604020735 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG Copyright (C) 2022 Nicolas Höft This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #if HAVE_SYS_TYPES_H || defined(__APPLE__) # include #endif #if HAVE_NETINET_IN_H # include #endif #if HAVE_UNISTD_H || defined(__APPLE__) # include #endif #ifdef HAVE_NETDB_H # include #endif #include "NGSocketExceptions.h" #include "NGInternetSocketAddress.h" #include "NGInternetSocketDomain.h" #include "common.h" @implementation NGInternetSocketAddress #if LIB_FOUNDATION_LIBRARY extern NSRecursiveLock *libFoundationLock; #define systemLock libFoundationLock #else static NSRecursiveLock *systemLock = nil; #endif static NSMapTable *nameCache = NULL; + (void)initialize { [NGSocket initialize]; if (nameCache == NULL) { nameCache = NSCreateMapTable(NSIntMapKeyCallBacks, NSObjectMapValueCallBacks, 128); } #if !LIB_FOUNDATION_LIBRARY [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskNowMultiThreaded:) name:NSWillBecomeMultiThreadedNotification object:nil]; #endif } + (void)taskNowMultiThreaded:(NSNotification *)_notification { if (systemLock == nil) systemLock = [[NSRecursiveLock alloc] init]; } static inline NSString *_nameOfLocalhost(void) { #if 1 return [[NSHost currentHost] name]; #else NSString *hostName = nil; [systemLock lock]; { char buffer[1024]; gethostname(buffer, sizeof(buffer)); hostName = [[NSString alloc] initWithCString:buffer]; } [systemLock unlock]; return [hostName autorelease]; #endif } - (void)_fillHost { /* Fill up the host and port ivars based on the INET address. */ NSString *newHost = nil; int errorCode = 0; if (self->isHostFilled) /* host is already filled .. */ return; #if DEBUG NSAssert(self->address != nil, @"either host or address must be filled ..."); #endif if (!self->isWildcardHost) { if (newHost == nil) { BOOL done = NO; while (!done) { char hostNameBuffer[256]; errorCode = getnameinfo((struct sockaddr *)self->address, [self addressRepresentationSize], hostNameBuffer, 255, NULL, 0, 0); if (errorCode != 0) { done = YES; switch (errorCode) { case EAI_NONAME: NSLog(@"%s: host not found ..", __PRETTY_FUNCTION__); break; case EAI_AGAIN: #ifndef __linux NSLog(@"%s:\n couldn't lookup host, retry ..", __PRETTY_FUNCTION__); done = NO; #else NSLog(@"%s: couldn't lookup host ..", __PRETTY_FUNCTION__); #endif break; case EAI_FAIL: NSLog(@"%s: A nonrecoverable error occurred.", __PRETTY_FUNCTION__); break; default: NSLog(@"%s: unknown error: h_errno=%i errno=%s", __PRETTY_FUNCTION__, errorCode, gai_strerror(errorCode)); break; } newHost = self->ipAddress; } else { newHost = [NSString stringWithCString:hostNameBuffer]; done = YES; } } if (errorCode != 0) { // throw could not get address .. NSLog(@"could not get DNS name of address %@ in domain %@: %s", self->ipAddress, [self domain], gai_strerror(errorCode)); } } } else { /* wildcard address */ newHost = nil; } ASSIGNCOPY(self->hostName, newHost); self->isHostFilled = YES; } - (NSException *)_fillAddress { /* Fill up the INET address based on the host and port ivars. */ // throws // NGCouldNotResolveHostNameException when a DNS lookup fails if (self->address != nil) /* address is already filled .. */ return nil; #if DEBUG NSAssert(self->isHostFilled, @"either host or address must be filled ..."); #endif if (self->hostName == nil) { if (self->isIp6) { struct sockaddr_in6 *addr6 = malloc(sizeof(struct sockaddr_in6)); addr6->sin6_addr = in6addr_any; addr6->sin6_port = htons(self->port); self->address = addr6; } else { struct sockaddr_in *addr = malloc(sizeof(struct sockaddr_in)); addr->sin_addr.s_addr = htonl(INADDR_ANY); addr->sin_port = htons(self->port); self->address = addr; } self->ipAddress = @"*"; } else { const char *chost; struct addrinfo hint; struct addrinfo* res = NULL; void* addr_ptr; char ipAddr[64]; memset(&hint, 0, sizeof(hint)); int ret; // try to interpret hostname as INET/INET6 dotted address (eg 122.133.44.87) chost = [[self hostName] cString]; hint.ai_family = PF_UNSPEC; hint.ai_flags |= AI_CANONNAME; ret = getaddrinfo(chost, NULL, &hint, &res); if (ret != 0) { NSString* reason = [NSString stringWithFormat:@"error code %s", gai_strerror(ret)]; return [[[NGCouldNotResolveHostNameException alloc] initWithHostName:[self hostName] reason:reason] autorelease]; } if (res->ai_family == AF_INET) { struct sockaddr_in *addr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in)); addr->sin_family = AF_INET; addr->sin_port = htons(self->port); memcpy(&addr->sin_addr, &((struct sockaddr_in *) res->ai_addr)->sin_addr, sizeof(struct in_addr)); self->address = addr; self->isIp6 = NO; self->isWildcardHost = (addr->sin_addr.s_addr == INADDR_ANY); addr_ptr = &addr->sin_addr; } else if (res->ai_family == AF_INET6) { struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)malloc(sizeof(struct sockaddr_in6)); addr6->sin6_family = AF_INET6; addr6->sin6_port = htons(self->port); memcpy(&addr6->sin6_addr, &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr, sizeof(struct in6_addr)); self->address = addr6; self->isWildcardHost = IN6_IS_ADDR_UNSPECIFIED(&addr6->sin6_addr); self->isIp6 = YES; addr_ptr = &addr6->sin6_addr; } inet_ntop(res->ai_family, addr_ptr, ipAddr, 64); freeaddrinfo(res); self->ipAddress = [NSString stringWithUTF8String: ipAddr]; self->isAddressFilled = YES; } return nil; } /* constructors */ + (id)addressWithPort:(int)_port onHost:(id)_host { return [[[self alloc] initWithPort:_port onHost:_host] autorelease]; } + (id)addressWithPort:(int)_port { return [[[self alloc] initWithPort:_port] autorelease]; } + (id)addressWithService:(NSString *)_sname onHost:(id)_host protocol:(NSString *)_protocol { return [[[self alloc] initWithService:_sname onHost:_host protocol:_protocol] autorelease]; } + (id)addressWithService:(NSString *)_sname protocol:(NSString *)_protocol { return [[[self alloc] initWithService:_sname protocol:_protocol] autorelease]; } + (id)wildcardAddress { return [[[self alloc] initWithPort:0 onHost:@"*"] autorelease]; } + (id)wildcardAddressWithPort:(int)_port { return [[[self alloc] initWithPort:_port onHost:@"*"] autorelease]; } - (id)init { if ((self = [super init])) { self->address = NULL; } return self; } - (id)initWithPort:(int)_port onHost:(id)_host { /* designated initializer */ if ((self = [self init])) { self->isAddressFilled = NO; self->isHostFilled = YES; self->port = _port; if (_host != nil) { if ([_host isKindOfClass:[NSHost class]]) _host = [(NSHost *)_host address]; if ([_host isEqualToString:@"*"]) { self->hostName = nil; /* wildcard host */ self->isWildcardHost = YES; } else { self->hostName = [_host copy]; self->isWildcardHost = NO; [self _fillAddress]; } } else { /* wildcard host */ self->isWildcardHost = YES; } } return self; } - (id)initWithService:(NSString *)_serviceName onHost:(id)_host protocol:(NSString *)_protocol { /* careful: the port in servent is in network byteorder! */ NSException *exc = nil; struct addrinfo* res = NULL; struct addrinfo hint = {0}; hint.ai_family = AF_UNSPEC; hint.ai_flags = AI_PASSIVE; if ([_protocol isEqualToString: @"tcp"]) hint.ai_socktype = SOCK_STREAM; else if ([_protocol isEqualToString: @"udp"]) hint.ai_socktype = SOCK_DGRAM; int _port = -1; int ret; ret = getaddrinfo(NULL, [_serviceName cString], &hint, &res); if (ret != 0) { exc = [[NGDidNotFindServiceException alloc] initWithServiceName:_serviceName]; } else { if (res->ai_family == AF_INET) _port = ((struct sockaddr_in *) res->ai_addr)->sin_port; else if (res->ai_family == AF_INET6) _port = ((struct sockaddr_in6 *) res->ai_addr)->sin6_port; } freeaddrinfo(res); if (exc != nil) { self = [self autorelease]; [exc raise]; return nil; } return [self initWithPort:ntohs(_port) onHost:_host]; } - (id)initWithPort:(int)_port { return [self initWithPort:_port onHost:_nameOfLocalhost()]; } - (id)initWithService:(NSString *)_serviceName protocol:(NSString *)_protocol { return [self initWithService:_serviceName onHost:_nameOfLocalhost() protocol:_protocol]; } - (id)initWithDomain:(id)_domain internalRepresentation:(void *)_representation size:(int)_length { struct sockaddr *sockAddr = _representation; char ipAddr[64]; void* addr_ptr; #if DEBUG NSAssert(_length == [_domain addressRepresentationSize], @"invalid socket address length"); #else if (_length != [_domain addressRepresentationSize]) { NSLog(@"%s: got invalid sockaddr_in size ...", __PRETTY_FUNCTION__); [self release]; return nil; } #endif if ((self = [self init]) == nil) return nil; self->isHostFilled = NO; /* need to lookup DNS */ /* fill address */ if (sockAddr->sa_family == AF_INET) { self->address = malloc(sizeof(struct sockaddr_in)); struct sockaddr_in *addr4 = (struct sockaddr_in *)sockAddr; addr_ptr = &addr4->sin_addr; self->isIp6 = NO; self->isWildcardHost = (addr4->sin_addr.s_addr == INADDR_ANY); self->port = ntohs(addr4->sin_port); } else if (sockAddr->sa_family == AF_INET6) { self->address = malloc(sizeof(struct sockaddr_in6)); struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)sockAddr; addr_ptr = &addr6->sin6_addr; self->isIp6 = YES; self->isWildcardHost = IN6_IS_ADDR_UNSPECIFIED(&addr6->sin6_addr); self->port = ntohs(addr6->sin6_port); } memcpy(self->address, _representation, [_domain addressRepresentationSize]); self->isAddressFilled = YES; if (!self->isWildcardHost) { /* not a wildcard address */ inet_ntop(sockAddr->sa_family, addr_ptr, ipAddr, 64); self->ipAddress = [NSString stringWithUTF8String: ipAddr]; } else { /* wildcard address */ self->hostName = nil; self->isHostFilled = YES; /* wildcard host, no DNS lookup ... */ self->ipAddress = @"*"; } return self; } - (void)dealloc { [self->hostName release]; if (self->address) free(self->address); [super dealloc]; } /* accessors */ - (NSString *)hostName { if (!self->isHostFilled) [self _fillHost]; return [[self->hostName copy] autorelease]; } - (BOOL) _isLoopback { if (self->address == nil) [[self _fillAddress] raise]; if (self->isIp6) { return IN6_IS_ADDR_LOOPBACK(&((struct sockaddr_in6 *)self->address)->sin6_addr); } unsigned int *ia = &(((struct sockaddr_in *)self->address)->sin_addr.s_addr); return ((((long int) (ntohl(*ia))) & 0xff000000) == 0x7f000000); } - (NSString *)address { if (self->hostName == nil) /* wildcard */ return nil; if (self->address == nil) [[self _fillAddress] raise]; return self->ipAddress; } - (int)port { return self->port; } - (BOOL)isWildcardAddress { if (self->isWildcardHost) return YES; return ([self hostName] == nil) || ([self port] == 0); } /* NGSocketAddress protocol */ - (void *)internalAddressRepresentation { // throws // NGCouldNotResolveHostNameException when a DNS lookup fails if (self->address == nil) [[self _fillAddress] raise]; return self->address; } - (int)addressRepresentationSize { return [[self domain] addressRepresentationSize]; } - (id)domain { static id domain = nil; static id domain6 = nil; if (domain == nil) domain = [[NGInternetSocketDomain domain] retain]; if (domain6 == nil) domain6 = [[NGInternetSocketDomain6 domain] retain]; if (self->isIp6) return domain6; return domain; } - (BOOL) isLocalhost { NSString *normalized_hostname; if (![self hostName]) return NO; if ([self _isLoopback]) return YES; // normalize the string normalized_hostname = [[self hostName] lowercaseString]; if ([normalized_hostname hasSuffix: @"."]) { normalized_hostname = [normalized_hostname substringToIndex: [normalized_hostname length] - 1]; } if ([normalized_hostname isEqualToString: @"localhost"] || [normalized_hostname isEqualToString: @"localhost.localdomain"] || [normalized_hostname hasSuffix: @".localhost"]) { return YES; } return NO; } - (BOOL) isIPv4 { return !self->isIp6; } - (BOOL) isIPv6 { return self->isIp6; } /* comparing */ - (NSUInteger)hash { return [self port]; } - (BOOL)isEqualToAddress:(NGInternetSocketAddress *)_otherAddress { if (self == _otherAddress) return YES; if (![[_otherAddress hostName] isEqualToString:[self hostName]]) return NO; if ([_otherAddress port] != [self port]) return NO; return YES; } - (BOOL)isEqual:(id)_object { if (_object == self) return YES; if ([_object class] != [self class]) return NO; return [self isEqualToAddress:_object]; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { // socket addresses are immutable, therefore just retain self return [self retain]; } /* NSCoding */ - (void)encodeWithCoder:(NSCoder *)_encoder { int aPort = [self port]; [_encoder encodeValueOfObjCType:@encode(int) at:&aPort]; [_encoder encodeObject:[self hostName]]; } - (id)initWithCoder:(NSCoder *)_decoder { int aPort; id aHost; [_decoder decodeValueOfObjCType:@encode(int) at:&aPort]; aHost = [_decoder decodeObject]; return [self initWithPort:aPort onHost:aHost]; } /* description */ - (NSString *)stringValue { NSString *name; if ((name = [self hostName]) == nil) name = @"*"; return [NSString stringWithFormat:@"%@:%i", name, [self port]]; } - (NSString *)description { NSMutableString *ms; id tmp; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if ((tmp = [self hostName]) != nil) [ms appendFormat:@" host=%@", tmp]; else [ms appendString:@" *host"]; if (!self->isAddressFilled) [ms appendString:@" not-filled"]; else [ms appendFormat:@" port=%d", [self port]]; //if (self->ipAddress != nil) //[ms appendFormat:@" ip=%@", self->ipAddress]; [ms appendString:@">"]; return ms; } @end /* NGInternetSocketAddress */ @implementation NGActiveSocket(NGInternetActiveSocket) + (id)socketConnectedToPort:(int)_port onHost:(id)_host { // this method calls +socketConnectedToAddress: with an // NGInternetSocketAddress return [self socketConnectedToAddress: [NGInternetSocketAddress addressWithPort:_port onHost:_host]]; } - (BOOL)connectToPort:(int)_port onHost:(id)_host { // this method calls -connectToAddress: with an NGInternetSocketAddress return [self connectToAddress: [NGInternetSocketAddress addressWithPort:_port onHost:_host]]; } @end /* NGActiveSocket(NGInternetActiveSocket) */ SOPE/sope-core/NGStreams/install-sh0000755000000000000000000001124515004363604016071 0ustar rootroot#! /bin/sh # # install - install a program, script, or datafile # This comes from X11R5. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. # # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 SOPE/sope-core/NGStreams/NGNetUtilities.m0000644000000000000000000000670015004363604017112 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGNetUtilities.h" #include "NGInternetSocketAddress.h" #include "NGLocalSocketAddress.h" #include "common.h" id NGSocketAddressFromString(NSString *_string) { const char *cstr = [_string cString]; if (cstr == NULL) return nil; if ([_string length] < 1) return nil; { const char *colon = index(cstr, ':'); if (colon) { // INET socket NSString *hostName = nil; if (*cstr == '[') { // ipv6 cstr++; char *pos = index(cstr, ']'); if (pos == 0) { [NSException raise:NSInvalidArgumentException format: @"Illegal Ipv6 address: %@", _string]; } while (*pos != ']') { if (*pos != ':' && *pos != '.' && !isxdigit(*pos)) { [NSException raise:NSInvalidArgumentException format: @"Illegal Ipv6 address: %@", _string]; } pos++; } colon = pos +1; if (*colon != ':') { [NSException raise:NSInvalidArgumentException format: @"Missing port on Ipv6 address: %@", _string]; } hostName = [NSString stringWithCString:(char *)cstr length:(pos - cstr)]; } else { // ipv4 if (((colon - cstr) == 1) && (*cstr == '*')) hostName = nil; // wildcard host else { hostName = [NSString stringWithCString:(char *)cstr length:(colon - cstr)]; } } // check what comes after colon if (isdigit(colon[1])) { // a port int port = atoi((char *)colon + 1); return [NGInternetSocketAddress addressWithPort:port onHost:hostName]; } else { // a service or 'auto' for auto-assigned ports const char *slash; NSString *protocol = @"tcp"; NSString *service; slash = index((colon + 1), '/'); colon++; if (slash == NULL) service = [NSString stringWithCString:colon]; else { service = [NSString stringWithCString:colon length:(slash - colon)]; protocol = [NSString stringWithCString:(slash + 1)]; } if ([service isEqualToString:@"auto"]) return [NGInternetSocketAddress addressWithPort:0 onHost:hostName]; return [NGInternetSocketAddress addressWithService:service onHost:hostName protocol:protocol]; } } #if !defined(WIN32) if ([_string isAbsolutePath]) return [NGLocalSocketAddress addressWithPath:_string]; #endif } return nil; } SOPE/sope-core/NGStreams/NGLocalSocketAddress.m0000644000000000000000000001375215004363604020206 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if !defined(WIN32) || defined(__CYGWIN32__) #include "NGSocketExceptions.h" #include "NGLocalSocketAddress.h" #include "NGLocalSocketDomain.h" #import #include "config.h" #if defined(__APPLE__) || defined(__FreeBSD__) # include #else # include #endif #if defined(HAVE_UNISTD_H) || defined(__APPLE__) # include #endif #ifndef SUN_LEN #define SUN_LEN(su) \ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) #endif #include "common.h" #ifndef AF_LOCAL # define AF_LOCAL AF_UNIX #endif #if defined(__WIN32__) && !defined(__CYGWIN32__) static NSString *socketDirectoryPath = @"\\\\.\\pipe\\"; #else static NSString *socketDirectoryPath = @"/tmp"; #endif @implementation NGLocalSocketAddress + (id)addressWithPath:(NSString *)_p { return [[(NGLocalSocketAddress *)[self alloc] initWithPath:_p] autorelease]; } + (id)address { return [[[self alloc] init] autorelease]; } - (id)initWithPath:(NSString *)_path { if ((self = [super init])) { self->address = calloc(1, sizeof(struct sockaddr_un)); memset(self->address, 0, sizeof(struct sockaddr_un)); #if defined(__WIN32__) && !defined(__CYGWIN32__) self->path = [_path copyWithZone:[self zone]]; #else if ([_path cStringLength] >= sizeof(((struct sockaddr_un *)self->address)->sun_path)) { NSLog(@"LocalDomain name too long: maxlen=%i, len=%i, path=%@", (int)sizeof(((struct sockaddr_un *)self->address)->sun_path), (int)[_path cStringLength], _path); [NSException raise:NSInvalidArgumentException format:@"path to long as local domain socket address !"]; [self release]; return nil; } ((struct sockaddr_un *)self->address)->sun_family = [[self domain] socketDomain]; [_path getCString:((struct sockaddr_un *)self->address)->sun_path maxLength:sizeof(((struct sockaddr_un *)self->address)->sun_path)]; #endif } return self; } - (id)init { int addressCounter = 0; NSString *newPath; newPath = [NSString stringWithFormat:@"_ngsocket_%d_%p_%03d", (int)getpid(), [NSThread currentThread], addressCounter]; newPath = [socketDirectoryPath stringByAppendingPathComponent:newPath]; return [self initWithPath:newPath]; } - (id)initWithDomain:(id)_domain internalRepresentation:(void *)_representation size:(int)_length { // this method is used by the address factory struct sockaddr_un *nun = _representation; NSString *path; path = (_length < 3) ? (id)@"" : [[NSString alloc] initWithCString:nun->sun_path]; self = [self initWithPath:path]; [path release]; path = nil; return self; } - (void)dealloc { if (self->address) free(self->address); [super dealloc]; } /* accessors */ - (NSString *)path { const char *sp; sp = ((struct sockaddr_un *)self->address)->sun_path; if (strlen(sp) == 0) return @""; return [NSString stringWithCString:sp]; } /* operations */ - (void)deletePath { const char *sp; sp = ((struct sockaddr_un *)self->address)->sun_path; if (strlen(sp) == 0) return; unlink(sp); } // NGSocketAddress protocol - (void *)internalAddressRepresentation { return self->address; } - (int)addressRepresentationSize { // varies in length return SUN_LEN(((struct sockaddr_un *)self->address)); } - (id)domain { return [NGLocalSocketDomain domain]; } - (BOOL) isLocalhost { return YES; } - (NSString *) hostName { return @"localhost"; } /* test for accessibility */ - (BOOL)canSendOnAddress { return (access(((struct sockaddr_un *)self->address)->sun_path, W_OK) == 0) ? YES : NO; } - (BOOL)canReceiveOnAddress { return (access(((struct sockaddr_un *)self->address)->sun_path, R_OK) == 0) ? YES : NO; } /* testing for equality */ - (BOOL)isEqualToAddress:(NGLocalSocketAddress *)_addr { return [[_addr path] isEqualToString:[self path]]; } - (BOOL)isEqual:(id)_object { if (_object == self) return YES; if ([_object class] != [self class]) return NO; return [self isEqualToAddress:_object]; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { /* socket addresses are immutable, just retain on copy ... */ return [self retain]; } /* NSCoding */ - (void)encodeWithCoder:(NSCoder *)_encoder { [_encoder encodeObject:[[NSHost currentHost] name]]; [_encoder encodeObject:[self path]]; } - (id)initWithCoder:(NSCoder *)_decoder { NSString *hostName = [_decoder decodeObject]; NSString *path = [_decoder decodeObject]; NSAssert([path isKindOfClass:[NSString class]], @"path must be a string .."); if (![hostName isEqualToString:[[NSHost currentHost] name]]) { NSLog(@"unarchived local socket address on a different host, " @"encoded on %@, decoded on %@ (path=%@)", hostName, [[NSHost currentHost] name], path); } return [self initWithPath:path]; } /* description */ - (NSString *)stringValue { NSString *p = [self path]; return [p length] == 0 ? (NSString *)@"*" : p; } - (NSString *)description { NSString *p = [self path]; if ([p length] == 0) p = @"[no path]"; return [NSString stringWithFormat:@"<0x%p[%@]: %@>", self, NSStringFromClass([self class]), p]; } @end /* NGLocalSocketAddress */ #endif /* !WIN32 */ SOPE/sope-core/NGStreams/NGStreams/0000755000000000000000000000000015004363604015725 5ustar rootrootSOPE/sope-core/NGStreams/NGStreams/NGSocketProtocols.h0000644000000000000000000000550315004363604021463 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGNet_NGSocketProtocols_H__ #define __NGNet_NGSocketProtocols_H__ #import #include @class NSException; // addresses @protocol NGSocketAddress < NSObject > - (void *)internalAddressRepresentation; - (int)addressRepresentationSize; - (id)domain; // (a NGSocketDomain) - (BOOL) isLocalhost; - (NSString *)hostName; // needed by socket address factory: - (id)initWithDomain:(id)_domain internalRepresentation:(void *)_representation size:(int)_length; @end // sockets @protocol NGSocket < NSObject > - (id)localAddress; - (BOOL)bindToAddress:(id)_localAddress; - (BOOL)close; - (NSException *)lastException; @end // domains @protocol NGSocketDomain < NSObject > - (id)addressWithRepresentation:(void *)_data size:(unsigned int)_size; - (int)socketDomain; - (int)addressRepresentationSize; - (int)protocol; // these two methods manage resources associated with addresses // (primarily the files used for AF_LOCAL sockets) - (BOOL)prepareAddress:(id)_address forBindWithSocket:(id)_socket; - (BOOL)cleanupAddress:(id)_address afterCloseOfSocket:(id)_socket; @end // concrete sockets @protocol NGActiveSocket < NGSocket, NGStream, NGByteSequenceStream > - (BOOL)connectToAddress:(id)_address; - (BOOL)shutdown; - (BOOL)isConnected; - (id)remoteAddress; @end @protocol NGPassiveSocket < NGSocket > - (BOOL)listenWithBacklog:(int)_backlogSize; - (id)accept; @end // packets @protocol NGDatagramPacket < NSObject > - (void)setSender:(id)_address; - (id)sender; - (void)setReceiver:(id)_address; - (id)receiver; - (NSData *)data; @end @protocol NGDatagramPacketFactory < NSObject > - (id)packetWithData:(NSData *)_data; - (id) packetWithBytes:(const void *)_bytes size:(int)_packetSize; @end #endif /* __NGNet_NGSocketProtocols_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGLocalSocketDomain.h0000644000000000000000000000307115004363604021657 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGNet_NGLocalSocketDomain_H__ #define __NGNet_NGLocalSocketDomain_H__ #if !defined(WIN32) // UNIX domain, not available on WIN32 #import #include /* Represents the AF_LOCAL (AF_UNIX) socket domain. NGLocalSocketDomain is a singleton, therefore on copy it returns itself and on unarchiving it replaces the unarchived instance with the singleton. */ @interface NGLocalSocketDomain : NSObject < NSCopying, NSCoding, NGSocketDomain > + (id)domain; // NGSocketDomain - (id)addressWithRepresentation:(void *)_data size:(unsigned int)_size; - (int)socketDomain; - (int)protocol; @end #define NGDefaultLocalSocketDomain [NGLocalSocketDomain domain] #endif /* !WIN32 */ #endif /* __NGNet_NGLocalSocketDomain_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGCharBuffer.h0000644000000000000000000000361115004363604020333 0ustar rootroot/* Copyright (C) 2000-2006 SKYRIX Software AG Copyright (C) 2006 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGCharBuffer_H__ #define __NGStreams_NGCharBuffer_H__ #include #include #include struct NGCharBufferLA; /* Although NGCharBuffer is defined to be a stream, it is usually not used as such. Instead most parsers implemented using NGCharBuffer will only call -la: and -consume. Note that -la: return -1 on EOF and -readCharacter throws an NGEndOfStreamException. -readCharacter is basically a -la:0 followed by a -consume. */ @interface NGCharBuffer : NGFilterTextStream { @protected struct NGCharBufferLA *la; int bufLen; BOOL wasEOF; int headIdx; int sizeLessOne; unichar (*readCharacter)(id, SEL); } + (id)charBufferWithSource:(id)_source la:(int)_la; - (id)initWithSource:(id)_source la:(int)_la; // LA - (int)la:(int)_ls; - (void)consume; // consume one character - (void)consume:(int)_cnt; // consume _cnt characters // NGTextStream - (unichar)readCharacter; @end #endif /* __NGStreams_NGCharBuffer_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGActiveSocket.h0000644000000000000000000001027215004363604020711 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGNet_NGActiveSocket_H__ #define __NGNet_NGActiveSocket_H__ #import #include #include #include @class NSData, NSFileHandle; /* Represents an active STREAM socket based on the standard Unix sockets library. An active socket can be either a socket gained by calling accept with an passive socket or by explicitly connecting one to an address (a client socket). Therefore an active socket has two addresses, the local and the remote one. There are three methods to perform a close, this is rooted in the fact that a socket actually is full-duplex, it provides a send and a receive channel. The stream-mode is updated according to what channels are open/closed. Initially the socket is full-duplex and you cannot reopen a channel that was shutdown. If you have shutdown both channels the socket can be considered closed. */ @interface NGActiveSocket : NGSocket < NGActiveSocket > { @private id remoteAddress; NGStreamMode mode; NSTimeInterval receiveTimeout; NSTimeInterval sendTimeout; } + (id)socketConnectedToAddress:(id)_address; - (id)initWithDomain:(id)_domain; // designated initializer #if !defined(WIN32) + (BOOL)socketPair:(id[2])_pair; #endif // ******************** operations ******************** // throws // NGSocketAlreadyConnectedException when the socket is already connected // NGInvalidSocketDomainException when the remote domain != local domain // NGCouldNotCreateSocketException if the socket creation failed - (BOOL)connectToAddress:(id)_address; - (BOOL)shutdown; // do a complete shutdown - (BOOL)shutdownSendChannel; - (BOOL)shutdownReceiveChannel; // ******************** accessors ********************* - (id)remoteAddress; - (BOOL)isConnected; - (BOOL)isOpen; - (void)disableNagle:(BOOL)_disable; - (void)setSendTimeout:(NSTimeInterval)_timeout; - (NSTimeInterval)sendTimeout; - (void)setReceiveTimeout:(NSTimeInterval)_timeout; - (NSTimeInterval)receiveTimeout; // test whether a read, a write or both would block the thread (using select) - (BOOL)wouldBlockInMode:(NGStreamMode)_mode; - (int)waitForMode:(NGStreamMode)_mode timeout:(NSTimeInterval)_timeout; - (unsigned)numberOfAvailableBytesForReading; - (BOOL)isAlive; // ******************** NGStream ********************** // throws // NGStreamReadErrorException when the read call failed // NGSocketNotConnectedException when the socket is not connected // NGEndOfStreamException when the end of the stream is reached - (unsigned)readBytes:(void *)_buf count:(unsigned)_len; // throws // NGStreamWriteErrorException when the write call failed // NGSocketNotConnectedException when the socket is not connected - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len; - (BOOL)flush; // does nothing, sockets are unbuffered - (NGStreamMode)mode; // returns read/write - (BOOL)safeReadBytes:(void *)_buf count:(unsigned)_len; - (BOOL)safeWriteBytes:(const void *)_buf count:(unsigned)_len; @end @interface NGActiveSocket(DataMethods) - (NSData *)readDataOfLength:(unsigned int)_length; - (NSData *)safeReadDataOfLength:(unsigned int)_length; - (unsigned int)writeData:(NSData *)_data; - (BOOL)safeWriteData:(NSData *)_data; @end #endif /* __NGNet_NGActiveSocket_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGStreamProtocols.h0000644000000000000000000000713515004363604021471 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGStreamProtocols_H__ #define __NGStreams_NGStreamProtocols_H__ #import #if !(MAC_OS_X_VERSION_10_2 <= MAC_OS_X_VERSION_MAX_ALLOWED) # define USE_SERIALIZER 1 # import #endif @class NSException; typedef enum { NGStreamMode_undefined = 0, NGStreamMode_readOnly = 1, NGStreamMode_writeOnly = 2, NGStreamMode_readWrite = 4 } NGStreamMode; /* if this value is returned by -read, -lastException is set ... */ enum {NGStreamError = 0x7fffffff}; typedef unsigned (*NGIOReadMethodType )(id, SEL, void *, unsigned); typedef unsigned (*NGIOWriteMethodType)(id, SEL, const void *, unsigned); typedef BOOL (*NGIOSafeReadMethodType )(id, SEL, void *, unsigned); typedef BOOL (*NGIOSafeWriteMethodType)(id, SEL, const void *, unsigned); @protocol NGInputStream < NSObject > - (unsigned)readBytes:(void *)_buf count:(unsigned)_len; - (BOOL)safeReadBytes:(void *)_buf count:(unsigned)_len; - (BOOL)close; // marks - (BOOL)mark; - (BOOL)rewind; - (BOOL)markSupported; @end @protocol NGOutputStream < NSObject > - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len; - (BOOL)safeWriteBytes:(const void *)_buf count:(unsigned)_len; - (BOOL)flush; - (BOOL)close; @end @protocol NGPositionableStream < NSObject > - (BOOL)moveToLocation:(unsigned)_location; - (BOOL)moveByOffset:(int)_delta; @end @protocol NGStream < NGInputStream, NGOutputStream > - (BOOL)close; - (NGStreamMode)mode; - (NSException *)lastException; @end @protocol NGByteSequenceStream < NGInputStream > - (int)readByte; // Java semantics (-1 on EOF) @end typedef int (*NGSequenceReadByteMethod)(id self, SEL _cmd); // push streams @class NSData; @protocol NGPushStream < NSObject > - (void)pushChar:(char)_c; - (void)pushCString:(const char *)_cstr; - (void)pushData:(NSData *)_block; - (void)pushBytes:(const void *)_buffer count:(unsigned)_len; - (void)abort; @end // serializer @protocol NGSerializer < NSObject > - (void)serializeChar:(char)_value; - (void)serializeShort:(short)_value; - (void)serializeInt:(int)_value; - (void)serializeLong:(long)_value; - (void)serializeFloat:(float)_value; - (void)serializeDouble:(double)_value; - (void)serializeLongLong:(long long)_value; - (char)deserializeChar; - (short)deserializeShort; - (int)deserializeInt; - (long)deserializeLong; - (float)deserializeFloat; - (double)deserializeDouble; - (long long)deserializeLongLong; - (void)serializeCString:(const char *)_value; - (char *)deserializeCString; #if USE_SERIALIZER - (void)serializeDataAt:(const void*)data ofObjCType:(const char*)type context:(id)_callback; - (void)deserializeDataAt:(const void*)data ofObjCType:(const char*)type context:(id)_callback; #endif @end #endif /* __NGStreams_NGStreamProtocols_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGSocketExceptions.h0000644000000000000000000001257115004363604021623 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGNet_NGSocketExceptions_H__ #define __NGNet_NGSocketExceptions_H__ #import #include #include /* Exceptions: NGIOException NGSocketException NGSocketBindException NGSocketAlreadyBoundException NGCouldNotBindSocketException NGSocketConnectionException NGSocketNotConnectedException NGSocketAlreadyConnectedException NGCouldNotConnectException NGSocketOptionException NGCouldNotSetSocketOptionException NGCouldNotGetSocketOptionException NGCouldNotResolveHostNameException NGDidNotFindServiceException NGSocketIsAlreadyListeningException NGCouldNotListenException NGCouldNotAcceptException NGInvalidSocketDomainException NGCouldNotCreateSocketException NGStreamException NGEndOfStreamException NGSocketShutdownException NGSocketShutdownDuringReadException NGSocketShutdownDuringWriteException NGSocketConnectionResetException NGSocketTimedOutException */ @interface NGSocketException : NGIOException { @protected id socket; } - (id)init; - (id)initWithReason:(NSString *)_reason; - (id)initWithReason:(NSString *)_reason socket:(id)_socket; - (id)socket; @end @interface NGCouldNotResolveHostNameException : NGSocketException { @protected NSString *hostName; } - (id)initWithHostName:(NSString *)_name reason:(NSString *)_reason; - (NSString *)hostName; @end @interface NGDidNotFindServiceException : NGSocketException { @protected NSString *serviceName; } - (id)init; - (id)initWithServiceName:(NSString *)_service; - (NSString *)serviceName; @end @interface NGInvalidSocketDomainException : NGSocketException { @protected id domain; } - (id)initWithReason:(NSString *)_reason socket:(id)_socket domain:(id)_domain; @end @interface NGCouldNotCreateSocketException : NGSocketException { @protected id domain; } - (id)init; - (id)initWithReason:(NSString *)_reason domain:(id)_domain; @end // ******************** bind *********************** @interface NGSocketBindException : NGSocketException @end @interface NGSocketAlreadyBoundException : NGSocketBindException @end @interface NGCouldNotBindSocketException : NGSocketBindException { @protected id address; } - (id)initWithReason:(NSString *)_reason socket:(id)_socket address:(id)address; - (id)address; @end // ******************** connect ******************** @interface NGSocketConnectException : NGSocketException @end @interface NGSocketNotConnectedException : NGSocketConnectException @end @interface NGSocketAlreadyConnectedException : NGSocketConnectException @end @interface NGCouldNotConnectException : NGSocketConnectException { @protected id address; } - (id)initWithReason:(NSString *)_reason socket:(id)_socket address:(id)address; - (id)address; @end // ******************** listen ******************** @interface NGSocketIsAlreadyListeningException : NGSocketException @end @interface NGCouldNotListenException : NGSocketException @end // ******************** accept ******************** @interface NGCouldNotAcceptException : NGSocketException @end // ******************** options ******************** @interface NGSocketOptionException : NGSocketException { @protected int option; int level; } - (id)init; - (id)initWithReason:(NSString *)_reason option:(int)_option level:(int)_level; @end @interface NGCouldNotSetSocketOptionException : NGSocketOptionException @end @interface NGCouldNotGetSocketOptionException : NGSocketOptionException @end // ******************** socket closed ************** @interface NGSocketShutdownException : NGEndOfStreamException - (id)initWithReason:(NSString *)_reason; - (id)initWithReason:(NSString *)_reason socket:(id)_socket; - (id)initWithSocket:(id)_socket; /* Note: this only returns a valid ptr, if the socket is still retained ! */ - (id)socket; @end @interface NGSocketShutdownDuringReadException : NGSocketShutdownException @end @interface NGSocketShutdownDuringWriteException : NGSocketShutdownException @end @interface NGSocketTimedOutException : NGSocketShutdownException @end @interface NGSocketConnectionResetException : NGSocketShutdownException @end #endif /* __NGNet_NGSocketExceptions_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGStream.h0000644000000000000000000000564415004363604017567 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGStream_H__ #define __NGStreams_NGStream_H__ #import #include #include @class NSData, NSException; static inline BOOL NGCanReadInStreamMode(NGStreamMode _mode) { return ((_mode == NGStreamMode_readOnly) || (_mode == NGStreamMode_readWrite)); } static inline BOOL NGCanWriteInStreamMode(NGStreamMode _mode) { return ((_mode == NGStreamMode_writeOnly) || (_mode == NGStreamMode_readWrite)); } @interface NGStream : NSObject < NGStream, NGByteSequenceStream > // ******************** primitives ******************** // Never returns 0. If an EOF like condition occures, NGEndOfStreamException // is thrown. - (unsigned)readBytes:(void *)_buf count:(unsigned)_len; // abstract - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len; // abstract - (void)setLastException:(NSException *)_exception; - (BOOL)flush; // empty - (BOOL)close; // empty - (NGStreamMode)mode; // abstract - (BOOL)isRootStream; // abstract /* methods which read/write exactly _len bytes */ // TODO: should return exception? (would change the API significantly) - (BOOL)safeReadBytes:(void *)_buf count:(unsigned)_len; - (BOOL)safeWriteBytes:(const void *)_buf count:(unsigned)_len; /* marking */ - (BOOL)mark; // does nothing - (BOOL)rewind; // does nothing - (BOOL)markSupported; // returns NO /* convenience methods */ - (int)readByte; // java semantics (-1 returned on EOF) // description - (NSString *)modeDescription; @end @interface NGStream(DataMethods) - (NSData *)readDataOfLength:(unsigned int)_length; - (NSData *)safeReadDataOfLength:(unsigned int)_length; - (unsigned int)writeData:(NSData *)_data; - (BOOL)safeWriteData:(NSData *)_data; @end // concrete implementations as functions (to be used in non-subclasses) NGStreams_EXPORT int NGReadByteFromStream(id _stream); NGStreams_EXPORT BOOL NGSafeReadBytesFromStream(id _in, void *_buf, unsigned _len); NGStreams_EXPORT BOOL NGSafeWriteBytesToStream(id _out,const void *_buf,unsigned _len); #endif /* __NGStreams_NGStream_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGGZipStream.h0000644000000000000000000000242615004363604020354 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGZlib_NGGZipStream_H__ #define __NGZlib_NGGZipStream_H__ #include @interface NGGZipStream : NGFilterStream { @private void *outp; void *outBuf; unsigned outBufLen; unsigned long crc; BOOL headerIsWritten; } - (unsigned)readBytes:(void *)_buf count:(unsigned)_len; // decoder - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len; // encoder - (void)close; - (void)flush; @end #endif /* __NGZlib_NGGZipStream_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGNetDecls.h0000644000000000000000000000226215004363604020026 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGNet_NGNetDecls_H__ #define __NGNet_NGNetDecls_H__ #if BUILD_libNGStreams_DLL # define NGNet_EXPORT __declspec(dllexport) # define NGNet_DECLARE __declspec(dllexport) #elif libNGStreams_ISDLL # define NGNet_EXPORT extern __declspec(dllimport) # define NGNet_DECLARE extern __declspec(dllimport) #else # define NGNet_EXPORT extern # define NGNet_DECLARE #endif #endif /* __NGNet_NGNetDecls_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGTextStream.h0000644000000000000000000000417715004363604020434 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGTextStream_H__ #define __NGStreams_NGTextStream_H__ #import #include /* NGTextStream Abstract superclass for 'text streams'. Text streams are streams which are based on unichars and NSStrings instead of bytes and byte buffers. */ @class NSException; @interface NGTextStream : NSObject < NGExtendedTextStream > { @private NSException *lastException; } // NGTextInputStream - (unichar)readCharacter; // abstract - (NSException *)lastException; - (void)setLastException:(NSException *)_exception; - (void)resetLastException; /* NGExtendedTextInputStream */ - (NSString *)readLineAsString; // inefficient - (unsigned)readCharacters:(unichar *)_chars count:(unsigned)_count; - (BOOL)safeReadCharacters:(unichar *)_chars count:(unsigned)_count; // NGTextOutputStream - (BOOL)writeCharacter:(unichar)_character; // abstract - (BOOL)writeString:(NSString *)_string; // writeCharacter: based - (BOOL)flush; // does nothing // NGExtendedTextOutputStream - (BOOL)writeFormat:(NSString *)_format arguments:(va_list)_ap; - (BOOL)writeFormat:(NSString *)_format, ...; - (BOOL)writeNewline; - (unsigned)writeCharacters:(const unichar *)_chars count:(unsigned)_count; - (BOOL)safeWriteCharacters:(const unichar *)_chars count:(unsigned)_count; @end #endif /* __NGStreams_NGTextStream_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGStreamPipe.h0000644000000000000000000000327215004363604020400 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGStreamPipe_H__ #define __NGStreams_NGStreamPipe_H__ #import @interface NGStreamPipe : NSPipe < NGStream, NGByteSequenceStream > { @private int fildes[2]; NSFileHandle *fhIn; NSFileHandle *fhOut; } + (id)pipe; - (id)init; - (NSFileHandle *)fileHandleForReading; - (NSFileHandle *)fileHandleForWriting; - (id)streamForReading; - (id)streamForWriting; // NGInputStream - (unsigned)readBytes:(void *)_buf count:(unsigned)_len; - (BOOL)safeReadBytes:(void *)_buf count:(unsigned)_len; - (BOOL)mark; - (BOOL)rewind; - (BOOL)markSupported; // NGOutputStream - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len; - (BOOL)safeWriteBytes:(const void *)_buf count:(unsigned)_len; - (BOOL)flush; // NGStream - (BOOL)close; - (NGStreamMode)mode; // Extensions - (BOOL)isOpen; @end #endif /* __NGStreams_NGStreamPipe_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGDataStream.h0000644000000000000000000000454315004363604020356 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGDataStream_H__ #define __NGStreams_NGDataStream_H__ #include #include @class NSData; @interface NGDataStream : NGStream < NGPositionableStream > { @private NSException *lastException; NGStreamMode streamMode; NSData *data; unsigned position; unsigned int (*dataLength)(id, SEL); const void *(*dataBytes)(id, SEL); /* for read-only streams */ unsigned int length; const void *bytes; } + (id)dataStream; + (id)dataStreamWithCapacity:(int)_capacity; + (id)streamWithData:(NSData *)_data; - (id)initWithData:(NSData *)_data mode:(NGStreamMode)_mode; - (id)initWithData:(NSData *)_data; - (NSException *)lastException; - (void)setLastException:(NSException *)_exception; - (void)resetLastException; // accessors - (NSData *)data; - (unsigned)availableBytes; // returns number of available bytes // primitives // throws // NGStreamNotOpenException when the stream is not open // NGEndOfStreamException when the end of the stream is reached - (unsigned)readBytes:(void *)_buf count:(unsigned)_len; // throws // NGReadOnlyStreamException when the stream is not writeable // NGStreamNotOpenException when the stream is not open - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len; - (BOOL)close; - (NGStreamMode)mode; - (BOOL)isRootStream; // NGPositionableStream - (BOOL)moveToLocation:(unsigned)_location; - (BOOL)moveByOffset:(int)_delta; // blocking .. - (BOOL)wouldBlockInMode:(NGStreamMode)_mode; // always NO .. @end #endif /* __NGStreams_NGDataStream_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGCTextStream.h0000644000000000000000000000560515004363604020534 0ustar rootroot/* Copyright (C) 2000-2008 SKYRIX Software AG Copyright (C) 2008 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGCTextStream_H__ #define __NGStreams_NGCTextStream_H__ #include #include #include #include #include @class NSEnumerator; NGStreams_EXPORT id NGTextIn; NGStreams_EXPORT id NGTextOut; NGStreams_EXPORT id NGTextErr; NGStreams_EXPORT void NGInitTextStdio(void); /* NGCTextStream NGCTextStream is a text stream which operates in the operation systems default encoding (it returns the bytes read from the source as characters). Note that the results of the unicode-methods do not necessarily represent a valid unicode character. This is only the case for character codes in the 7bit ASCII set. NGCTextStream never returns a character value above 255. To retrieve correctly converted unicode characters use the NGTextStream class. */ @interface NGCTextStream : NGTextStream { @private id source; // retained NGIOReadMethodType readBytes; NGIOWriteMethodType writeBytes; BOOL (*flushBuffer)(id, SEL); NSStringEncoding encoding; } + (id)textStreamWithInputSource:(id)_source; + (id)textStreamWithOutputSource:(id)_source; + (id)textStreamWithSource:(id)_stream; - (id)initWithSource:(id)_stream; - (id)initWithInputSource:(id)_source; - (id)initWithOutputSource:(id)_source; // accessors - (id)source; // operations - (BOOL)close; // forwarded to source // NGTextInputStream, NGExtendedTextInputStream - (unichar)readCharacter; - (unsigned char)readChar; - (NSString *)readLineAsString; // Enumeration - (NSEnumerator *)lineEnumerator; // NGTextOutputStream, NGExtendedTextOutputStream - (BOOL)writeCharacter:(unichar)_character; - (BOOL)writeString:(NSString *)_string; - (BOOL)flush; - (BOOL)writeNewline; - (void)setEncoding: (NSStringEncoding) theEncoding; @end #endif /* __NGStreams_NGCTextStream_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGLocalSocketAddress.h0000644000000000000000000000420215004363604022032 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGNet_NGLocalSocketAddress_H__ #define __NGNet_NGLocalSocketAddress_H__ #if !defined(WIN32) || defined(__CYGWIN32__) /* UNIX domain sockets, currently not available on Windows The Win32 local sockets are done using so called 'named pipes'. */ #include /* Represents a UNIX domain socket address (AF_LOCAL) or a named pipe (Win32). Socket addresses are immutable. -copy therefore returns a retained self. Note that when a local socket address is archived it stores the host together with the path. This ensures that the address-space will be the same on unarchiving, otherwise it will return an error. */ @interface NGLocalSocketAddress : NSObject < NSCopying, NGSocketAddress > { @private #if defined(__WIN32__) && !defined(__CYGWIN32__) NSString *path; #else void *address; /* ptr to struct sockaddr_un */ #endif } + (id)addressWithPath:(NSString *)_path; + (id)address; - (id)initWithPath:(NSString *)_path; // designated initializer - (id)init; // creates unique path (pid,thread-id,cnt) /* accessors */ - (NSString *)path; /* testing for equality */ - (BOOL)isEqualToAddress:(NGLocalSocketAddress *)_addr; - (BOOL)isEqual:(id)_obj; /* test for accessibility */ - (BOOL)canSendOnAddress; - (BOOL)canReceiveOnAddress; @end #endif /* !WIN32 */ #endif /* __NGNet_NGLocalSocketAddress_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGDescriptorFunctions.h0000644000000000000000000000412015004363604022327 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGDescriptorFunctions_H__ #define __NGStreams_NGDescriptorFunctions_H__ #import #if !defined(WIN32) /* Polls a descriptor. Returns 1 if events occurred, 0 if a timeout occured and -1 if an error other than EINTR or EAGAIN occured. */ extern int NGPollDescriptor(int _fd, short _events, int _timeout); /* Set/Get descriptor flags */ extern int NGGetDescriptorFlags(int _fd); extern void NGSetDescriptorFlags(int _fd, int _flags); extern void NGAddDescriptorFlag (int _fd, int _flag); /* Reading and writing with non-blocking IO support. The functions return -1 on error, with errno set to either recv's or poll's errno 0 on the end of file condition -2 if the operation timed out Enable login topic 'nonblock' to find out about timeouts. */ extern int NGDescriptorRecv(int _fd, char *_buf, int _len, int _flags, int _timeout); extern int NGDescriptorSend(int _fd, const char *_buf, int _len, int _flags, int _timeout); /* Check whether the descriptor is associated to a terminal device. Get the name of the associated terminal device. */ extern BOOL NGDescriptorIsAtty(int _fd); extern NSString *NGDescriptorGetTtyName(int _fd); #endif /* !WIN32 */ #endif /* __NGStreams_NGDescriptorFunctions_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGActiveSSLSocket.h0000644000000000000000000000370715004363604021300 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG Copyright (C) 2011 Jeroen Dekkers Copyright (C) 2020 Nicolas Höft This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGNet_NGActiveSSLSocket_H__ #define __NGNet_NGActiveSSLSocket_H__ #import #import #include #include "../config.h" enum { TLSVerifyDefault = 0, TLSVerifyNone = 1, TLSVerifyAllowInsecureLocalhost = 2 }; @interface NGActiveSSLSocket : NGActiveSocket { @protected #ifdef HAVE_GNUTLS void *cred; /* real type: gnutls_certificate_credentials_t */ void *session; /* real type: gnutls_session_t */ #else void *ctx; /* real type: SSL_CTX */ void *ssl; /* real type: SSL */ #endif NSString *hostName; BOOL validatePeer; } + (id) socketConnectedToAddress: (id) _address withVerifyMode: (int) mode; - (id)initWithConnectedActiveSocket: (NGActiveSocket *) _socket withVerifyMode: (int) mode; /** * enable/disable peer certificate validation. must be called before * the handshake is performed. Default is enabled. */ - (void) validatePeerCertificate: (BOOL) validate; - (BOOL) startTLS; @end #endif /* __NGNet_NGActiveSSLSocket_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGStreamExceptions.h0000644000000000000000000001361515004363604021626 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGStreamExceptions_H__ #define __NGStreams_NGStreamExceptions_H__ #import #include @class NSData; @interface NGIOException : NSException - (id)init; - (id)initWithReason:(NSString *)_reason; + (void)raiseWithReason:(NSString *)_reason; + (void)raiseOnStream:(id)_stream reason:(NSString *)_reason; + (void)raiseOnStream:(id)_stream; @end static inline BOOL NGIsIOException(NSException *_exception) { return [_exception isKindOfClass:[NGIOException class]]; } // ******************** NGStreamException ************************* @class NSValue; @interface NGStreamException : NGIOException { @protected NSValue *streamPointer; /* only valid if stream is not deallocated */ } - (id)init; - (id)initWithStream:(id)_stream; - (id)initWithStream:(id)_stream reason:(NSString *)_reason; - (id)initWithStream:(id)_stream format:(NSString *)_format,...; + (id)exceptionWithStream:(id)_stream; + (id)exceptionWithStream:(id)_stream reason:(NSString *)_reason; + (void)raiseWithStream:(id)_stream; + (void)raiseWithStream:(id)_stream format:(NSString *)_format,...; + (void)raiseWithStream:(id)_stream reason:(NSString *)_reason; @end static inline BOOL NGIsStreamException(NSException *_exception) { return [_exception isKindOfClass:[NGStreamException class]]; } // ******************** NGEndOfStreamException ******************** @interface NGEndOfStreamException : NGStreamException { @protected unsigned readCount; // number of bytes that could be read in unsigned safeCount; // number of bytes that were requested NSData *data; } - (id)initWithStream:(id)_stream; - (id)initWithStream:(id)_stream readCount:(unsigned)_readCount safeCount:(unsigned)_safeCount data:(NSData *)_data; - (NSData *)readBytes; // the bytes read before EOF @end static inline BOOL NGIsEndOfStreamException(NSException *_exception) { return [_exception isKindOfClass:[NGEndOfStreamException class]]; } // ******************** open state exceptions ********************* @interface NGCouldNotOpenStreamException : NGStreamException @end @interface NGCouldNotCloseStreamException : NGStreamException @end @interface NGStreamNotOpenException : NGStreamException @end static inline BOOL NGIsCouldNotOpenStreamException(NSException *_exception) { return [_exception isKindOfClass:[NGCouldNotOpenStreamException class]]; } static inline BOOL NGIsCouldNotCloseStreamException(NSException *_exception) { return [_exception isKindOfClass:[NGCouldNotCloseStreamException class]]; } static inline BOOL NGIsStreamNotOpenException(NSException *_exception) { return [_exception isKindOfClass:[NGStreamNotOpenException class]]; } // ******************** NGStreamErrors **************************** @interface NGStreamErrorException : NGStreamException { @protected int osErrorCode; } - (id)initWithStream:(id)_stream errorCode:(int)_code; + (void)raiseWithStream:(id)_stream errorCode:(int)_code; - (int)operationSystemErrorCode; - (NSString *)operatingSystemError; @end static inline BOOL NGIsStreamErrorException(NSException *_exception) { return [_exception isKindOfClass:[NGStreamErrorException class]]; } @interface NGStreamReadErrorException : NGStreamErrorException @end @interface NGStreamWriteErrorException : NGStreamErrorException @end @interface NGStreamSeekErrorException : NGStreamErrorException @end static inline BOOL NGIsStreamReadErrorException(NSException *_exception) { return [_exception isKindOfClass:[NGStreamReadErrorException class]]; } static inline BOOL NGIsStreamWriteErrorException(NSException *_exception) { return [_exception isKindOfClass:[NGStreamWriteErrorException class]]; } static inline BOOL NGIsStreamSeekErrorException(NSException *_exception) { return [_exception isKindOfClass:[NGStreamSeekErrorException class]]; } // ******************** NGStreamModeExceptions ******************** @interface NGStreamModeException : NGStreamException @end @interface NGUnknownStreamModeException : NGStreamModeException { @protected NSString *streamMode; } - (id)initWithStream:(id)_stream mode:(NSString *)_streamMode; @end @interface NGReadOnlyStreamException : NGStreamModeException @end @interface NGWriteOnlyStreamException : NGStreamModeException @end static inline BOOL NGIsStreamModeException(NSException *_exception) { return [_exception isKindOfClass:[NGStreamModeException class]]; } static inline BOOL NGIsUnknownStreamModeException(NSException *_exception) { return [_exception isKindOfClass:[NGUnknownStreamModeException class]]; } static inline BOOL NGIsReadOnlyStreamException(NSException *_exception) { return [_exception isKindOfClass:[NGReadOnlyStreamException class]]; } static inline BOOL NGIsWriteOnlyStreamException(NSException *_exception) { return [_exception isKindOfClass:[NGWriteOnlyStreamException class]]; } // ******************** NGIOAccessException *********************** @interface NGIOAccessException : NGIOException @end @interface NGIOSearchAccessException : NGIOAccessException @end #endif /* __NGStreams_NGStreamExceptions_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGConcreteStreamFileHandle.h0000644000000000000000000000275215004363604023163 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGConcreteStreamFileHandle_H__ #define __NGStreams_NGConcreteStreamFileHandle_H__ #import #include @class NSData; @interface NGConcreteStreamFileHandle : NSFileHandle { id stream; } - (id)initWithStream:(id)_stream; // accessors - (id)stream; // ops - (void)closeFile; - (int)fileDescriptor; // abstract // buffering - (void)synchronizeFile; // reading - (NSData *)readDataOfLength:(unsigned int)_length; - (NSData *)readDataToEndOfFile; // writing - (void)writeData:(NSData *)_data; // seeking - (void)seekToFileOffset:(unsigned long long)_offset; @end #endif /* __NGStreams_NGConcreteStreamFileHandle_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGStringTextStream.h0000644000000000000000000000371515004363604021620 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGStringTextStream_H__ #define __NGStreams_NGStringTextStream_H__ #include #include /* NGStringTextStream A text stream which navigates inside an NSString or NSMutableString object. */ @interface NGStringTextStream : NGTextStream { @private NSString *string; // retained unsigned index; // position BOOL isMutable; } + (id)textStreamWithString:(NSString *)_string; - (id)initWithString:(NSString *)_string; // accessors - (NSString *)string; // operations - (BOOL)close; // releases string // NGTextInputStream, NGExtendedTextInputStream - (unichar)readCharacter; - (NSString *)readLineAsString; // inefficient implementation // NGTextOutputStream, NGExtendedTextOutputStream // throws // NGReadOnlyStreamException when the stream is not writeable // NGStreamNotOpenException when the stream is not open - (BOOL)writeCharacter:(unichar)_character; // throws // NGReadOnlyStreamException when the stream is not writeable // NGStreamNotOpenException when the stream is not open - (BOOL)writeString:(NSString *)_string; - (BOOL)flush; @end #endif /* __NGStreams_NGStringTextStream_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGBase64Stream.h0000644000000000000000000000316415004363604020527 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGBase64Stream_H__ #define __NGStreams_NGBase64Stream_H__ #include /* NGBase64Stream A filter stream which either decodes or encodes Base64 entities on the fly. */ @interface NGBase64Stream : NGFilterStream { @protected /* decoding */ unsigned char decBuffer[3]; // output buffer unsigned char decBufferLen; // number of bytes in buffer /* encoding */ unsigned int buf; // a 24-bit quantity unsigned int bufBytes; // how many octets are set in it unsigned char line[74]; // output buffer unsigned char lineLength; // output buffer fill pointer } - (unsigned)readBytes:(void *)_buf count:(unsigned)_len; // decoder - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len; // encoder - (BOOL)close; - (BOOL)flush; @end #endif /* __NGStreams_NGBase64Stream_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGPassiveSocket.h0000644000000000000000000000470715004363604021116 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGNet_NGPassiveSocket_H__ #define __NGNet_NGPassiveSocket_H__ #import #include #include /* Represents a STREAM server socket based on the standard Unix sockets library. A passive socket has exactly one address, the address the socket is bound to. If you do not bind the socket, the address is determined after the listen() call was executed through the getsockname() call. Note that if the socket is bound it's still an active socket in the system's view, it becomes an passive one when the listen call is executed. NOTE: Currently the passive _must_ be bound. This is because during the creation of the socket the domain is needed. The domain is encapsulated in the socket-address. Therefore the method of letting the kernel determine a socket address, as described above, currently does not work. */ @interface NGPassiveSocket : NGSocket < NGPassiveSocket > { @protected id acceptLock; // prevents file-locking int backlogSize; } + (id)socketBoundToAddress:(id)_address; /* accessors */ - (BOOL)isListening; - (BOOL)isOpen; /* operations */ // throws // NGSocketIsAlreadyListeningException when the socket is in the listen state // NGCouldNotListenException when the listen call failed - (BOOL)listenWithBacklog:(int)_backlogSize; // accept blocks when multiple threads try to accept (using acceptLock) // throws // NGCouldNotAcceptException when the socket is not listening // NGCouldNotAcceptException when the accept call failed - (id)accept; @end #endif /* __NGNet_NGPassiveSocket_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGNet.h0000644000000000000000000000270715004363604017057 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGNet_H__ #define __NGNet_H__ #include #include #include #include #include #include #include #include #include #include #if !defined(WIN32) # include # include #endif // kit class @interface NGNet : NSObject @end #define LINK_NGNet void __link_NGNet() { [NGNet class]; } #endif /* __NGNet_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGFilterTextStream.h0000644000000000000000000000224015004363604021567 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGFilterTextStream_H__ #define __NGStreams_NGFilterTextStream_H__ #include @interface NGFilterTextStream : NGTextStream { id source; } + (id)textFilterWithSource:(id)_source; - (id)initWithSource:(id)_source; // accessors - (id)source; @end #endif /* __NGStreams_NGFilterTextStream_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGUrlChars.h0000644000000000000000000000452215004363604020051 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGUrlChars_H__ #define __NGStreams_NGUrlChars_H__ static inline BOOL isUrlAlpha(unsigned char _c) { return (((_c >= 'a') && (_c <= 'z')) || ((_c >= 'A') && (_c <= 'Z'))) ? YES : NO; } static inline BOOL isUrlDigit(unsigned char _c) { return ((_c >= '0') && (_c <= '9')) ? YES : NO; } static inline BOOL isUrlSafeChar(unsigned char _c) { switch (_c) { case '$': case '-': case '_': case '@': case '.': case '&': case '+': return YES; default: return NO; } } static inline BOOL isUrlExtraChar(unsigned char _c) { switch (_c) { case '!': case '*': case '"': case '\'': case '|': case ',': return YES; } return NO; } static inline BOOL isUrlEscapeChar(unsigned char _c) { return (_c == '%') ? YES : NO; } static inline BOOL isUrlReservedChar(unsigned char _c) { switch (_c) { case '=': case ';': case '/': case '#': case '?': case ':': case ' ': return YES; } return NO; } static inline BOOL isUrlXalpha(unsigned char _c) { if (isUrlAlpha(_c)) return YES; if (isUrlDigit(_c)) return YES; if (isUrlSafeChar(_c)) return YES; if (isUrlExtraChar(_c)) return YES; if (isUrlEscapeChar(_c)) return YES; return NO; } static inline BOOL isUrlHexChar(unsigned char _c) { if (isUrlDigit(_c)) return YES; if ((_c >= 'a') && (_c <= 'f')) return YES; if ((_c >= 'A') && (_c <= 'F')) return YES; return NO; } static inline BOOL isUrlAlphaNum(unsigned char _c) { return (isUrlAlpha(_c) || isUrlDigit(_c)) ? YES : NO; } #endif /* __NGStreams_NGUrlChars_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGInternetSocketDomain.h0000644000000000000000000000401115004363604022410 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGNet_NGInternetSocketDomain_H__ #define __NGNet_NGInternetSocketDomain_H__ #import #include /* Represents the AF_INET socket domain. NGInternetSocketDomain is a singleton, therefore on copy it returns itself and on unarchiving it replaces the unarchived instance with the singleton. */ @interface NGInternetSocketDomain : NSObject < NSCoding, NSCopying, NGSocketDomain > + (id)domain; // NGSocketDomain - (id)addressWithRepresentation:(void *)_data size:(unsigned int)_size; - (int)socketDomain; - (int)protocol; @end /* Represents the AF_INET6 socket domain. NGInternetSocketDomain6 is a singleton, therefore on copy it returns itself and on unarchiving it replaces the unarchived instance with the singleton. */ @interface NGInternetSocketDomain6 : NSObject < NSCoding, NSCopying, NGSocketDomain > + (id)domain; // NGSocketDomain - (id)addressWithRepresentation:(void *)_data size:(unsigned int)_size; - (int)socketDomain; - (int)protocol; @end #define NGDefaultInternetSocketDomain [NGInternetSocketDomain domain] #define NGDefaultInternetSocketDomain6 [NGInternetSocketDomain6 domain] #endif /* __NGNet_NGInternetSocketDomain_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGByteCountStream.h0000644000000000000000000000303115004363604021410 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGByteCountStream_H__ #define __NGStreams_NGByteCountStream_H__ #include @interface NGByteCountStream : NGFilterStream { @protected unsigned totalReadCount; unsigned totalWriteCount; unsigned char byteToCount; unsigned byteReadCount; unsigned byteWriteCount; } + (id)byteCounterForStream:(id)_stream byte:(unsigned char)_byte; - (id)initWithSource:(id)_source byte:(unsigned char)_byte; // accessors - (void)setByteToCount:(unsigned char)_byte; - (unsigned char)byteToCount; - (unsigned)readCount; - (unsigned)writeCount; - (unsigned)totalReadCount; - (unsigned)totalWriteCount; // operations - (void)resetCounters; @end #endif /* __NGStreams_NGByteCountStream_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGStreamCoder.h0000644000000000000000000000642115004363604020536 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGStreamCoder_H__ #define __NGStreams_NGStreamCoder_H__ #import #if !(MAC_OS_X_VERSION_10_2 <= MAC_OS_X_VERSION_MAX_ALLOWED) # define USE_SERIALIZER 1 # import #endif #import #import #include @interface NGStreamCoder : NSCoder #if USE_SERIALIZER < NSObjCTypeSerializationCallBack > #endif { @protected id stream; // destination/source stream NGIOSafeReadMethodType readIMP; // safe read method NGIOSafeWriteMethodType writeIMP; // safe write method // used during encoding NSHashTable *outObjects; // objects written so far NSHashTable *outConditionals; // conditional objects NSHashTable *outPointers; // set of pointers NSMapTable *replacements; // src-object to replacement BOOL traceMode; // YES if finding conditionals BOOL didWriteHeader; SEL classForCoder; // default: classForCoder: SEL replObjectForCoder; // default: replacementObjectForCoder: BOOL encodingRoot; // used during decoding unsigned inArchiverVersion; // archiver's version that wrote the data NSMapTable *inObjects; // decoded objects: key -> object NSMapTable *inClasses; // decoded classes: key -> class info NSMapTable *inPointers; // decoded pointers: key -> pointer NSMapTable *inClassAlias; // archive name -> decoded name NSMapTable *inClassVersions; // archive name -> class info NSZone *objectZone; BOOL decodingRoot; BOOL didReadHeader; } + (id)coderWithStream:(id)_stream; - (id)initWithStream:(id)_stream; // accessors - (id)stream; - (NSString *)coderSignature; // ID of the coder used - (int)coderVersion; // Version of the coder used // encoding - (void)encodeConditionalObject:(id)_object; - (void)encodeRootObject:(id)_object; // decoding - (unsigned int)systemVersion; - (id)decodeObject; // Substituting One Class for Another + (NSString *)classNameDecodedForArchiveClassName:(NSString *)nameInArchive; + (void)decodeClassName:(NSString *)nameInArch asClassName:(NSString *)trueName; - (NSString *)classNameDecodedForArchiveClassName:(NSString *)nameInArchive; - (void)decodeClassName:(NSString *)nameInArch asClassName:(NSString *)trueName; @end #endif /* __NGStreams_NGStreamCoder_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGStreamsDecls.h0000644000000000000000000000232715004363604020720 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGStreamDecls_H__ #define __NGStreams_NGStreamDecls_H__ #if BUILD_libNGStreams_DLL # define NGStreams_EXPORT __declspec(dllexport) # define NGStreams_DECLARE __declspec(dllexport) #elif libNGStreams_ISDLL # define NGStreams_EXPORT extern __declspec(dllimport) # define NGStreams_DECLARE __declspec(dllimport) #else # define NGStreams_EXPORT extern # define NGStreams_DECLARE #endif #endif /* __NGStreams_NGStreamDecls_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGDatagramSocket.h0000644000000000000000000000773015004363604021223 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGNet_NGDatagramSocket_H__ #define __NGNet_NGDatagramSocket_H__ #import #include #include /* Represents an UDP socket. UDP is a protocol based on IP, it's major difference to TCP is that UDP is connectionless and unreliable (UDP datagrams send are not guaranteed to reach their destination). Note that you can connect an UDP socket. However, this only sets a 'default' target address, an UDP socket can be connected multiple times, therefore changing the default target. You can still use the send methods which take a target when the socket is connected. With UDP you do not have a distinction between active and passive sockets (you cannot put an UDP socket in the listen-state). A socket becomes a server socket by calling receive, which blocks the thread until a datagram is available and it becomes a client socket by calling send. However to send datagrams you have to know the target address of the server-socket. This is usually acomplished by binding the socket to a well-known address. The receive packet methods take a timeout argument. The timeout is accomplished by using a poll call that waits for read and timeout. A timeout of 0 specifies that no timeout is used, that means the thread will block if no data is available. When receiving a packet the socket needs to know the maximum packet size. While packets may be bigger than the maximum size, the additional bytes are discarded. If the packet size is known you should use receivePacketWithMaxSize: instead of receivePacket. If the packet size is always the same, set the maximum packet size and use receivePacket. */ extern NSString *NGSocketTimedOutNotificationName; @interface NGDatagramSocket : NGSocket { id packetFactory; int maxPacketSize; // default = 2048 struct { BOOL isConnected:1; } udpFlags; } + (id)socketBoundToAddress:(id)_address; #if !defined(WIN32) + (BOOL)socketPair:(id[2])_pair; #endif // accessors - (void)setMaxPacketSize:(int)_maxPacketSize; - (int)maxPacketSize; - (void)setPacketFactory:(id)_factory; - (id)packetFactory; - (int)socketType; // returns SOCK_DGRAM // polling - (BOOL)wouldBlockInMode:(NGStreamMode)_mode; // sending // returns NO on timeout - (BOOL)sendPacket:(id)_packet timeout:(NSTimeInterval)_timeout; // blocks until data can be send - (BOOL)sendPacket:(id)_packet; // receiving - (id)receivePacketWithMaxSize:(int)_maxPacketSize timeout:(NSTimeInterval)_timeout; - (id)receivePacketWithTimeout:(NSTimeInterval)_timeout; - (id)receivePacketWithMaxSize:(int)_maxPacketSize; - (id)receivePacket; // ************************* options ************************* // // set methods throw NGCouldNotSetSocketOptionException // get methods throw NGCouldNotGetSocketOptionException - (void)setBroadcast:(BOOL)_flag; - (BOOL)doesBroadcast; // aborts, only supported for TCP - (void)setDebug:(BOOL)_flag; - (BOOL)doesDebug; @end #endif /* __NGNet_NGDatagramSocket_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGFilterStream.h0000644000000000000000000000367115004363604020733 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGFilterStream_H__ #define __NGStreams_NGFilterStream_H__ #include /* NGFilterStream This is an abstract superclass for streams which just operate on 'basic' streams like sockets or file streams. As an example subclass take the buffered stream which performs buffered IO on any given stream. */ @interface NGFilterStream : NGStream { @protected id source; NGIOReadMethodType readBytes; NGIOWriteMethodType writeBytes; } + (id)filterWithInputSource:(id)_source; + (id)filterWithOutputSource:(id)_source; + (id)filterWithSource:(id)_source; - (id)initWithInputSource:(id)_source; - (id)initWithOutputSource:(id)_source; - (id)initWithSource:(id)_source; /* accessors */ - (id)inputStream; - (id)outputStream; - (id)source; /* primitives */ - (unsigned)readBytes:(void *)_buf count:(unsigned)_len; - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len; - (BOOL)flush; - (BOOL)close; - (NGStreamMode)mode; - (BOOL)isRootStream; @end #endif /* __NGStreams_NGFilterStream_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGByteBuffer.h0000644000000000000000000000416715004363604020370 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGByteBuffer_H__ #define __NGStreams_NGByteBuffer_H__ #include #include struct NGByteBufferLA; /* Although NGByteBuffer is defined to be a stream, it is usually not used as such. Instead most parsers implemented using NGByteBuffer will only call -la: and -consume. The stream interface is provided to read large blocks with a known length. Eg if you have a structure that prefixes some data with the data's length, you can first parse the length and then call -safeReadBytes:count: to read the content. Note that -readByte and -la: return -1 on EOF. */ @interface NGByteBuffer : NGFilterStream { @protected struct NGByteBufferLA *la; unsigned bufLen; BOOL wasEOF; unsigned headIdx; unsigned sizeLessOne; int (*readByte)(id, SEL); int (*laFunction)(id, SEL, unsigned); } /* Initialize a byte buffer with a lookahead depth of _la bytes. */ + (id)byteBufferWithSource:(id)_stream la:(unsigned)_la; - (id)initWithSource:(id)_stream la:(unsigned)_la; // LA - (int)la:(unsigned)_lookaheadPosition; - (void)consume; // consume one byte - (void)consume:(unsigned)_cnt; // consume _cnt bytes // NGStream - (int)readByte; - (unsigned)readBytes:(void *)_buf count:(unsigned)_len; @end #endif /* __NGStreams_NGByteBuffer_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGBufferedStream.h0000644000000000000000000000400415004363604021217 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGBufferedStream_H__ #define __NGStreams_NGBufferedStream_H__ #include @interface NGBufferedStream : NGFilterStream { @private void *readBuffer; void *readBufferPos; // current position (ptr) in buffer unsigned readBufferFillSize; // number of 'read' bytes in the buffer unsigned readBufferSize; // maximum capacity in bytes void *writeBuffer; unsigned writeBufferFillSize; unsigned writeBufferSize; struct { unsigned int _flushOnNewline:1; } flags; } + (id)filterWithSource:(id)_source bufferSize:(unsigned)_size; - (id)initWithSource:(id)_source bufferSize:(unsigned)_size; - (id)initWithSource:(id)_source; /* accessors */ - (void)setReadBufferSize:(unsigned)_size; - (unsigned)readBufferSize; - (void)setWriteBufferSize:(unsigned)_size; - (unsigned)writeBufferSize; /* blocking .. */ - (BOOL)wouldBlockInMode:(NGStreamMode)_mode; /* primitives */ - (unsigned)readBytes:(void *)_buf count:(unsigned)_len; - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len; - (BOOL)flush; @end @interface NGStream(NGBufferedStreamExtensions) - (NGBufferedStream *)bufferedStream; @end #endif /* __NGStreams_NGBufferedStream_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGFileStream.h0000644000000000000000000000722415004363604020363 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGFileStream_H__ #define __NGStreams_NGFileStream_H__ /* NGFileStream NGFileStream is a stream which allows reading/writing local files. */ #if defined(__MINGW32__) && defined(HAVE_WINDOWS_H) # include #endif #ifdef HAVE_POLL_H # include #endif #ifdef HAVE_SYS_POLL_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #if defined(__MINGW32__) # include #endif #include #include #include @class NSFileHandle; NGStreams_EXPORT NSString *NGFileReadOnly; NGStreams_EXPORT NSString *NGFileWriteOnly; NGStreams_EXPORT NSString *NGFileReadWrite; NGStreams_EXPORT NSString *NGFileAppend; NGStreams_EXPORT NSString *NGFileReadAppend; NGStreams_EXPORT id NGIn; NGStreams_EXPORT id NGOut; NGStreams_EXPORT id NGErr; NGStreams_EXPORT void NGInitStdio(void); @interface NGFileStream : NGStream < NGPositionableStream > { @private #if defined(__MINGW32__) HANDLE fh; // Windows file handle #else int fd; // Unix file descriptor #endif NGStreamMode streamMode; NSString *systemPath; NSFileHandle *handle; // not retained ! int markDelta; // tracks mark, for marking (special value -1) } - (id)initWithPath:(NSString *)_path; - (id)initWithFileHandle:(NSFileHandle *)_handle; // use with care ! // throws // NGUnknownStreamModeException when _mode is invalid // NGCouldNotOpenStreamException when the file could not be opened - (BOOL)openInMode:(NSString *)_mode; - (BOOL)isOpen; // Foundation file handles - (NSFileHandle *)fileHandle; - (int)fileDescriptor; #if defined(__MINGW32__) - (HANDLE)windowsFileHandle; #endif // primitives // throws // NGWriteOnlyStreamException when the stream is not readable // NGStreamNotOpenException when the stream is not open // NGEndOfStreamException when the end of the stream is reached // NGReadErrorException when the read call failed - (unsigned)readBytes:(void *)_buf count:(unsigned)_len; // throws // NGReadOnlyStreamException when the stream is not writeable // NGStreamNotOpenException when the stream is not open // NGWriteErrorException when the write call failed - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len; // throws NGCouldNotCloseStreamException when the close call failed - (BOOL)close; - (NGStreamMode)mode; - (BOOL)isRootStream; // blocking - (BOOL)wouldBlockInMode:(NGStreamMode)_mode; // not supported with Windows // marking - (BOOL)mark; - (BOOL)rewind; - (BOOL)markSupported; // returns YES // NGPositionableStream // throws // NGStreamSeekErrorException - (BOOL)moveToLocation:(unsigned)_location; // note that absolute moves delete marks // throws // NGStreamSeekErrorException - (BOOL)moveByOffset:(int)_delta; @end #endif /* __NGStreams_NGFileStream_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGStream+serialization.h0000644000000000000000000000535415004363604022436 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGStream_serialization_H__ #define __NGStreams_NGStream_serialization_H__ #include #include #include #if !(MAC_OS_X_VERSION_10_2 <= MAC_OS_X_VERSION_MAX_ALLOWED) # define USE_SERIALIZER 1 # import #endif /* Serialization is implemented as a category because of it's importance. From a design point of view it would be better placed in an extra class, so that the serialization scheme could be replaced. */ @interface NGStream(serialization) < NGSerializer > - (void)serializeChar:(char)_value; - (void)serializeShort:(short)_value; - (void)serializeInt:(int)_value; - (void)serializeLong:(long)_value; - (void)serializeFloat:(float)_value; - (void)serializeDouble:(double)_value; - (void)serializeLongLong:(long long)_value; - (char)deserializeChar; - (short)deserializeShort; - (int)deserializeInt; - (long)deserializeLong; - (float)deserializeFloat; - (double)deserializeDouble; - (long long)deserializeLongLong; - (void)serializeCString:(const char *)_value; - (char *)deserializeCString; #if USE_SERIALIZER - (void)serializeDataAt:(const void*)data ofObjCType:(const char*)type context:(id)_callback; - (void)deserializeDataAt:(void *)data ofObjCType:(const char*)type context:(id)_callback; #endif @end NGStreams_EXPORT void NGStreamSerializeObjC(id self, const void *_data, const char *_type, #if USE_SERIALIZER id _callback #else id _callback #endif ); NGStreams_EXPORT void NGStreamDeserializeObjC(id self, void *_data, const char *_type, #if USE_SERIALIZER id _callback #else id _callback #endif ); #endif /* __NGStreams_NGStream_serialization_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGTaskStream.h0000644000000000000000000000205115004363604020377 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGTaskStream_H__ #define __NGStreams_NGTaskStream_H__ #include @class NSTask; @interface NGTaskStream : NGStream { @private NSTask *task; int stdinHandle; int stdoutHandle; } @end #endif /* __NGStreams_NGTaskStream_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGLockingStream.h0000644000000000000000000000272715004363604021075 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGLockingStream_H__ #define __NGStreams_NGLockingStream_H__ #import #include @interface NGLockingStream : NGFilterStream { @private id readLock; id writeLock; void (*_lockMethod)(id, SEL); void (*_unlockMethod)(id, SEL); } + (id)filterWithSource:(id)_source lock:(id)_lock; - (id)initWithSource:(id)_source lock:(id)_lock; // primitives - (unsigned)readBytes:(void *)_buf count:(unsigned)_len; - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len; - (BOOL)flush; @end #endif /* __NGStreams_NGLockingStream_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGInternetSocketAddress.h0000644000000000000000000000650015004363604022573 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGNet_NGInternetSocketAddress_H__ #define __NGNet_NGInternetSocketAddress_H__ #include #include /* Represents an Internet socket address (AF_INET). Socket addresses are immutable. -copy therefore returns a retained self. The host arguments are id because they are allowed to be either NSString or NSHost objects (although NSString's are preferred). If the host is nil, then a wildcard (INADDR_ANY) is used. Note that the hostName is resolved when the internalAddressRepresentation is requested. */ @interface NGInternetSocketAddress : NSObject < NSCopying, NSCoding, NGSocketAddress > { @private void *address; /* ptr to struct sockaddr */ NSString *ipAddress; NSString *hostName; int port; BOOL isAddressFilled; BOOL isHostFilled; BOOL isWildcardHost; BOOL isIp6; } + (id)addressWithPort:(int)_port onHost:(id)_host; + (id)addressWithPort:(int)_port; // localhost - (id)initWithPort:(int)_port onHost:(id)_host; // designated init - (id)initWithPort:(int)_port; // localhost // these throw NGDidNotFindServiceException if the service is not found + (id)addressWithService:(NSString *)_serviceName onHost:(id)_host protocol:(NSString *)_protocol; + (id)addressWithService:(NSString *)_serviceName protocol:(NSString *)_proto; - (id)initWithService:(NSString *)_serviceName onHost:(id)_host protocol:(NSString *)_protocol; - (id)initWithService:(NSString *)_serviceName protocol:(NSString *)_protocol; + (id)wildcardAddress; + (id)wildcardAddressWithPort:(int)_port; /* accessors */ - (NSString *)address; - (int)port; - (BOOL)isWildcardAddress; - (BOOL)isIPv6; - (BOOL)isIPv4; /* testing for equality */ - (BOOL)isEqualToAddress:(NGInternetSocketAddress *)_addr; - (BOOL)isEqual:(id)_obj; /* description */ - (NSString *)stringValue; // returns 'hostname:port' as used in URLs - (NSString *)description; /* NGSocketAddress */ // throws NGCouldNotResolveHostNameException - (void *)internalAddressRepresentation; - (int)addressRepresentationSize; - (id)domain; @end @interface NGActiveSocket(NGInternetActiveSocket) // this method calls +socketConnectedToAddress: with an NGInternetSocketAddress + (id)socketConnectedToPort:(int)_port onHost:(id)_host; // this method calls -connectToAddress: with an NGInternetSocketAddress - (BOOL)connectToPort:(int)_port onHost:(id)_host; @end #endif /* __NGNet_NGInternetSocketAddress_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGTerminalSupport.h0000644000000000000000000000234615004363604021500 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGTerminalSupport_H__ #define __NGStreams_NGTerminalSupport_H__ #include #include @interface NGStream(NGTerminalSupport) - (BOOL)isAssociatedWithTerminalDevice; - (NSString *)nameOfAssociatedTerminalDevice; @end @interface NGTextStream(NGTerminalSupport) - (BOOL)isAssociatedWithTerminalDevice; - (NSString *)nameOfAssociatedTerminalDevice; @end #endif /* __NGStreams_NGTerminalSupport_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGDatagramPacket.h0000644000000000000000000000337315004363604021201 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGNet_NGDatagramPacket_H__ #define __NGNet_NGDatagramPacket_H__ #import #include @class NSData; /* This class represents an UDP datagram. It contains the addresses of it's sender and it's receiver. */ @interface NGDatagramPacket : NSObject < NGDatagramPacket > { @protected id sender; id receiver; NSData *packet; } // packet factory + (id)packetWithData:(NSData *)_data; + (id)packetWithBytes:(const void *)_bytes size:(int)_packetSize; - (id)initWithBytes:(const void *)_bytes size:(int)_size; - (id)initWithData:(NSData *)_data; // accessors - (void)setSender:(id)_address; - (id)sender; - (void)setReceiver:(id)_address; - (id)receiver; - (void)setData:(NSData *)_data; - (NSData *)data; - (int)packetSize; // operations - (void)reverseAddresses; @end #endif /* __NGNet_NGDatagramPacket_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGNetUtilities.h0000644000000000000000000000323715004363604020752 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGNet_NGNetUtilities_H__ #define __NGNet_NGNetUtilities_H__ #import #include /* Some supporting functions */ /* This function tried to 'guess' the appropriate socket address from _string. It currently creates an internet domain address if a ':' is encountered and a local domain address if the string returns true on -isAbsolutePath. The function returns nil if the string argument is nil or empty. Examples are: INET: "*:20000" // wildcard IP, port 20000 "localhost:1000" // localhost, port 1000 "*:echo/udp" // wildcard IP, echo service on UDP "*:echo" // wildcard IP, echo service on TCP (TCP=default) LOCAL: "/tmp/mySocket" */ id NGSocketAddressFromString(NSString *_string); #endif /* __NGNet_NGNetUtilities_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGStreams.h0000644000000000000000000000345015004363604017743 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_H__ #define __NGStreams_H__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // kit class @interface NGStreams : NSObject @end // static linking #define LINK_NGStreams \ void __link_NGStreams(void) { \ [NGStreams class]; \ __link_NGStreams(); \ } #endif /* __NGStreams_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGSocket.h0000644000000000000000000001262615004363604017562 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGNet_NGSocket_H__ #define __NGNet_NGSocket_H__ #import #include #if defined(WIN32) # include #endif @class NSFileHandle, NSException; /* Represents the sockets accessible through the standard Unix sockets library. The socket class itself is abstract and has two concrete subclasses, NGActiveSocket and NGPassiveSocket. The terminology may be confusing at first, but I choose to use these instead of Client/ServerSocket because the NGPassiveSocket accept method returns a socket which isn't one of these. It's an active socket which is already connected. NGActiveSocket represents a connection while NGPassiveSocket only accepts connections (it can't be read or written). Each socket has a local address. The socket can be bound to an address by using the bind() call or the address can be assigned by the operating system kernel. Passive sockets are normally bound to a well-known port (or service), active sockets receive in most cases their address from the kernel. fd is the file descriptor gained through the socket() call. closeOnFree specifies whether the socket is closed when the memory for the socket object is reclaimed. Note that the creation of the actual socket has to wait until it is bound or a connect or listen call has been initiated. This is because the socket() call needs the socket-domain, which is encapsulated in the NGSocketAddress objects. Until the socket is created the fd variable contains the value NGInvalidSocketDescriptor. */ #if defined(WIN32) # define NGInvalidSocketDescriptor INVALID_SOCKET #else # define NGInvalidSocketDescriptor ((int)-1) #endif @interface NGSocket : NSObject < NGSocket > { @protected #if defined(WIN32) SOCKET fd; #else int fd; // socket descriptor #endif id domain; id localAddress; NSFileHandle *fileHandle; // not retained ! struct { int closeOnFree:1; // close socket on collect/dealloc ? int isBound:1; // was a bind issued (either by the kernel or explicitly) } flags; NSException *lastException; } + (id)socketInDomain:(id)_domain; - (id)initWithDomain:(id)_domain; // designated initializer // ************************* create a socket ***************** - (BOOL)primaryCreateSocket; - (BOOL)close; // ************************* bind a socket ******************* // throws // NGSocketAlreadyBoundException if the socket is already bound - (BOOL)bindToAddress:(id)_address; // throws // NGSocketAlreadyBoundException if the socket is already bound - (BOOL)kernelBoundAddress; // ************************* accessors *********************** - (id)localAddress; - (BOOL)isBound; - (void)setLastException:(NSException *)_exception; - (NSException *)lastException; - (void)resetLastException; - (int)socketType; // abstract - (id)domain; - (NSFileHandle *)fileHandle; #if defined(WIN32) - (SOCKET)fileDescriptor; #else - (int)fileDescriptor; - (void)setFileDescriptor: (int) theFd closeWhenDone: (BOOL) closeFd; #endif // ************************* options ************************* // // set methods throw NGCouldNotSetSocketOptionException // get methods throw NGCouldNotGetSocketOptionException - (void)setDebug:(BOOL)_flag; - (void)setReuseAddress:(BOOL)_flag; - (void)setKeepAlive:(BOOL)_flag; - (void)setDontRoute:(BOOL)_flag; - (BOOL)doesDebug; - (BOOL)doesReuseAddress; - (BOOL)doesKeepAlive; - (BOOL)doesNotRoute; - (void)setSendBufferSize:(int)_size; - (void)setReceiveBufferSize:(int)_size; - (int)sendBufferSize; - (int)receiveBufferSize; @end #if defined(WIN32) // Windows Descriptor Functions // events # ifndef POLLIN # define POLLRDNORM 1 # define POLLIN POLLRDNORM # define POLLWRNORM 2 # define POLLOUT POLLWRNORM # define POLLERR 4 # define POLLHUP 4 # endif /* Polls a descriptor. Returns 1 if events occurred, 0 if a timeout occured and -1 if an error other than EINTR or EAGAIN occured. */ int NGPollDescriptor(SOCKET _fd, short _events, int _timeout); /* Reading and writing with non-blocking IO support. The functions return -1 on error, with errno set to either recv's or poll's errno 0 on the end of file condition -2 if the operation timed out Enable login topic 'nonblock' to find out about timeouts. */ int NGDescriptorRecv(SOCKET _fd, char *_buf, int _len, int _flags, int _timeout); int NGDescriptorSend(SOCKET _fd, const char *_buf, int _len, int _flags, int _timeout); #endif /* WIN32 */ #endif /* __NGNet_NGSocket_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGTextStreamProtocols.h0000644000000000000000000000325515004363604022335 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGStreams_NGTextStreamProtocols_H__ #define __NGStreams_NGTextStreamProtocols_H__ #import #import @class NSString, NSException; @protocol NGTextInputStream < NSObject > - (unichar)readCharacter; @end @protocol NGTextOutputStream < NSObject > - (BOOL)writeCharacter:(unichar)_character; - (BOOL)writeString:(NSString *)_string; - (BOOL)flush; @end @protocol NGTextStream < NGTextInputStream, NGTextOutputStream > - (NSException *)lastException; @end // extended text streams @protocol NGExtendedTextInputStream < NGTextInputStream > - (NSString *)readLineAsString; @end @protocol NGExtendedTextOutputStream < NGTextOutputStream > - (BOOL)writeFormat:(NSString *)_format, ...; - (BOOL)writeNewline; @end @protocol NGExtendedTextStream < NGExtendedTextInputStream, NGExtendedTextOutputStream > @end #endif /* __NGStreams_NGTextStreamProtocols_H__ */ SOPE/sope-core/NGStreams/NGStreams/NGActiveSocket+serialization.h0000644000000000000000000000412015004363604023555 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGNet_NGActiveSocket_serialization_H__ #define __NGNet_NGActiveSocket_serialization_H__ #if !(MAC_OS_X_VERSION_10_2 <= MAC_OS_X_VERSION_MAX_ALLOWED) # define USE_SERIALIZER 1 #endif #import #if USE_SERIALIZER # import #endif #include #include @interface NGActiveSocket(serialization) #if USE_SERIALIZER < NGSerializer > #endif - (void)serializeChar:(char)_value; - (void)serializeShort:(short)_value; - (void)serializeInt:(int)_value; - (void)serializeLong:(long)_value; - (void)serializeFloat:(float)_value; - (void)serializeDouble:(double)_value; - (void)serializeLongLong:(long long)_value; - (char)deserializeChar; - (short)deserializeShort; - (int)deserializeInt; - (long)deserializeLong; - (float)deserializeFloat; - (double)deserializeDouble; - (long long)deserializeLongLong; - (void)serializeCString:(const char *)_value; - (char *)deserializeCString; #if USE_SERIALIZER - (void)serializeDataAt:(const void*)data ofObjCType:(const char*)type context:(id)_callback; - (void)deserializeDataAt:(void *)data ofObjCType:(const char*)type context:(id)_callback; #endif @end #endif /* __NGNet_NGActiveSocket_serialization_H__ */ SOPE/sope-core/NGStreams/NGTerminalSupport.m0000644000000000000000000000520015004363604017632 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGTerminalSupport.h" #include "NGFileStream.h" #include "NGFilterStream.h" #include "NGCTextStream.h" #include "NGDescriptorFunctions.h" @implementation NGStream(NGTerminalSupport) - (BOOL)isAssociatedWithTerminalDevice { return NO; } - (NSString *)nameOfAssociatedTerminalDevice { return nil; } @end @implementation NGFileStream(NGTerminalSupport) - (BOOL)isAssociatedWithTerminalDevice { #if defined(WIN32) return NO; #else return [self isOpen] ? NGDescriptorIsAtty(self->fd) : NO; #endif } - (NSString *)nameOfAssociatedTerminalDevice { #if defined(WIN32) return nil; #else return [self isOpen] ? NGDescriptorGetTtyName(self->fd) : (NSString *)nil; #endif } @end /* NGFileStream(NGTerminalSupport) */ @implementation NGFilterStream(NGTerminalSupport) - (BOOL)isAssociatedWithTerminalDevice { id src = [self source]; return [src respondsToSelector:_cmd] ? [src isAssociatedWithTerminalDevice] : NO; } - (NSString *)nameOfAssociatedTerminalDevice { id src = [self source]; return [src respondsToSelector:_cmd] ? [src nameOfAssociatedTerminalDevice] : NO; } @end /* NGFilterStream(NGTerminalSupport) */ @implementation NGTextStream(NGTerminalSupport) - (BOOL)isAssociatedWithTerminalDevice { return NO; } - (NSString *)nameOfAssociatedTerminalDevice { return nil; } @end /* NGTextStream(NGTerminalSupport) */ @implementation NGCTextStream(NGTerminalSupport) - (BOOL)isAssociatedWithTerminalDevice { id src = [self source]; return [src respondsToSelector:_cmd] ? [src isAssociatedWithTerminalDevice] : NO; } - (NSString *)nameOfAssociatedTerminalDevice { id src = [self source]; return [src respondsToSelector:_cmd] ? [src nameOfAssociatedTerminalDevice] : NO; } @end /* NGCTextStream(NGTerminalSupport) */ void __link_NGStreams_NGTerminalSupport(void) { __link_NGStreams_NGTerminalSupport(); } SOPE/sope-core/NGStreams/NGLockingStream.m0000644000000000000000000000627515004363604017241 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "common.h" @implementation NGLockingStream + (id)filterWithSource:(id)_source lock:(id)_lock { return [[[self alloc] initWithSource:_source lock:_lock] autorelease]; } - (id)initWithSource:(id)_source lock:(id)_lock { if ((self = [super initWithSource:_source])) { if (_lock == nil) { readLock = [[NSRecursiveLock allocWithZone:[self zone]] init]; writeLock = [readLock retain]; } else { readLock = [_lock retain]; writeLock = [readLock retain]; } } return self; } - (id)initWithSource:(id)_source { return [self initWithSource:_source lock:nil]; } - (void)dealloc { [self->readLock release]; [self->writeLock release]; [super dealloc]; } // primitives - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { volatile unsigned result = 0; [readLock lock]; NS_DURING { result = (readBytes != NULL) ? (unsigned)readBytes(source, _cmd, _buf, _len) : [source readBytes:_buf count:_len]; } NS_HANDLER { [readLock unlock]; [localException raise]; } NS_ENDHANDLER; [readLock unlock]; return result; } - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len { volatile unsigned result = 0; [writeLock lock]; NS_DURING { result = (writeBytes != NULL) ? (unsigned)writeBytes(source, _cmd, _buf, _len) : [source writeBytes:_buf count:_len]; } NS_HANDLER { [writeLock unlock]; [localException raise]; } NS_ENDHANDLER; [writeLock unlock]; return result; } - (BOOL)flush { BOOL res = NO; [writeLock lock]; NS_DURING { res = [super flush]; } NS_HANDLER { [writeLock unlock]; [localException raise]; } NS_ENDHANDLER; [writeLock unlock]; return res; } - (BOOL)safeReadBytes:(void *)_buf count:(unsigned)_len { BOOL res = NO; [readLock lock]; NS_DURING { res = [super safeReadBytes:_buf count:_len]; } NS_HANDLER { [readLock unlock]; [localException raise]; } NS_ENDHANDLER; [readLock unlock]; return res; } - (BOOL)safeWriteBytes:(const void *)_buf count:(unsigned)_len { BOOL res = NO; [writeLock lock]; NS_DURING { res = [super safeWriteBytes:_buf count:_len]; } NS_HANDLER { [writeLock unlock]; [localException raise]; } NS_ENDHANDLER; [writeLock unlock]; return res; } @end /* NGLockingStream */ SOPE/sope-core/NGStreams/NGBase64Stream.m0000644000000000000000000002310215004363604016663 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "common.h" static inline BOOL isbase64(char a) { if (('A' <= a) && (a <= 'Z')) return YES; if (('a' <= a) && (a <= 'z')) return YES; if (('0' <= a) && (a <= '9')) return YES; if ((a == '+') || (a == '/')) return YES; return NO; } @implementation NGBase64Stream // ******************** decoding ******************** static char dmap[256] = { 127, 127, 127, 127, 127, 127, 127, 127, // 000-007 127, 127, 127, 127, 127, 127, 127, 127, // 010-017 127, 127, 127, 127, 127, 127, 127, 127, // 020-027 127, 127, 127, 127, 127, 127, 127, 127, // 030-037 127, 127, 127, 127, 127, 127, 127, 127, // 040-047 !"#$%&' 127, 127, 127, 62, 127, 127, 127, 63, // 050-057 ()*+,-./ 52, 53, 54, 55, 56, 57, 58, 59, // 060-067 01234567 60, 61, 127, 127, 127, 126, 127, 127, // 070-077 89:;<=>? 127, 0, 1, 2, 3, 4, 5, 6, // 100-107 @ABCDEFG 7, 8, 9, 10, 11, 12, 13, 14, // 110-117 HIJKLMNO 15, 16, 17, 18, 19, 20, 21, 22, // 120-127 PQRSTUVW 23, 24, 25, 127, 127, 127, 127, 127, // 130-137 XYZ[\]^_ 127, 26, 27, 28, 29, 30, 31, 32, // 140-147 `abcdefg 33, 34, 35, 36, 37, 38, 39, 40, // 150-157 hijklmno 41, 42, 43, 44, 45, 46, 47, 48, // 160-167 pqrstuvw 49, 50, 51, 127, 127, 127, 127, 127, // 170-177 xyz{|}~ 127, 127, 127, 127, 127, 127, 127, 127, // 200-207 127, 127, 127, 127, 127, 127, 127, 127, // 210-217 127, 127, 127, 127, 127, 127, 127, 127, // 220-227 127, 127, 127, 127, 127, 127, 127, 127, // 230-237 127, 127, 127, 127, 127, 127, 127, 127, // 240-247 127, 127, 127, 127, 127, 127, 127, 127, // 250-257 127, 127, 127, 127, 127, 127, 127, 127, // 260-267 127, 127, 127, 127, 127, 127, 127, 127, // 270-277 127, 127, 127, 127, 127, 127, 127, 127, // 300-307 127, 127, 127, 127, 127, 127, 127, 127, // 310-317 127, 127, 127, 127, 127, 127, 127, 127, // 320-327 127, 127, 127, 127, 127, 127, 127, 127, // 330-337 127, 127, 127, 127, 127, 127, 127, 127, // 340-347 127, 127, 127, 127, 127, 127, 127, 127, // 350-357 127, 127, 127, 127, 127, 127, 127, 127, // 360-367 127, 127, 127, 127, 127, 127, 127, 127, // 370-377 }; - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { unsigned char chunk[4]; // input buffer unsigned char chunkLen; // input buffer length unsigned readLen = 0; if (self->decBufferLen == 0) { // no bytes in buffer, read next token register unsigned value; { volatile unsigned pos = 0, toGo = 4; char tmp[4]; memset(chunk, 126, sizeof(chunk)); // set all EOF NS_DURING { do { unsigned readCount = 0; unsigned char i; readCount = [super readBytes:tmp count:toGo]; NSAssert(readCount != 0, @"invalid result from readBytes:count:"); for (i = 0; i < readCount; i++) { if (isbase64(tmp[(int)i])) { chunk[pos] = tmp[(int)i]; pos++; toGo--; } } } while (toGo > 0); } NS_HANDLER { if ([localException isKindOfClass:[NGEndOfStreamException class]]) { if (pos == 0) [localException raise]; } else [localException raise]; } NS_ENDHANDLER; chunkLen = pos; } NSAssert(chunkLen > 0, @"invalid chunk len (should have thrown EOF) .."); if (chunkLen == 4) { // complete token NSCAssert(self->decBufferLen == 0, @"data pending in buffer .."); NSCAssert(chunkLen == 4, @"invalid chunk size .."); value = ((dmap[chunk[0]] << 18) | (dmap[chunk[1]] << 12) | (dmap[chunk[2]] << 6) | (dmap[chunk[3]])); self->decBuffer[0] = (unsigned char)(0xFF & (value >> 16)); self->decBuffer[1] = (unsigned char)(0xFF & (value >> 8)); self->decBuffer[2] = (unsigned char)(0xFF & (value)); self->decBufferLen = 3; } else { unsigned char b0 = dmap[chunk[0]]; unsigned char b1 = dmap[chunk[1]]; unsigned char b2 = dmap[chunk[2]]; unsigned char b3 = dmap[chunk[3]]; char eqCount = 0; // number of equal signs NSCAssert(self->decBufferLen == 0, @"data pending in buffer .."); if (b0 == 126) { b0 = 0; eqCount++; } if (b1 == 126) { b1 = 0; eqCount++; } if (b2 == 126) { b2 = 0; eqCount++; } if (b3 == 126) { b3 = 0; eqCount++; } value = ((b0 << 18) | (b1 << 12) | (b2 << 6) | (b3)); self->decBuffer[0] = (unsigned char)(value >> 16); self->decBufferLen = 1; if (eqCount <= 1) { self->decBuffer[1] = (unsigned char)((value >> 8) & 0xFF); self->decBufferLen = 2; if (eqCount == 0) { self->decBuffer[2] = (unsigned char)((value & 0xFF)); self->decBufferLen = 3; } } } NSAssert((self->decBufferLen > 0) && (self->decBufferLen < 4), @"invalid result length .."); } // copy decoded bytes to output buffer if (_len >= self->decBufferLen) { readLen = self->decBufferLen; memcpy(_buf, self->decBuffer, readLen); self->decBufferLen = 0; } else { readLen = _len; NSAssert((readLen > 0) && (readLen < 3), @"invalid length .."); if (readLen == 1) { *(char *)_buf = self->decBuffer[0]; self->decBuffer[0] = self->decBuffer[1]; self->decBuffer[1] = self->decBuffer[2]; self->decBufferLen--; } else { // readLen == 2; ((char *)_buf)[0] = self->decBuffer[0]; ((char *)_buf)[1] = self->decBuffer[1]; self->decBuffer[0] = self->decBuffer[2]; self->decBufferLen -= 2; } } return readLen; } // ******************** encoding ******************** static char emap[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0-7 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 8-15 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 16-23 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 24-31 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 32-39 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 40-47 'w', 'x', 'y', 'z', '0', '1', '2', '3', // 48-55 '4', '5', '6', '7', '8', '9', '+', '/' // 56-63 }; static inline void _encodeToken(NGBase64Stream *self) { int i = self->lineLength; // ratio 3:4 self->line[i] = emap[0x3F & (self->buf >> 18)]; // sextet 1 (octet 1) self->line[i + 1] = emap[0x3F & (self->buf >> 12)]; // sextet 2 (octet 1 and 2) self->line[i + 2] = emap[0x3F & (self->buf >> 6)]; // sextet 3 (octet 2 and 3) self->line[i + 3] = emap[0x3F & (self->buf)]; // sextet 4 (octet 3) self->lineLength += 4; self->buf = 0; self->bufBytes = 0; } static inline void _encodePartialToken(NGBase64Stream *self) { int i = self->lineLength; self->line[i] = emap[0x3F & (self->buf >> 18)]; // sextet 1 (octet 1) self->line[i + 1] = emap[0x3F & (self->buf >> 12)]; // sextet 2 (octet 1 and 2) self->line[i + 2] = (self->bufBytes == 1) ? '=' : emap[0x3F & (self->buf >> 6)]; self->line[i + 3] = (self->bufBytes <= 2) ? '=' : emap[0x3F & (self->buf)]; self->lineLength += 4; self->buf = 0; self->bufBytes = 0; } static inline void _flushLine(NGBase64Stream *self) { [self->source safeWriteBytes:self->line count:self->lineLength]; self->lineLength = 0; } static inline void _encode(NGBase64Stream *self, const char *_in, unsigned _inLen) { // Given a sequence of input bytes, produces a sequence of output bytes // using the base64 encoding. register unsigned int i; for (i = 0; i < _inLen; i++) { if (self->bufBytes == 0) self->buf = ((self->buf & 0xFFFF) | (_in[i] << 16)); else if (self->bufBytes == 1) self->buf = ((self->buf & 0xFF00FF) | ((_in[i] << 8) & 0xFFFF)); else self->buf = ((self->buf & 0xFFFF00) | (_in[i] & 0xFF)); if ((++(self->bufBytes)) == 3) { _encodeToken(self); if (self->lineLength >= 72) _flushLine(self); } if (i == (_inLen - 1)) { if ((self->bufBytes > 0) && (self->bufBytes < 3)) _encodePartialToken(self); if (self->lineLength > 0) _flushLine(self); } } // reset line buffer memset(self->line, 0, sizeof(self->line)); } - (BOOL)close { if (![self flush]) return NO; if (![super close]) return NO; return YES; } - (BOOL)flush { // output buffer if (self->bufBytes) _encodePartialToken(self); _flushLine(self); // reset line buffer memset(self->line, 0, sizeof(self->line)); return [super flush]; } - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len { _encode(self, _buf, _len); return _len; } @end /* NGBase64Stream */ SOPE/sope-core/NGStreams/NGSocket+private.h0000644000000000000000000000246515004363604017365 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGSocket.h" @interface NGSocket(PrivateMethods) #if defined(WIN32) - (id)_initWithDomain:(id)_domain descriptor:(SOCKET)_fd; #else - (id)_initWithDomain:(id)_domain descriptor:(int)_fd; #endif - (void)setOption:(int)_option value:(void *)_value len:(int)_len; - (void)getOption:(int)_option value:(void *)_value len:(int *)_len; - (void)setOption:(int)_option level:(int)_level value:(void *)_value len:(int)_len; - (void)getOption:(int)_option level:(int)_level value:(void *)_val len:(int *)_len; @end SOPE/sope-core/NGStreams/COPYRIGHT0000644000000000000000000000010615004363604015352 0ustar rootrootCopyright (C) 2000-2005 SKYRIX Software AG Contact: info@skyrix.com SOPE/sope-core/NGStreams/NGStringTextStream.m0000644000000000000000000001003715004363604017755 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #include "NGStringTextStream.h" #include "NGStreamExceptions.h" @implementation NGStringTextStream + (id)textStreamWithString:(NSString *)_string { return [[[self alloc] initWithString:_string] autorelease]; } - (id)initWithString:(NSString *)_string { if ((self = [super init])) { self->string = [_string retain]; self->index = 0; self->isMutable = [_string isKindOfClass:[NSMutableString class]]; } return self; } - (void)dealloc { [self->string release]; [super dealloc]; } /* accessors */ - (NSString *)string { return string; } /* operations */ - (BOOL)close { // releases string [self->string release]; self->string = nil; return YES; } // NGTextInputStream - (unichar)readCharacter { // throws // NGStreamNotOpenException when the stream is not open unsigned currentLength = [string length]; unichar result; if (string == nil) { [NGStreamNotOpenException raiseWithReason: @"tried to read from a string text stream which was closed"]; } if (currentLength == index) [[[NGEndOfStreamException alloc] init] raise]; result = [string characterAtIndex:index]; index++; return result; } // NGExtendedTextInputStream - (NSString *)readLineAsString { // throws // NGStreamNotOpenException when the stream is not open unsigned currentLength = [string length]; NSRange range; if (string == nil) { [NGStreamNotOpenException raiseWithReason: @"tried to read from a string text stream which was closed"]; } if (currentLength == index) //[[[NGEndOfStreamException alloc] init] raise] return nil; range.location = index; range.length = (currentLength - index); range = [string rangeOfString:@"\n" options:NSLiteralSearch range:range]; if (range.length == 0) { // did not found newline NSString *result = [string substringFromIndex:index]; index = currentLength; return result; } else { NSString *result = nil; range.length = (range.location - index); range.location = index; result = [string substringWithRange:range]; index += range.length + 1; return result; } } // NGTextOutputStream - (BOOL)writeCharacter:(unichar)_character { // throws // NGReadOnlyStreamException when the stream is not writeable // NGStreamNotOpenException when the stream is not open if (string == nil) { [NGStreamNotOpenException raiseWithReason: @"tried to write to a string text stream which was closed"]; return NO; } if (!isMutable) { [[[NGReadOnlyStreamException alloc] init] raise]; return NO; } [(NSMutableString *)string appendString: [NSString stringWithCharacters:&_character length:1]]; return YES; } - (BOOL)writeString:(NSString *)_string { // throws // NGReadOnlyStreamException when the stream is not writeable // NGStreamNotOpenException when the stream is not open if (string == nil) { [NGStreamNotOpenException raiseWithReason: @"tried to write to a string text stream which was closed"]; return NO; } if (!isMutable) { [[[NGReadOnlyStreamException alloc] init] raise]; return NO; } [(NSMutableString *)string appendString:_string]; return YES; } - (BOOL)flush { return YES; } @end /* NGStringTextStream */ SOPE/sope-core/NGStreams/NGSocket.m0000644000000000000000000005054415004363604015725 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "NGSocketExceptions.h" #include "NGSocket.h" #include "NGSocket+private.h" #include "NGInternetSocketDomain.h" #include "config.h" #if defined(__APPLE__) # include # include #endif #if defined(HAVE_UNISTD_H) || defined(__APPLE__) # include #endif #include "common.h" @interface _NGConcreteSocketFileHandle : NGConcreteStreamFileHandle { } - (id)initWithSocket:(id)_socket; @end @interface NSObject(WildcardAddresses) - (BOOL)isWildcardAddress; @end #ifdef __s390__ # define SockAddrLenType socklen_t #elif __APPLE__ # define SockAddrLenType unsigned int #else # define SockAddrLenType socklen_t #endif @implementation NGSocket #if defined(WIN32) && !defined(__CYGWIN32__) static BOOL isInitialized = NO; static WSADATA wsaData; + (void)initialize { if (!isInitialized) { isInitialized = YES; if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) NSLog(@"WARNING: Could not start Windows sockets !"); NSLog(@"WinSock version %i.%i.", LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion)); } } static void _killWinSock(void) __attribute__((destructor)); static void _killWinSock(void) { fprintf(stderr, "killing Windows sockets ..\n"); if (isInitialized) { WSACleanup(); isInitialized = NO; } } #endif /* WIN32 */ + (id)socketInDomain:(id)_domain { return [[[self alloc] initWithDomain:_domain] autorelease]; } - (id)init { return [self initWithDomain:[NGInternetSocketDomain domain]]; } #if defined(WIN32) && !defined(__CYGWIN32__) - (id)_initWithDomain:(id)_domain descriptor:(SOCKET)_fd { #else - (id)_initWithDomain:(id)_domain descriptor:(int)_fd { #endif if ((self = [super init])) { self->fd = _fd; self->flags.closeOnFree = YES; self->flags.isBound = (_fd == NGInvalidSocketDescriptor) ? NO : YES; self->domain = [_domain retain]; if (_fd == NGInvalidSocketDescriptor) [self primaryCreateSocket]; } return self; } - (id)initWithDomain:(id)_domain { return [self _initWithDomain:_domain descriptor:NGInvalidSocketDescriptor]; } - (void)gcFinalize { [self close]; } - (void)dealloc { [self gcFinalize]; [self->lastException release]; [self->localAddress release]; [self->domain release]; self->fileHandle = nil; [super dealloc]; } /* creation */ - (BOOL)primaryCreateSocket { // throws // NGCouldNotCreateSocketException if the socket creation failed fd = socket([domain socketDomain], [self socketType], [domain protocol]); #if defined(WIN32) && !defined(__CYGWIN32__) if (fd == SOCKET_ERROR) { // error int e = WSAGetLastError(); NSString *reason = nil; switch (e) { case WSAEACCES: reason = @"Not allowed to create socket of this type"; break; case WSAEMFILE: reason = @"Could not create socket: descriptor table is full"; break; case WSAEPROTONOSUPPORT: reason = @"Could not create socket: The protocol type or the specified " @"protocol is not supported within this domain"; break; default: reason = [NSString stringWithFormat:@"Could not create socket: %s", strerror(e)]; break; } #else if (fd == -1) { // error int e = errno; NSString *reason = nil; switch (e) { case EACCES: reason = @"Not allowed to create socket of this type"; break; case EMFILE: reason = @"Could not create socket: descriptor table is full"; break; case ENOMEM: reason = @"Could not create socket: Insufficient user memory available"; break; case EPROTONOSUPPORT: reason = @"Could not create socket: The protocol type or the specified " @"protocol is not supported within this domain"; break; default: reason = [NSString stringWithFormat:@"Could not create socket: %s", strerror(e)]; break; } #endif [[[NGCouldNotCreateSocketException alloc] initWithReason:reason domain:domain] raise]; return NO; } return YES; } - (BOOL)close { if (self->fd != NGInvalidSocketDescriptor && self->flags.closeOnFree) { #if DEBUG && 0 NSLog(@"%@: closing socket fd %i", self, self->fd); #endif #if defined(WIN32) && !defined(__CYGWIN32__) closesocket(self->fd); #else close(self->fd); #endif self->fd = NGInvalidSocketDescriptor; if (self->flags.isBound) { self->flags.isBound = NO; [[self domain] cleanupAddress:self->localAddress afterCloseOfSocket:self]; } else self->flags.isBound = NO; } self->fd = NGInvalidSocketDescriptor; return YES; } /* operations */ - (void)setLastException:(NSException *)_exception { /* NOTE: watch out for cycles !!! */ // THREAD ASSIGN(self->lastException, _exception); } - (NSException *)lastException { // THREAD return self->lastException; } - (void)resetLastException { // THREAD ASSIGN(self->lastException,(id)nil); } - (BOOL)primaryBindToAddress:(id)_address { // throws // NGCouldNotBindSocketException if the bind failed [[self domain] prepareAddress:_address forBindWithSocket:self]; if (bind(fd, (struct sockaddr *)[_address internalAddressRepresentation], [_address addressRepresentationSize]) != 0) { NSString *reason = nil; #if defined(WIN32) && !defined(__CYGWIN32__) int errorCode = WSAGetLastError(); #else int errorCode = errno; #endif switch (errorCode) { default: reason = [NSString stringWithCString:strerror(errorCode)]; break; } reason = [NSString stringWithFormat:@"Could not bind to address %@: %@", _address, reason]; [[[NGCouldNotBindSocketException alloc] initWithReason:reason socket:self address:_address] raise]; return NO; } /* bind was successful */ ASSIGN(self->localAddress, _address); self->flags.isBound = YES; return YES; } - (BOOL)bindToAddress:(id)_address { // throws // NGSocketAlreadyBoundException if the socket is already bound // NGCouldNotCreateSocketException if the socket creation failed // NGCouldNotBindSocketException if the bind failed // check whether socket is already bound (either manually or by the kernel) if (flags.isBound) { [[[NGSocketAlreadyBoundException alloc] initWithReason:@"socket is already bound." socket:self] raise]; } if (_address == nil) { /* let kernel bind address */ return [self kernelBoundAddress]; } // perform bind if (![self primaryBindToAddress:_address]) return NO; /* check for wildcard port */ if ([_address respondsToSelector:@selector(isWildcardAddress)]) { if ([(id)_address isWildcardAddress]) { SockAddrLenType len = [[_address domain] addressRepresentationSize]; char data[len]; // struct sockaddr if (getsockname(fd, (void *)&data, &len) == 0) { // function is MT-safe id boundAddr; boundAddr = [[_address domain] addressWithRepresentation:&(data[0]) size:len]; #if 0 NSLog(@"got sock name (addr-len=%d, %s, %d) %@ ..", len, inet_ntoa( (((struct sockaddr_in *)(&data[0]))->sin_addr)), ntohs(((struct sockaddr_in *)(&data[0]))->sin_port), boundAddr); #endif ASSIGN(self->localAddress, boundAddr); } else { // could not get local socket name, THROW NSLog(@"ERROR: couldn't resolve wildcard address %@", _address); } } } return YES; } - (BOOL)kernelBoundAddress { SockAddrLenType len = [[self domain] addressRepresentationSize]; char data[len]; // check whether socket is already bound (either manually or by the kernel) if (flags.isBound) { [[[NGSocketAlreadyBoundException alloc] initWithReason:@"socket is already bound." socket:self] raise]; return NO; } #if 0 NSLog(@"socket: kernel bound address of %i in domain %@", self->fd, [self domain]); #endif if (getsockname(self->fd, (void *)&data, &len) != 0) { // function is MT-safe // could not get local socket name, THROW [[[NGSocketException alloc] initWithReason:@"could not get local socket name" socket:self] raise]; return NO; } if (self->localAddress) { // release old address [self->localAddress release]; self->localAddress = nil; } self->localAddress = [[self domain] addressWithRepresentation:(void *)data size:len]; self->localAddress = [self->localAddress retain]; self->flags.isBound = YES; return YES; } /* accessors */ - (id)localAddress { return self->localAddress; } - (BOOL)isBound { return self->flags.isBound; } - (int)socketType { [self subclassResponsibility:_cmd]; return -1; } - (id)domain { return self->domain; } #if defined(WIN32) && !defined(__CYGWIN32__) - (SOCKET)fileDescriptor { #else - (int)fileDescriptor { #endif return self->fd; } - (void)setFileDescriptor: (int) theFd closeWhenDone: (BOOL) closeFd { [self close]; self->fd = theFd; self->flags.closeOnFree = closeFd; } - (void)resetFileHandle { // called by the NSFileHandle on dealloc self->fileHandle = nil; } - (NSFileHandle *)fileHandle { /* the filehandle will reset itself from the stream when being deallocated */ if (self->fileHandle == nil) { self->fileHandle = [(_NGConcreteSocketFileHandle *)[_NGConcreteSocketFileHandle alloc] initWithSocket:self]; } return [self->fileHandle autorelease]; } /* options */ - (void)setOption:(int)_option level:(int)_level value:(void *)_value len:(int)_len { if (setsockopt(fd, _level, _option, _value, _len) != 0) { NSString *reason = nil; #if defined(WIN32) && !defined(__CYGWIN32__) int e = WSAGetLastError(); switch (e) { case WSAEBADF: reason = @"Could not set socket option, invalid file descriptor"; break; case WSAEINVAL: reason = @"Could not set socket option, option is invalid or socket has been" @"shut down"; break; case WSAENOPROTOOPT: reason = @"Could not set socket option, option is not supported by protocol"; break; case WSAENOTSOCK: reason = @"Could not set socket option, descriptor isn't a socket"; break; default: reason = [NSString stringWithFormat:@"Could not set socket option: %s", strerror(e)]; break; } #else int e = errno; switch (e) { case EBADF: reason = @"Could not set socket option, invalid file descriptor"; break; case EINVAL: reason = @"Could not set socket option, option is invalid or socket has been" @"shut down"; break; case ENOPROTOOPT: reason = @"Could not set socket option, option is not supported by protocol"; break; case ENOTSOCK: reason = @"Could not set socket option, descriptor isn't a socket"; break; default: reason = [NSString stringWithFormat:@"Could not set socket option: %s", strerror(e)]; break; } #endif [[[NGCouldNotSetSocketOptionException alloc] initWithReason:reason option:_option level:_level] raise]; } } - (void)setOption:(int)_option value:(void *)_value len:(int)_len { [self setOption:_option level:SOL_SOCKET value:_value len:_len]; } - (void)getOption:(int)_option level:(int)_level value:(void *)_value len:(int *)_len { int rc; socklen_t tlen; rc = getsockopt(fd, _level, _option, _value, &tlen); if (_len) *_len = tlen; if (rc != 0) { NSString *reason = nil; #if defined(WIN32) && !defined(__CYGWIN32__) int e = WSAGetLastError(); switch (e) { case WSAEBADF: reason = @"Could not get socket option, invalid file descriptor"; break; case WSAEINVAL: reason = @"Could not get socket option, option is invalid at the specified level"; break; case WSAENOPROTOOPT: reason = @"Could not get socket option, option is not supported by protocol"; break; case WSAENOTSOCK: reason = @"Could not get socket option, descriptor isn't a socket"; break; case WSAEOPNOTSUPP: reason = @"Could not get socket option, operation is not supported by protocol"; break; default: reason = [NSString stringWithFormat:@"Could not get socket option: %s", strerror(e)]; break; } #else int e = errno; switch (e) { case EBADF: reason = @"Could not get socket option, invalid file descriptor"; break; case EINVAL: reason = @"Could not get socket option, option is invalid at the specified level"; break; case ENOPROTOOPT: reason = @"Could not get socket option, option is not supported by protocol"; break; case ENOTSOCK: reason = @"Could not get socket option, descriptor isn't a socket"; break; case EOPNOTSUPP: reason = @"Could not get socket option, operation is not supported by protocol"; break; default: reason = [NSString stringWithFormat:@"Could not get socket option: %s", strerror(e)]; break; } #endif [[[NGCouldNotGetSocketOptionException alloc] initWithReason:reason option:_option level:_level] raise]; } } - (void)getOption:(int)_option value:(void *)_value len:(int *)_len { [self getOption:_option level:SOL_SOCKET value:_value len:_len]; } static int i_yes = 1; static int i_no = 0; static inline void setBoolOption(id self, int _option, BOOL _flag) { [self setOption:_option level:SOL_SOCKET value:(_flag ? &i_yes : &i_no) len:4]; } static inline BOOL getBoolOption(id self, int _option) { int value, len; [self getOption:_option level:SOL_SOCKET value:&value len:&len]; return (value ? YES : NO); } - (void)setDebug:(BOOL)_flag { setBoolOption(self, SO_DEBUG, _flag); } - (BOOL)doesDebug { return getBoolOption(self, SO_DEBUG); } - (void)setReuseAddress:(BOOL)_flag { setBoolOption(self, SO_REUSEADDR, _flag); } - (BOOL)doesReuseAddress { return getBoolOption(self, SO_REUSEADDR); } - (void)setKeepAlive:(BOOL)_flag { setBoolOption(self, SO_KEEPALIVE, _flag); } - (BOOL)doesKeepAlive { return getBoolOption(self, SO_KEEPALIVE); } - (void)setDontRoute:(BOOL)_flag { setBoolOption(self, SO_DONTROUTE, _flag); } - (BOOL)doesNotRoute { return getBoolOption(self, SO_DONTROUTE); } - (void)setSendBufferSize:(int)_size { [self setOption:SO_SNDBUF level:SOL_SOCKET value:&_size len:sizeof(_size)]; } - (int)sendBufferSize { int size, len; [self getOption:SO_SNDBUF level:SOL_SOCKET value:&size len:&len]; return size; } - (void)setReceiveBufferSize:(int)_size { [self setOption:SO_RCVBUF level:SOL_SOCKET value:&_size len:sizeof(_size)]; } - (int)receiveBufferSize { int size, len; [self getOption:SO_RCVBUF level:SOL_SOCKET value:&size len:&len]; return size; } - (int)getSocketError { int error, len; [self getOption:SO_ERROR level:SOL_SOCKET value:&error len:&len]; return error; } /* description */ - (NSString *)description { return [NSString stringWithFormat: @"<%@[0x%p]: fd=%i type=%i bound=%@ domain=%@>", NSStringFromClass([self class]), self, [self fileDescriptor], [self socketType], [self localAddress] ? [self localAddress] : (id)@"no", [self domain] ]; } @end /* NGSocket */ @implementation _NGConcreteSocketFileHandle - (id)initWithSocket:(id)_socket { return [super initWithStream:(id)_socket]; } // accessors - (int)fileDescriptor { return [(NGSocket *)stream fileDescriptor]; } @end /* _NGConcreteSocketFileHandle */ #if defined(WIN32) && !defined(__CYGWIN32__) // Windows Descriptor functions // ******************** Poll ********************* int NGPollDescriptor(SOCKET _fd, short _events, int _timeout) { struct timeval timeout; fd_set rSet; fd_set wSet; fd_set eSet; int result; FD_ZERO(&rSet); FD_ZERO(&wSet); FD_ZERO(&eSet); if (_events & POLLIN) FD_SET(_fd, &rSet); if (_events & POLLOUT) FD_SET(_fd, &wSet); if (_events & POLLERR) FD_SET(_fd, &eSet); timeout.tv_sec = _timeout / 1000; timeout.tv_usec = _timeout * 1000 - timeout.tv_sec * 1000000; do { result = select(FD_SETSIZE, &rSet, &wSet, &eSet, &timeout); if (result == -1) { // error int e = WSAGetLastError(); if (e != WSAEINTR) // only retry of interrupted or repeatable break; } } while (result == -1); return (result < 0) ? -1 : result; } // ******************** Flags ******************** #if 0 int NGGetDescriptorFlags(int _fd) { int val; val = fcntl(_fd, F_GETFL, 0); if (val < 0) [NGIOException raiseWithReason:@"could not get descriptor flags"]; return val; } void NGSetDescriptorFlags(int _fd, int _flags) { if (fcntl(_fd, F_SETFL, _flags) == -1) [NGIOException raiseWithReason:@"could not set descriptor flags"]; } void NGAddDescriptorFlag (int _fd, int _flag) { int val = NGGetDescriptorFlags(_fd); NGSetDescriptorFlags(_fd, val | _flag); } #endif // ******************** NonBlocking IO ************ int NGDescriptorRecv(SOCKET _fd, char *_buf, int _len, int _flags, int _timeout) { int errorCode; int result; result = recv(_fd, _buf, _len, _flags); if (result == 0) return 0; // EOF errorCode = errno; if ((result == -1) && (errorCode == WSAEWOULDBLOCK)) { // retry #if 0 struct pollfd pfd; pfd.fd = _fd; pfd.events = POLLRDNORM; pfd.revents = 0; do { if ((result = poll(&pfd, 1, _timeout)) < 0) { errorCode = errno; // retry if interrupted if ((errorCode != EINTR) && (errorCode != EAGAIN)) break; } } while (result < 0); #endif result = 1; if (result == 1) { // data waiting, try to read result = recv(_fd, _buf, _len, _flags); if (result == 0) return 0; // EOF else if (result == -1) { errorCode = errno; if (errorCode == WSAEWOULDBLOCK) NSLog(@"WARNING: would block although descriptor was polled .."); } } else if (result == 0) { result = -2; } else result = -1; } return result; } int NGDescriptorSend(SOCKET _fd, const char *_buf, int _len, int _flags, int _timeout) { int errorCode; int result; result = send(_fd, _buf, _len, _flags); if (result == 0) return 0; // EOF errorCode = errno; if ((result == -1) && (errorCode == WSAEWOULDBLOCK)) { // retry #if 0 struct pollfd pfd; pfd.fd = _fd; pfd.events = POLLWRNORM; pfd.revents = 0; do { if ((result = poll(&pfd, 1, _timeout)) < 0) { errorCode = errno; if (errorCode != WSAEINTR) // retry only if interrupted break; } } while (result < 0); #endif result = 1; // block .. if (result == 1) { // data waiting, try to read result = send(_fd, _buf, _len, _flags); if (result == 0) return 0; // EOF } else if (result == 0) { #if 0 NSLog(@"nonblock: send on %i timed out after %i milliseconds ..", _fd, _timeout); #endif result = -2; } else result = -1; } return result; } #endif /* WIN32 */ SOPE/sope-core/NGStreams/config.guess0000755000000000000000000013743115004363604016413 0ustar rootroot#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2020 Free Software Foundation, Inc. timestamp='2020-10-22' # This file 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 3 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, see . # # 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 Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. tmp= # shellcheck disable=SC2172 trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 set_cc_for_build() { # prevent multiple calls if $tmp is already set test "$tmp" && return 0 : "${TMPDIR=/tmp}" # shellcheck disable=SC2039 { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } dummy=$tmp/dummy case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in ,,) echo "int x;" > "$dummy.c" for driver in cc gcc c89 c99 ; do if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD="$driver" break fi done if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac } # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "$UNAME_SYSTEM" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu set_cc_for_build cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else #include #ifdef __DEFINED_va_list LIBC=musl #else LIBC=gnu #endif #endif EOF eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" ;; esac # Note: order is significant - the case branches are not exclusive. case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ "/sbin/$sysctl" 2>/dev/null || \ "/usr/sbin/$sysctl" 2>/dev/null || \ echo unknown)` case "$UNAME_MACHINE_ARCH" in aarch64eb) machine=aarch64_be-unknown ;; armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` machine="${arch}${endian}"-unknown ;; *) machine="$UNAME_MACHINE_ARCH"-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case "$UNAME_MACHINE_ARCH" in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case "$UNAME_MACHINE_ARCH" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "$UNAME_VERSION" in Debian*) release='-gnu' ;; *) release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "$machine-${os}${release}${abi-}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" exit ;; *:MidnightBSD:*:*) echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" exit ;; *:ekkoBSD:*:*) echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" exit ;; *:SolidBSD:*:*) echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" exit ;; *:OS108:*:*) echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE" exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:MirBSD:*:*) echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:Sortix:*:*) echo "$UNAME_MACHINE"-unknown-sortix exit ;; *:Twizzler:*:*) echo "$UNAME_MACHINE"-unknown-twizzler exit ;; *:Redox:*:*) echo "$UNAME_MACHINE"-unknown-redox exit ;; mips:OSF1:*.*) echo mips-dec-osf1 exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo "$UNAME_MACHINE"-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo "$UNAME_MACHINE"-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix"$UNAME_RELEASE" exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos"$UNAME_RELEASE" exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos"$UNAME_RELEASE" exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint"$UNAME_RELEASE" exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint"$UNAME_RELEASE" exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint"$UNAME_RELEASE" exit ;; m68k:machten:*:*) echo m68k-apple-machten"$UNAME_RELEASE" exit ;; powerpc:machten:*:*) echo powerpc-apple-machten"$UNAME_RELEASE" exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix"$UNAME_RELEASE" exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix"$UNAME_RELEASE" exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos"$UNAME_RELEASE" exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 then if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ test "$TARGET_BINARY_INTERFACE"x = x then echo m88k-dg-dgux"$UNAME_RELEASE" else echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else echo i586-dg-dgux"$UNAME_RELEASE" fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if test -x /usr/bin/oslevel ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if test -x /usr/bin/lslpp ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi echo "$IBM_ARCH"-ibm-aix"$IBM_REV" exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` case "$UNAME_MACHINE" in 9000/31?) HP_ARCH=m68000 ;; 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if test -x /usr/bin/getconf; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "$sc_cpu_version" in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "$sc_kernel_bits" in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi if test "$HP_ARCH" = ""; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if test "$HP_ARCH" = hppa2.0w then set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi echo "$HP_ARCH"-hp-hpux"$HPUX_REV" exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if test -x /usr/sbin/sysversion ; then echo "$UNAME_MACHINE"-unknown-osf1mk else echo "$UNAME_MACHINE"-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi"$UNAME_RELEASE" exit ;; *:BSD/OS:*:*) echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" exit ;; arm:FreeBSD:*:*) UNAME_PROCESSOR=`uname -p` set_cc_for_build if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi else echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf fi exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case "$UNAME_PROCESSOR" in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; i*:CYGWIN*:*) echo "$UNAME_MACHINE"-pc-cygwin exit ;; *:MINGW64*:*) echo "$UNAME_MACHINE"-pc-mingw64 exit ;; *:MINGW*:*) echo "$UNAME_MACHINE"-pc-mingw32 exit ;; *:MSYS*:*) echo "$UNAME_MACHINE"-pc-msys exit ;; i*:PW*:*) echo "$UNAME_MACHINE"-pc-pw32 exit ;; *:Interix*:*) case "$UNAME_MACHINE" in x86) echo i586-pc-interix"$UNAME_RELEASE" exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix"$UNAME_RELEASE" exit ;; IA64) echo ia64-unknown-interix"$UNAME_RELEASE" exit ;; esac ;; i*:UWIN*:*) echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-pc-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; *:GNU:*:*) # the GNU system echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" exit ;; *:Minix:*:*) echo "$UNAME_MACHINE"-unknown-minix exit ;; aarch64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi else echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf fi fi exit ;; avr32*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; cris:Linux:*:*) echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; crisv32:Linux:*:*) echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; e2k:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; frv:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; hexagon:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:Linux:*:*) echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; ia64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; k1om:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m32r*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m68*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) set_cc_for_build IS_GLIBC=0 test x"${LIBC}" = xgnu && IS_GLIBC=1 sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef mips #undef mipsel #undef mips64 #undef mips64el #if ${IS_GLIBC} && defined(_ABI64) LIBCABI=gnuabi64 #else #if ${IS_GLIBC} && defined(_ABIN32) LIBCABI=gnuabin32 #else LIBCABI=${LIBC} #endif #endif #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa64r6 #else #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa32r6 #else #if defined(__mips64) CPU=mips64 #else CPU=mips #endif #endif #endif #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) MIPS_ENDIAN= #else MIPS_ENDIAN= #endif #endif EOF eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`" test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } ;; mips64el:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-"$LIBC" exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; padre:Linux:*:*) echo sparc-unknown-linux-"$LIBC" exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-"$LIBC" exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; *) echo hppa-unknown-linux-"$LIBC" ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-"$LIBC" exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-"$LIBC" exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-"$LIBC" exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-"$LIBC" exit ;; riscv32:Linux:*:* | riscv64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" exit ;; sh64*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sh*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; tile*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; vax:Linux:*:*) echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) set_cc_for_build LIBCABI=$LIBC if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_X32 >/dev/null then LIBCABI="$LIBC"x32 fi fi echo "$UNAME_MACHINE"-pc-linux-"$LIBCABI" exit ;; xtensa*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo "$UNAME_MACHINE"-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo "$UNAME_MACHINE"-unknown-stop exit ;; i*86:atheos:*:*) echo "$UNAME_MACHINE"-unknown-atheos exit ;; i*86:syllable:*:*) echo "$UNAME_MACHINE"-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos"$UNAME_RELEASE" exit ;; i*86:*DOS:*:*) echo "$UNAME_MACHINE"-pc-msdosdjgpp exit ;; i*86:*:4.*:*) UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" else echo "$UNAME_MACHINE"-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos"$UNAME_RELEASE" exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos"$UNAME_RELEASE" exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos"$UNAME_RELEASE" exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos"$UNAME_RELEASE" exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv"$UNAME_RELEASE" exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo "$UNAME_MACHINE"-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo "$UNAME_MACHINE"-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux"$UNAME_RELEASE" exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if test -d /usr/nec; then echo mips-nec-sysv"$UNAME_RELEASE" else echo mips-unknown-sysv"$UNAME_RELEASE" fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux"$UNAME_RELEASE" exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux"$UNAME_RELEASE" exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux"$UNAME_RELEASE" exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux"$UNAME_RELEASE" exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux"$UNAME_RELEASE" exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux"$UNAME_RELEASE" exit ;; SX-ACE:SUPER-UX:*:*) echo sxace-nec-superux"$UNAME_RELEASE" exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Rhapsody:*:*) echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; arm64:Darwin:*:*) echo aarch64-apple-darwin"$UNAME_RELEASE" exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac if command -v xcode-select > /dev/null 2> /dev/null && \ ! xcode-select --print-path > /dev/null 2> /dev/null ; then # Avoid executing cc if there is no toolchain installed as # cc will be a stub that puts up a graphical alert # prompting the user to install developer tools. CC_FOR_BUILD=no_compiler_found else set_cc_for_build fi if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_PPC >/dev/null then UNAME_PROCESSOR=powerpc fi elif test "$UNAME_PROCESSOR" = i386 ; then # uname -m returns i386 or x86_64 UNAME_PROCESSOR=$UNAME_MACHINE fi echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-*:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk"$UNAME_RELEASE" exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk"$UNAME_RELEASE" exit ;; NSR-*:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk"$UNAME_RELEASE" exit ;; NSV-*:NONSTOP_KERNEL:*:*) echo nsv-tandem-nsk"$UNAME_RELEASE" exit ;; NSX-*:NONSTOP_KERNEL:*:*) echo nsx-tandem-nsk"$UNAME_RELEASE" exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. # shellcheck disable=SC2154 if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo "$UNAME_MACHINE"-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux"$UNAME_RELEASE" exit ;; *:DragonFly:*:*) echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "$UNAME_MACHINE" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" exit ;; i*86:rdos:*:*) echo "$UNAME_MACHINE"-pc-rdos exit ;; i*86:AROS:*:*) echo "$UNAME_MACHINE"-pc-aros exit ;; x86_64:VMkernel:*:*) echo "$UNAME_MACHINE"-unknown-esx exit ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; *:Unleashed:*:*) echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE" exit ;; esac # No uname command or uname output not recognized. set_cc_for_build cat > "$dummy.c" < #include #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #include #if defined(_SIZE_T_) || defined(SIGLOST) #include #endif #endif #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) #if !defined (ultrix) #include #if defined (BSD) #if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); #else #if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); #else printf ("vax-dec-bsd\n"); exit (0); #endif #endif #else printf ("vax-dec-bsd\n"); exit (0); #endif #else #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname un; uname (&un); printf ("vax-dec-ultrix%s\n", un.release); exit (0); #else printf ("vax-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname *un; uname (&un); printf ("mips-dec-ultrix%s\n", un.release); exit (0); #else printf ("mips-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } echo "$0: unable to guess system type" >&2 case "$UNAME_MACHINE:$UNAME_SYSTEM" in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&2 <&2 </dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = "$UNAME_MACHINE" UNAME_RELEASE = "$UNAME_RELEASE" UNAME_SYSTEM = "$UNAME_SYSTEM" UNAME_VERSION = "$UNAME_VERSION" EOF fi exit 1 # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: SOPE/sope-core/NGStreams/NGActiveSSLSocket.m0000644000000000000000000004723715004363604017450 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG Copyright (C) 2011 Jeroen Dekkers Copyright (C) 2020 Nicolas Höft This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* match_function() and _validateHostname are based on boost asio implementations Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include "common.h" #if HAVE_GNUTLS # include # include #define LOOP_CHECK(rval, cmd) \ do { \ rval = cmd; \ } while(rval == GNUTLS_E_AGAIN || rval == GNUTLS_E_INTERRUPTED); #elif HAVE_OPENSSL # define id openssl_id # include # include # include # undef id #endif #include @interface NGActiveSocket(UsedPrivates) - (id)initWithDomain:(id)_domain onHostName: (NSString *)_hostName; - (BOOL)primaryConnectToAddress:(id)_address; #if HAVE_OPENSSL - (BOOL) _validateHostname: (X509 *) server_cert; #endif /* HAVE_OPENSSL */ @end @implementation NGActiveSSLSocket - (void) validatePeerCertificate:(BOOL)_validate { validatePeer = _validate; } - (BOOL)primaryConnectToAddress:(id)_address { if (![super primaryConnectToAddress:_address]) /* could not connect to Unix socket ... */ return NO; return [self startTLS]; } + (id) socketConnectedToAddress: (id) _address withVerifyMode: (int) mode { NGActiveSSLSocket *sock = [[self alloc] initWithDomain:[_address domain] onHostName: [_address hostName]]; if (mode == TLSVerifyNone || ([_address isLocalhost] && mode == TLSVerifyAllowInsecureLocalhost)) { [sock validatePeerCertificate: NO]; } else { [sock validatePeerCertificate: YES]; } if (![sock connectToAddress:_address]) { NSException *e; e = [[sock lastException] retain]; [self release]; e = [e autorelease]; [e raise]; return nil; } sock = [sock autorelease]; return sock; } - (id)initWithConnectedActiveSocket: (NGActiveSocket *) _socket withVerifyMode: (int) mode { id remoteAddr; int oldopts; int sock_fd; if (![_socket isConnected]) { NSLog(@"ERROR(%s): Socket needs to be connected to remote", __PRETTY_FUNCTION__); [self release]; return nil; } remoteAddr = [_socket remoteAddress]; [self initWithDomain: [remoteAddr domain] onHostName: [remoteAddr hostName]]; if (mode == TLSVerifyNone || ([remoteAddr isLocalhost] && mode == TLSVerifyAllowInsecureLocalhost)) { [self validatePeerCertificate: NO]; } else { [self validatePeerCertificate: YES]; } sock_fd = [_socket fileDescriptor]; // the fd is still owned by the other socket [self setFileDescriptor: sock_fd closeWhenDone: NO]; // We remove the NON-BLOCKING I/O flag on the file descriptor, otherwise // SOPE will break on SSL-sockets. oldopts = fcntl(sock_fd, F_GETFL, 0); fcntl(sock_fd, F_SETFL, oldopts & !O_NONBLOCK); return self; } #if HAVE_GNUTLS #if GNUTLS_VERSION_NUMBER < 0x030406 /* This function will verify the peer's certificate, and check * if the hostname matches, as well as the activation, expiration dates. */ static int _verify_certificate_callback (gnutls_session_t session) { unsigned int status; const gnutls_datum_t *cert_list; unsigned int cert_list_size; int ret; gnutls_x509_crt_t cert; const char *hostname; /* read hostname */ hostname = gnutls_session_get_ptr (session); /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ ret = gnutls_certificate_verify_peers2 (session, &status); if (ret < 0) { NSLog(@"ERROR: verify_peer2 failed"); return GNUTLS_E_CERTIFICATE_ERROR; } if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) NSLog(@"ERROR: The certificate hasn't got a known issuer."); if (status & GNUTLS_CERT_REVOKED) NSLog(@"ERROR: The certificate has been revoked."); if (status & GNUTLS_CERT_EXPIRED) NSLog(@"ERROR: The certificate has expired"); if (status & GNUTLS_CERT_NOT_ACTIVATED) NSLog(@"ERROR: The certificate is not yet activated"); if (status & GNUTLS_CERT_INVALID) { NSLog(@"ERROR: The certificate is not trusted."); return GNUTLS_E_CERTIFICATE_ERROR; } /* Up to here the process is the same for X.509 certificates and * OpenPGP keys. From now on X.509 certificates are assumed. This can * be easily extended to work with openpgp keys as well. */ if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) return GNUTLS_E_CERTIFICATE_ERROR; if (gnutls_x509_crt_init (&cert) < 0) { NSLog(@"WARNING: could not initialize gnutls certificate"); return GNUTLS_E_CERTIFICATE_ERROR; } cert_list = gnutls_certificate_get_peers (session, &cert_list_size); if (cert_list == NULL) { NSLog(@"WARNING: GnuTLS certificate not found"); return GNUTLS_E_CERTIFICATE_ERROR; } if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) { NSLog(@"WARNING: Unable to parse certificate"); return GNUTLS_E_CERTIFICATE_ERROR; } if (!gnutls_x509_crt_check_hostname (cert, hostname)) { NSLog(@"ERROR: Certificate does not match hostname '%s'", hostname); return GNUTLS_E_CERTIFICATE_ERROR; } gnutls_x509_crt_deinit (cert); /* notify gnutls to continue handshake normally */ return 0; } #endif /* GNUTLS_VERSION_NUMBER < 0x030406 */ - (id)initWithDomain:(id)_domain onHostName: (NSString *)_hostName { hostName = [_hostName copy]; if ((self = [super initWithDomain:_domain])) { static BOOL didGlobalInit = NO; int ret; if (!didGlobalInit) { /* Global system initialization*/ if (gnutls_global_init()) { [self release]; return nil; } didGlobalInit = YES; } ret = gnutls_certificate_allocate_credentials((gnutls_certificate_credentials_t *) &self->cred); if (ret) { NSLog(@"ERROR(%s): couldn't create GnuTLS credentials (%s)", __PRETTY_FUNCTION__, gnutls_strerror(ret)); [self release]; return nil; } #ifdef CA_BUNDLE ret = gnutls_certificate_set_x509_trust_file(self->cred, CA_BUNDLE, GNUTLS_X509_FMT_PEM); #elif GNUTLS_VERSION_NUMBER >= 0x030020 ret = gnutls_certificate_set_x509_system_trust(self->cred); #else #error "Cant use default system trust, CA_BUNDLE needs to be passed" #endif if (ret < 0) { NSLog(@"ERROR(%s): could not set GnuTLS system trust (%s)", __PRETTY_FUNCTION__, gnutls_strerror(ret)); [self release]; return nil; } self->session = NULL; } return self; } - (void)dealloc { if (self->session) { gnutls_deinit((gnutls_session_t) self->session); self->session = NULL; } if (self->cred) { gnutls_certificate_free_credentials((gnutls_certificate_credentials_t) self->cred); self->cred = NULL; } [hostName release]; [super dealloc]; } /* basic IO, reading and writing bytes */ - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { ssize_t ret; if (self->session == NULL) // should throw error return NGStreamError; LOOP_CHECK(ret, gnutls_record_recv((gnutls_session_t) self->session, _buf, _len)); if (ret <= 0) return NGStreamError; else return ret; } - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len { ssize_t ret; if (self->session == NULL) // should throw error return NGStreamError; LOOP_CHECK(ret, gnutls_record_send((gnutls_session_t) self->session, _buf, _len)); if (ret <= 0) return NGStreamError; else return ret; } /* connection and shutdown */ - (BOOL)markNonblockingAfterConnect { return NO; } - (BOOL) startTLS { int ret; gnutls_session_t sess; [self disableNagle: YES]; ret = gnutls_init((gnutls_session_t *) &self->session, GNUTLS_CLIENT); if (ret) { // should set exception ! NSLog(@"ERROR(%s): couldn't create GnuTLS session (%s)", __PRETTY_FUNCTION__, gnutls_strerror(ret)); return NO; } sess = (gnutls_session_t) self->session; gnutls_set_default_priority(sess); ret = gnutls_credentials_set(sess, GNUTLS_CRD_CERTIFICATE, (gnutls_certificate_credentials_t) self->cred); if (ret) { // should set exception ! NSLog(@"ERROR(%s): couldn't set GnuTLS credentials (%s)", __PRETTY_FUNCTION__, gnutls_strerror(ret)); return NO; } // set SNI ret = gnutls_server_name_set(sess, GNUTLS_NAME_DNS, [hostName UTF8String], [hostName length]); if (ret) { // should set exception ! NSLog(@"ERROR(%s): couldn't set GnuTLS SNI (%s)", __PRETTY_FUNCTION__, gnutls_strerror(ret)); return NO; } if (validatePeer) { #if GNUTLS_VERSION_NUMBER >= 0x030406 gnutls_session_set_verify_cert(sess, [hostName UTF8String], 0); #else gnutls_session_set_ptr(session, (void *) [hostName UTF8String]); gnutls_certificate_set_verify_function(self->cred, _verify_certificate_callback); #endif /* GNUTLS_VERSION_NUMBER >= 0x030406*/ } #if GNUTLS_VERSION_NUMBER < 0x030109 gnutls_transport_set_ptr(sess, (gnutls_transport_ptr_t)(long)self->fd); #else gnutls_transport_set_int(sess, self->fd); #endif /* GNUTLS_VERSION_NUMBER < 0x030109 */ #if GNUTLS_VERSION_NUMBER >= 0x030100 gnutls_handshake_set_timeout(sess, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); #endif do { ret = gnutls_handshake(sess); } while (ret < 0 && gnutls_error_is_fatal(ret) == 0); if (ret < 0) { NSLog(@"ERROR(%s):GnutTLS handshake failed on socket (%s)", __PRETTY_FUNCTION__, gnutls_strerror(ret)); if (ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { NSLog(@"Alert: %s", gnutls_alert_get_name(gnutls_alert_get(sess))); } [self shutdown]; return NO; } return YES; } - (BOOL)shutdown { if (self->session) { int ret; if (NGInvalidSocketDescriptor != self->fd) { LOOP_CHECK(ret, gnutls_bye((gnutls_session_t)self->session, GNUTLS_SHUT_RDWR)); } else { NSLog(@"WARNING(%s): Cannot gnutls_bye() NGInvalidSocketDescriptor", __PRETTY_FUNCTION__); } gnutls_deinit((gnutls_session_t) self->session); self->session = NULL; } if (self->cred) { gnutls_certificate_free_credentials((gnutls_certificate_credentials_t) self->cred); self->cred = NULL; } return [super shutdown]; } #elif HAVE_OPENSSL #if OPENSSL_VERSION_NUMBER < 0x10020000L static BOOL match_pattern(const char* pattern, size_t pattern_length, const char* host) { const char* p = pattern; const char* p_end = p + pattern_length; const char* h = host; while (p != p_end && *h) { if (*p == '*') { ++p; while (*h && *h != '.') { if (match_pattern(p, p_end - p, h++)) { return YES; } } } else if (tolower(*p) == tolower(*h)) { ++p; ++h; } else { return NO; } } return p == p_end && !*h; } - (BOOL) _validateHostname: (X509 *) server_cert { // Go through the alternate names in the certificate looking for matching DNS // entries. int i; GENERAL_NAMES* gens = (GENERAL_NAMES*) X509_get_ext_d2i(server_cert, NID_subject_alt_name, 0, 0); for (i = 0; i < sk_GENERAL_NAME_num(gens); ++i) { GENERAL_NAME* gen = sk_GENERAL_NAME_value(gens, i); if (gen->type == GEN_DNS) { ASN1_IA5STRING* dns_name = gen->d.dNSName; if (dns_name->type == V_ASN1_IA5STRING && dns_name->data && dns_name->length) { const char* pattern = (const char*)dns_name->data; size_t pattern_length = dns_name->length; if (match_pattern(pattern, pattern_length, [hostName UTF8String])) { GENERAL_NAMES_free(gens); return YES; } } } } GENERAL_NAMES_free(gens); // No match in the alternate names, so try the common names. We should only // use the "most specific" common name, which is the last one in the list. X509_NAME* name = X509_get_subject_name(server_cert); ASN1_STRING* common_name = 0; while ((i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) >= 0) { X509_NAME_ENTRY* name_entry = X509_NAME_get_entry(name, i); common_name = X509_NAME_ENTRY_get_data(name_entry); } if (common_name && common_name->data && common_name->length) { const char* pattern = (const char*) common_name->data; size_t pattern_length = common_name->length; if (match_pattern(pattern, pattern_length, [hostName UTF8String])) { return YES; } } return NO; } /* See http://archives.seul.org/libevent/users/Jan-2013/msg00039.html */ static int cert_verify_callback(X509_STORE_CTX *x509_ctx, void *arg) { NGActiveSSLSocket *sslsock = (NGActiveSSLSocket *)arg; BOOL validation_result = NO; /* This is the function that OpenSSL would call if we hadn't called * SSL_CTX_set_cert_verify_callback(). Therefore, we are "wrapping" * the default functionality, rather than replacing it. */ int ok_so_far = 0; X509 *server_cert = NULL; ok_so_far = X509_verify_cert(x509_ctx) == 1; server_cert = X509_STORE_CTX_get_current_cert(x509_ctx); if (ok_so_far) { validation_result = [sslsock _validateHostname: server_cert]; } if (validation_result == YES) { return 1; } else { NSLog(@"SSL(%s): Certificate validation failed", __PRETTY_FUNCTION__); return 0; } } #endif /* #OPENSSL_VERSION_NUMBER < 0x10020000L */ - (id)initWithDomain:(id)_domain onHostName: (NSString *)_hostName { hostName = [_hostName copy]; if ((self = [super initWithDomain:_domain])) { #if OPENSSL_VERSION_NUMBER < 0x10100000L static BOOL didGlobalInit = NO; if (!didGlobalInit) { /* Global system initialization*/ SSL_library_init(); SSL_load_error_strings(); didGlobalInit = YES; } #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ /* Create our context*/ if ((self->ctx = SSL_CTX_new(SSLv23_method())) == NULL) { NSLog(@"ERROR(%s): couldn't create SSL context for v23 method !", __PRETTY_FUNCTION__); [self release]; return nil; } // use system default trust store #ifdef CA_BUNDLE SSL_CTX_load_verify_locations(self->ctx, CA_BUNDLE, NULL); #else SSL_CTX_set_default_verify_paths(self->ctx); #endif // CA_BUNDLE if ((self->ssl = SSL_new(self->ctx)) == NULL) { // should set exception ! NSLog(@"ERROR(%s): couldn't create SSL socket structure ...", __PRETTY_FUNCTION__); return nil; } //SSL_CTX_set_options(self->ctx, SSL_OP_IGNORE_UNEXPECTED_EOF); #if OPENSSL_VERSION_NUMBER < 0x10020000L SSL_CTX_set_cert_verify_callback(self->ctx, cert_verify_callback, (void *)self); #elif OPENSSL_VERSION_NUMBER < 0x10100000L X509_VERIFY_PARAM *param = NULL; param = SSL_get0_param(self->ssl); X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); if (!X509_VERIFY_PARAM_set1_host(param, [hostName UTF8String], 0)) { return nil; } #else SSL_set1_host(self->ssl, [hostName UTF8String]); #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ // send SNI SSL_set_tlsext_host_name(self->ssl, [hostName UTF8String]); } return self; } - (void)dealloc { if (self->ssl) { SSL_free(self->ssl); self->ssl = NULL; } if (self->ctx) { SSL_CTX_free(self->ctx); self->ctx = NULL; } [hostName release]; [super dealloc]; } /* basic IO, reading and writing bytes */ - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { int ret; if (self->ssl == NULL) // should throw error return NGStreamError; ret = SSL_read(self->ssl, _buf, _len); if (ret <= 0) return NGStreamError; return ret; } - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len { return SSL_write(self->ssl, _buf, _len); } /* connection and shutdown */ - (BOOL)markNonblockingAfterConnect { return NO; } - (BOOL) startTLS { int ret; int verifyMode = validatePeer == YES ? SSL_VERIFY_PEER : SSL_VERIFY_NONE; [self disableNagle: YES]; SSL_set_verify(self->ssl, verifyMode, NULL); if (self->ssl == NULL) { NSLog(@"ERROR(%s): SSL structure is not set up!", __PRETTY_FUNCTION__); return NO; } if (SSL_set_fd(self->ssl, self->fd) <= 0) { // should set exception ! NSLog(@"ERROR(%s): couldn't set FD ...", __PRETTY_FUNCTION__); return NO; } ret = SSL_connect(self->ssl); if (ret <= 0) { NSLog(@"ERROR(%s): couldn't setup SSL connection on host %@ (%s)", __PRETTY_FUNCTION__, hostName, ERR_reason_error_string(ERR_get_error())); [self shutdown]; return NO; } return YES; } - (BOOL)shutdown { if (self->ssl) { if (NGInvalidSocketDescriptor != self->fd) { int ret = SSL_shutdown(self->ssl); int err = SSL_get_error(self->ssl, ret); if (ret == 0 && NGInvalidSocketDescriptor != self->fd) { //From SSL_shutdown description here -> https://github.com/openssl/openssl/blob/master/doc/man3/SSL_shutdown.pod //SL_shutdown() should not be called if a previous fatal error has occurred on a connection; //i.e., if SSL_get_error(3) has returned SSL_ERROR_SYSCALL or SSL_ERROR_SSL. if(err != SSL_ERROR_SYSCALL && err != SSL_ERROR_SSL) { // call shutdown a second time SSL_shutdown(self->ssl); } } } else { NSLog(@"WARNING(%s): Cannot SSL_shutdown() NGInvalidSocketDescriptor", __PRETTY_FUNCTION__); } } return [super shutdown]; } #else /* no OpenSSL available */ + (void)initialize { NSLog(@"WARNING: The NGActiveSSLSocket class was accessed, " @"but OpenSSL support is turned off."); } - (id)initWithDomain:(id)_domain onHostName: (NSString *)_hostName withVerifyMode: (int) mode { [self release]; return nil; } #endif @end /* NGActiveSSLSocket */ SOPE/sope-core/NGStreams/NGLocalSocketDomain.m0000644000000000000000000000632115004363604020022 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if !defined(WIN32) #include "NGLocalSocketDomain.h" #include "NGLocalSocketAddress.h" #include "NGSocket.h" #if defined(__APPLE__) || defined(__FreeBSD__) # include # include #else # include #endif #include "common.h" @implementation NGLocalSocketDomain static NGLocalSocketDomain *domain = nil; + (void)initialize { BOOL isInitialized = NO; if (!isInitialized) { isInitialized = YES; [NGSocket initialize]; domain = [[NGLocalSocketDomain alloc] init]; } } + (id)domain { return domain; } // NGSocketDomain - (id)addressWithRepresentation:(void *)_data size:(unsigned int)_size { NGLocalSocketAddress *address = nil; address = [[NGLocalSocketAddress alloc] initWithDomain:self internalRepresentation:_data size:_size]; return AUTORELEASE(address); } - (BOOL)prepareAddress:(id)_address forBindWithSocket:(id)_socket { if ([_socket conformsToProtocol:@protocol(NGPassiveSocket)]) { NSString *path = [(NGLocalSocketAddress *)_address path]; // ignore errors .. [[NSFileManager defaultManager] removeFileAtPath:path handler:nil]; } return YES; } - (BOOL)cleanupAddress:(id)_address afterCloseOfSocket:(id)_socket { if ([_socket conformsToProtocol:@protocol(NGPassiveSocket)]) { #if 0 NSString *path = [(NGLocalSocketAddress *)_address path]; // ignore errors .. [[NSFileManager defaultManager] removeFileAtPath:path handler:nil]; #endif } return YES; } - (int)socketDomain { return AF_LOCAL; } - (int)addressRepresentationSize { // maximum size return sizeof(struct sockaddr_un); } - (int)protocol { return 0; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { /* domains are immutable, just return self on copy .. */ return [self retain]; } /* NSCoding */ - (void)encodeWithCoder:(NSCoder *)_encoder { } - (id)initWithCoder:(NSCoder *)_decoder { [self release]; self = nil; return [domain retain]; /* replace with singleton */ } - (id)awakeAfterUsingCoder:(NSCoder *)_decoder { if (self != domain) { [self release]; self = nil; return [domain retain]; /* replace with singleton */ } else return self; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"", self]; } @end /* NGLocalSocketDomain */ #endif // !WIN32 SOPE/sope-core/NGStreams/NGSocketExceptions.m0000644000000000000000000001660615004363604017770 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #import #import #include "NGSocketExceptions.h" @implementation NGSocketException - (id)init { return [self initWithReason:@"a socket exception occured" socket:nil]; } - (id)initWithReason:(NSString *)_reason { return [self initWithReason:_reason socket:nil]; } - (id)initWithReason:(NSString *)_reason socket:(id)_socket { self = [super initWithName:NSStringFromClass([self class]) reason:_reason userInfo:nil]; if (self) { self->socket = _socket; } return self; } - (id)socket { return self->socket; } @end /* NGSocketException */ @implementation NGCouldNotResolveHostNameException - (id)init { return [self initWithHostName:@"" reason:nil]; } - (id)initWithHostName:(NSString *)_name reason:(NSString *)_reason { NSString *r; r = [[NSString alloc] initWithFormat:@"Could not resolve host %@: %@", _name, _reason ? _reason : (NSString *)@"error"]; if ((self = [super initWithReason:r socket:nil]) != nil) { self->hostName = [_name copy]; } [r release]; r = nil; return self; } - (void)dealloc { [self->hostName release]; [super dealloc]; } /* accessors */ - (NSString *)hostName { return self->hostName; } @end /* NGCouldNotResolveHostNameException */ @implementation NGDidNotFindServiceException - (id)init { return [self initWithServiceName:nil]; } - (id)initWithServiceName:(NSString *)_service { self = [super initWithReason: [NSString stringWithFormat:@"did not find service %@", _service] socket:nil]; if (self) { self->serviceName = [_service copy]; } return self; } - (void)dealloc { [self->serviceName release]; [super dealloc]; } - (NSString *)serviceName { return self->serviceName; } @end /* NGDidNotFindServiceException */ @implementation NGInvalidSocketDomainException - (id)initWithReason:(NSString *)_reason socket:(id)_socket domain:(id)_domain { if ((self = [super initWithReason:_reason socket:nil])) { self->domain = [_domain retain]; } return self; } - (void)dealloc { [self->domain release]; [super dealloc]; } - (id)domain { return self->domain; } @end /* NGInvalidSocketDomainException */ @implementation NGCouldNotCreateSocketException - (id)init { return [self initWithReason:@"Could not create socket" domain:nil]; } - (id)initWithReason:(NSString *)_reason domain:(id)_domain { if ((self = [super initWithReason:_reason socket:nil])) { self->domain = [_domain retain]; } return self; } - (void)dealloc { [self->domain release]; [super dealloc]; } - (id)domain { return self->domain; } @end /* NGCouldNotCreateSocketException */ // ******************** bind *********************** @implementation NGSocketBindException @end /* NGSocketBindException */ @implementation NGSocketAlreadyBoundException - (id)init { return [self initWithReason:@"Socket is already bound"]; } @end /* NGSocketAlreadyBoundException */ @implementation NGCouldNotBindSocketException - (id)init { return [self initWithReason:@"could not bind socket" socket:nil address:nil]; } - (id)initWithReason:(NSString *)_reason socket:(id)_socket address:(id)_address { if ((self = [super initWithReason:_reason socket:_socket])) { self->address = [_address retain]; } return self; } - (void)dealloc { [self->address release]; [super dealloc]; } - (id)address { return self->address; } @end /* NGCouldNotBindSocketException */ // ******************** connect ******************** @implementation NGSocketConnectException @end /* NGSocketConnectException */ @implementation NGSocketNotConnectedException - (id)init { return [self initWithReason:@"Socket is not connected"]; } @end /* NGSocketNotConnectedException */ @implementation NGSocketAlreadyConnectedException - (id)init { return [self initWithReason:@"Socket is already connected"]; } @end /* NGSocketAlreadyConnectedException */ @implementation NGCouldNotConnectException - (id)init { return [self initWithReason:@"could not connect socket" socket:nil address:nil]; } - (id)initWithReason:(NSString *)_reason socket:(id)_socket address:(id)_address { if ((self = [super initWithReason:_reason socket:_socket])) { self->address = [_address retain]; } return self; } - (void)dealloc { [self->address release]; [super dealloc]; } - (id)address { return self->address; } @end /* NGCouldNotConnectException */ // ******************** listen ******************** @implementation NGSocketIsAlreadyListeningException - (id)init { return [self initWithReason:@"Socket is already listening"]; } @end /* NGSocketIsAlreadyListeningException */ @implementation NGCouldNotListenException @end /* NGCouldNotListenException */ // ******************** accept ******************** @implementation NGCouldNotAcceptException @end /* NGCouldNotAcceptException */ // ******************** options ******************** @implementation NGSocketOptionException - (id)init { return [self initWithReason:@"Could not get/set socket option" option:-1 level:-1]; } - (id)initWithReason:(NSString *)_reason option:(int)_option level:(int)_level { if ((self = [super initWithReason:_reason])) { option = _option; level = _level; } return self; } - (int)option { return option; } - (int)level { return level; } @end /* NGSocketOptionException */ @implementation NGCouldNotSetSocketOptionException @end /* NGCouldNotSetSocketOptionException */ @implementation NGCouldNotGetSocketOptionException @end /* NGCouldNotGetSocketOptionException */ // ******************** socket closed ************** @implementation NGSocketShutdownException - (id)init { return [self initWithStream:nil reason:@"the socket was shutdown"]; } - (id)initWithReason:(NSString *)_reason { return [self initWithStream:nil reason:_reason]; } - (id)initWithReason:(NSString *)_reason socket:(id)_socket { return [self initWithStream:_socket reason:_reason]; } - (id)initWithSocket:(id)_socket { return [self initWithStream:_socket reason:@"the socket was shutdown"]; } /* accessors */ - (id)socket { return [self->streamPointer nonretainedObjectValue]; } @end /* NGSocketShutdownException */ @implementation NGSocketShutdownDuringReadException @end @implementation NGSocketShutdownDuringWriteException @end @implementation NGSocketTimedOutException @end @implementation NGSocketConnectionResetException @end SOPE/sope-core/NGStreams/TODO0000644000000000000000000000021715004363604014552 0ustar rootrootTODO for NGStreams ================== - can we support NSxxStreams? - do we really need the dependency to: - NGStreams - NGExtensions ? SOPE/sope-core/NGStreams/SxCore-NGStreams.graffle0000644000000000000000000036303315004363604020466 0ustar rootroot CanvasColor w 1.000000e+00 ColumnAlign 0 ColumnSpacing 5.400000e+01 GraphDocumentVersion 2 GraphicsList Class Group Graphics Bounds {{639, 1332}, {225, 18}} Class ShapedGraphic ID 8385 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGCouldNotGetSocketOptionException} Bounds {{720, 1359}, {225, 18}} Class ShapedGraphic ID 8386 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGCouldNotSetSocketOptionException} Bounds {{702, 1296}, {171, 18}} Class ShapedGraphic ID 8387 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGSocketOptionException} Class LineGraphic Head ID 8385 ID 8388 Points {778.5, 1314} {760.5, 1332} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8387 Class LineGraphic Head ID 8386 ID 8389 Points {793.929, 1314} {826.071, 1359} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8387 ID 8384 Bounds {{567, 999}, {234, 18}} Class ShapedGraphic ID 8383 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGCouldNotResolveHostNameException} Class Group Graphics Bounds {{324, 315}, {126, 18}} Class ShapedGraphic ID 8368 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGBase64Stream.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGBase64Stream} Bounds {{396, 279}, {126, 18}} Class ShapedGraphic ID 8369 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGLockingStream.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGLockingStream} Bounds {{252, 279}, {126, 18}} Class ShapedGraphic ID 8370 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGMD5Stream.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMD5Stream} Bounds {{396, 252}, {126, 18}} Class ShapedGraphic ID 8371 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGByteBuffer.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGByteBuffer} Bounds {{396, 225}, {126, 18}} Class ShapedGraphic ID 8372 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGByteCountStream.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGByteCountStream} Bounds {{252, 252}, {126, 18}} Class ShapedGraphic ID 8373 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGBufferedStream.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGBufferedStream} Bounds {{252, 225}, {126, 18}} Class ShapedGraphic ID 8374 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGGZipStream.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGGZipStream} Bounds {{324, 189}, {126, 18}} Class ShapedGraphic ID 8375 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGFilterStream.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGFilterStream} Class LineGraphic Head ID 8368 ID 8376 Points {387, 207} {387, 315} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8375 Class LineGraphic Head ID 8369 ID 8377 Points {394.2, 207} {451.8, 279} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8375 Class LineGraphic Head ID 8370 ID 8378 Points {379.8, 207} {322.2, 279} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8375 Class LineGraphic Head ID 8371 ID 8379 Points {397.286, 207} {448.714, 252} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8375 Class LineGraphic Head ID 8372 ID 8380 Points {405, 207} {441, 225} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8375 Class LineGraphic Head ID 8373 ID 8381 Points {376.714, 207} {325.286, 252} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8375 Class LineGraphic Head ID 8374 ID 8382 Points {369, 207} {333, 225} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8375 ID 8367 Bounds {{36, 981}, {207, 18}} Class ShapedGraphic ID 8366 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGCouldNotCloseStreamException} Class Group Graphics Bounds {{117, 1404}, {243, 18}} Class ShapedGraphic ID 8357 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGSocketShutdownDuringReadException} Bounds {{18, 1377}, {243, 18}} Class ShapedGraphic ID 8358 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGSocketConnectionResetException} Bounds {{117, 1350}, {243, 18}} Class ShapedGraphic ID 8359 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGSocketTimedOutException} Bounds {{54, 1287}, {279, 18}} Class ShapedGraphic ID 8360 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGSocketShutdownException} Bounds {{18, 1323}, {243, 18}} Class ShapedGraphic ID 8361 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGSocketShutdownDuringWriteException} Class LineGraphic Head ID 8357 ID 8362 Points {196.962, 1305} {235.038, 1404} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8360 Class LineGraphic Head ID 8358 ID 8363 Points {188.1, 1305} {144.9, 1377} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8360 Class LineGraphic Head ID 8359 ID 8364 Points {199.929, 1305} {232.071, 1350} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8360 Class LineGraphic Head ID 8361 ID 8365 Points {180, 1305} {153, 1323} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8360 ID 8356 Bounds {{567, 972}, {234, 18}} Class ShapedGraphic ID 8355 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGSocketIsAlreadyListeningException} Class Group Graphics Bounds {{225, 1089}, {180, 18}} Class ShapedGraphic ID 8348 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGStreamSeekErrorException} Bounds {{333, 1062}, {180, 18}} Class ShapedGraphic ID 8349 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGStreamWriteErrorException} Bounds {{225, 1035}, {180, 18}} Class ShapedGraphic ID 8350 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGStreamReadErrorException} Bounds {{279, 999}, {153, 18}} Class ShapedGraphic ID 8351 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGStreamErrorException} Class LineGraphic Head ID 8348 ID 8352 Points {351.45, 1017} {319.05, 1089} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8351 Class LineGraphic Head ID 8349 ID 8353 Points {365.143, 1017} {413.357, 1062} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8351 Class LineGraphic Head ID 8350 ID 8354 Points {345.375, 1017} {325.125, 1035} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8351 ID 8347 Class Group Graphics Bounds {{171, 540}, {126, 18}} Class ShapedGraphic ID 8334 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGDatagramSocket.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGDatagramSocket} Bounds {{315, 567}, {117, 18}} Class ShapedGraphic ID 8335 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGActiveSocket} Bounds {{171, 567}, {126, 18}} Class ShapedGraphic ID 8336 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGActiveSocket.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGActiveSocket} Bounds {{315, 513}, {117, 18}} Class ShapedGraphic ID 8337 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGPassiveSocket} Bounds {{171, 513}, {126, 18}} Class ShapedGraphic ID 8338 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGPassiveSocket.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGPassiveSocket} Bounds {{45, 576}, {81, 18}} Class ShapedGraphic ID 8339 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGSocket} Bounds {{45, 540}, {81, 18}} Class ShapedGraphic ID 8340 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocket.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGSocket} Class LineGraphic Head ID 8334 ID 8341 Points {126, 549} {171, 549} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8340 Class LineGraphic Head ID 8336 ID 8342 Points {315, 576} {297, 576} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 8335 Class LineGraphic Head ID 8336 ID 8343 Points {124.876, 556.159} {184.5, 567} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8340 Class LineGraphic Head ID 8338 ID 8344 Points {315, 522} {297, 522} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 8337 Class LineGraphic Head ID 8338 ID 8345 Points {124.876, 541.841} {184.5, 531} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8340 Class LineGraphic Head ID 8340 ID 8346 Points {85.5, 576} {85.5, 558} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 8339 ID 8333 Class Group Graphics Bounds {{558, 1179}, {198, 18}} Class ShapedGraphic ID 8329 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGSocketAlreadyBoundException} Bounds {{585, 1143}, {171, 18}} Class ShapedGraphic ID 8330 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGSocketBindException} Bounds {{603, 1206}, {198, 18}} Class ShapedGraphic ID 8331 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGCouldNotBindSocketException} Class LineGraphic Head ID 8331 ID 8332 Points {675, 1161} {697.5, 1206} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8330 ID 8328 Bounds {{567, 945}, {234, 18}} Class ShapedGraphic ID 8327 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGInvalidSocketDomainException} Class Group Graphics Bounds {{99, 684}, {126, 18}} Class ShapedGraphic ID 8316 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGCharBuffer.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGCharBuffer} Bounds {{243, 684}, {126, 18}} Class ShapedGraphic ID 8317 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStringTextStream.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGStringTextStream} Bounds {{99, 648}, {126, 18}} Class ShapedGraphic ID 8318 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGFilterTextStream.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGFilterTextStream} Bounds {{306, 648}, {126, 18}} Class ShapedGraphic ID 8319 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGCTextStream.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGCTextStream} Bounds {{297, 612}, {153, 18}} Class ShapedGraphic ID 8320 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGTextStreamProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGExtendedTextStream} Bounds {{153, 612}, {126, 18}} Class ShapedGraphic ID 8321 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGTextStream.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGTextStream} Class LineGraphic Head ID 8316 ID 8322 Points {162, 666} {162, 684} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8318 Class LineGraphic Head ID 8317 ID 8323 Points {227.25, 630} {294.75, 684} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8321 Class LineGraphic Head ID 8318 ID 8324 Points {202.5, 630} {175.5, 648} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8321 Class LineGraphic Head ID 8319 ID 8325 Points {254.25, 630} {330.75, 648} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8321 Class LineGraphic Head ID 8321 ID 8326 Points {297, 621} {279, 621} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 8320 ID 8315 Class Group Graphics Bounds {{234, 1233}, {180, 18}} Class ShapedGraphic ID 8308 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGWriteOnlyStreamException} Bounds {{234, 1179}, {180, 18}} Class ShapedGraphic ID 8309 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGReadOnlyStreamException} Bounds {{270, 1134}, {207, 18}} Class ShapedGraphic ID 8310 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGStreamModeException} Bounds {{306, 1206}, {207, 18}} Class ShapedGraphic ID 8311 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGUnknownStreamModeException} Class LineGraphic Head ID 8308 ID 8312 Points {369, 1152} {328.5, 1233} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8310 Class LineGraphic Head ID 8309 ID 8313 Points {363.6, 1152} {333.9, 1179} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8310 Class LineGraphic Head ID 8311 ID 8314 Points {378, 1152} {405, 1206} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8310 ID 8307 Bounds {{567, 918}, {234, 18}} Class ShapedGraphic ID 8306 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGDidNotFindServiceException} Bounds {{351, 837}, {171, 18}} Class ShapedGraphic ID 8305 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGIOSearchAccessException} Class Group Graphics Bounds {{99, 234}, {90, 18}} Class ShapedGraphic ID 8302 Shape RoundedRectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NSFileHandle} Bounds {{54, 270}, {180, 18}} Class ShapedGraphic ID 8303 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGConcreteStreamFileHandle.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGConcreteStreamFileHandle} Class LineGraphic Head ID 8303 ID 8304 Points {144, 252} {144, 270} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8302 ID 8301 Bounds {{567, 891}, {234, 18}} Class ShapedGraphic ID 8300 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGCouldNotListenException} Bounds {{189, 837}, {144, 18}} Class ShapedGraphic ID 8299 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGIOAccessException} Class Group Graphics Bounds {{837, 1116}, {225, 18}} Class ShapedGraphic ID 8292 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGSocketAlreadyConnectedException} Bounds {{801, 1143}, {198, 18}} Class ShapedGraphic ID 8293 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGSocketNotConnectedException} Bounds {{837, 1053}, {171, 18}} Class ShapedGraphic ID 8294 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGSocketConnectException} Bounds {{801, 1089}, {198, 18}} Class ShapedGraphic ID 8295 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGCouldNotConnectException} Class LineGraphic Head ID 8292 ID 8296 Points {926.357, 1071} {945.643, 1116} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8294 Class LineGraphic Head ID 8293 ID 8297 Points {920.25, 1071} {902.25, 1143} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8294 Class LineGraphic Head ID 8295 ID 8298 Points {916.875, 1071} {905.625, 1089} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8294 ID 8291 Class Group Graphics Bounds {{45, 306}, {207, 18}} Class ShapedGraphic ID 8289 Shape Rectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NSObjCTypeSerializationCallBack} Bounds {{45, 342}, {207, 18}} Class ShapedGraphic ID 8290 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamCoder.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGStreamCoder} ID 8288 Class Group Graphics Bounds {{45, 477}, {153, 18}} Class ShapedGraphic ID 8283 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGInternetSocketDomain.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGInternetSocketDomain} Bounds {{216, 468}, {117, 18}} Class ShapedGraphic ID 8284 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGSocketDomain} Bounds {{45, 450}, {153, 18}} Class ShapedGraphic ID 8285 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGLocalSocketDomain.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGLocalSocketDomain} Class LineGraphic Head ID 8283 ID 8286 Points {216, 480.441} {197.975, 481.501} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 8284 Class LineGraphic Head ID 8285 ID 8287 Points {216, 470.118} {194.883, 467.633} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 8284 ID 8282 Class Group Graphics Bounds {{252, 72}, {99, 18}} Class ShapedGraphic ID 8277 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGDataStream.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGDataStream} Bounds {{369, 45}, {135, 18}} Class ShapedGraphic ID 8278 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGPositionableStream} Bounds {{252, 27}, {99, 18}} Class ShapedGraphic ID 8279 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGFileStream.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGFileStream} Class LineGraphic Head ID 8277 ID 8280 Points {391.5, 63} {346.415, 72.017} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 8278 Class LineGraphic Head ID 8279 ID 8281 Points {369, 45} {350.325, 42.51} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 8278 ID 8276 Class Group Graphics Bounds {{72, 27}, {99, 18}} Class ShapedGraphic ID 8273 Shape RoundedRectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NSPipe} Bounds {{72, 63}, {99, 18}} Class ShapedGraphic ID 8274 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamPipe.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGStreamPipe} Class LineGraphic Head ID 8274 ID 8275 Points {121.5, 45} {121.5, 63} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8273 ID 8272 Bounds {{306, 936}, {207, 18}} Class ShapedGraphic ID 8271 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGStreamNotOpenException} Bounds {{27, 1197}, {162, 18}} Class ShapedGraphic ID 8270 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGEndOfStreamException} Bounds {{207, 774}, {108, 18}} Class ShapedGraphic ID 8269 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGIOException} Bounds {{567, 864}, {234, 18}} Class ShapedGraphic ID 8268 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGCouldNotCreateSocketException} Bounds {{198, 900}, {126, 18}} Class ShapedGraphic ID 8267 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGStreamException} Bounds {{18, 945}, {207, 18}} Class ShapedGraphic ID 8266 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGCouldNotOpenStreamException} Bounds {{729, 774}, {126, 18}} Class ShapedGraphic ID 8265 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGSocketException} Bounds {{567, 837}, {234, 18}} Class ShapedGraphic ID 8264 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGCouldNotAcceptException} Class Group Graphics Bounds {{351, 459}, {153, 18}} Class ShapedGraphic ID 8261 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGInternetSocketAddress.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGInternetSocketAddress} Bounds {{216, 441}, {117, 18}} Class ShapedGraphic ID 8262 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGSocketAddress} Bounds {{351, 432}, {153, 18}} Class ShapedGraphic ID 8263 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGLocalSocketAddress.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGLocalSocketAddress} ID 8260 Class LineGraphic Head ID 8261 ID 8259 Points {333, 456.882} {354.117, 459.367} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 8262 Class LineGraphic Head ID 8263 ID 8258 Points {333, 446.559} {351.025, 445.499} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 8262 Bounds {{342, 108}, {99, 18}} Class ShapedGraphic ID 8257 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGTaskStream.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGTaskStream} Class Group Graphics Bounds {{216, 387}, {126, 18}} Class ShapedGraphic ID 8255 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGSocketProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGDatagramPacket} Bounds {{45, 387}, {153, 18}} Class ShapedGraphic ID 8256 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGDatagramPacket.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGDatagramPacket} ID 8254 Class LineGraphic Head ID 8256 ID 8253 Points {216, 396} {198, 396} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 8255 Bounds {{207, 738}, {108, 18}} Class ShapedGraphic ID 8252 Shape RoundedRectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NSException} Bounds {{45, 189}, {81, 18}} Class ShapedGraphic ID 8251 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGStream} Bounds {{117, 117}, {153, 18}} Class ShapedGraphic ID 8250 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStreamProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGByteSequenceStream} Bounds {{153, 189}, {81, 18}} Class ShapedGraphic ID 8249 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGStreams/NGStreams/NGStream.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGStream} Class LineGraphic Head ID 8383 ID 8248 Points {787.68, 792} {688.32, 999} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8265 Class LineGraphic Head ID 8366 ID 8247 Points {247.5, 918} {153, 981} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8267 Class LineGraphic Head ID 8269 ID 8246 Points {261, 756} {261, 774} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8252 Class LineGraphic Head ID 8355 ID 8245 Points {787.091, 792} {688.909, 972} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8265 Class LineGraphic Head ID 8329 ID 8244 Points {667.125, 1161} {660.375, 1179} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8330 Class LineGraphic Head ID 8294 ID 8243 Points {796.21, 792} {918.29, 1053} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8265 Class LineGraphic Head ID 8360 ID 8242 Points {116.55, 1215} {184.95, 1287} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8270 Class LineGraphic Head ID 8327 ID 8241 Points {786.316, 792} {689.684, 945} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8265 Class LineGraphic Head ID 8387 ID 8240 Points {791.922, 792} {787.578, 1296} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8265 Class LineGraphic Head ID 8330 ID 8239 Points {789.037, 792} {673.463, 1143} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8265 Class LineGraphic Head ID 8306 ID 8238 Points {785.25, 792} {690.75, 918} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8265 Class LineGraphic Head ID 8305 ID 8237 Points {333, 846} {351, 846} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8299 Class LineGraphic Head ID 8300 ID 8236 Points {783.692, 792} {692.308, 891} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8265 Class LineGraphic Head ID 8299 ID 8235 Points {261, 792} {261, 837} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8269 Class LineGraphic Head ID 8290 ID 8234 Points {148.5, 324} {148.5, 342} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 8289 Class LineGraphic Head ID 8277 ID 8233 Points {201.808, 189} {293.192, 90} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8249 Class LineGraphic Head ID 8274 ID 8232 Points {88.0714, 189} {118.929, 81} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 8251 Class LineGraphic Head ID 8274 ID 8231 Points {181.5, 117} {133.5, 81} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 8250 Class LineGraphic Head ID 8279 ID 8230 Points {199.5, 189} {295.5, 45} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8249 Class LineGraphic Head ID 8271 ID 8229 Points {298.125, 918} {372.375, 936} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8267 Class LineGraphic Head ID 8351 ID 8228 Points {269.591, 918} {346.909, 999} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8267 Class LineGraphic Head ID 8310 ID 8227 Points {265.327, 918} {369.173, 1134} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8267 Class LineGraphic Head ID 8267 ID 8226 Points {261, 792} {261, 900} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8269 Class LineGraphic Head ID 8375 ID 8225 Points {234, 198} {324, 198} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8249 Class LineGraphic Head ID 8270 ID 8224 Points {256.364, 918} {112.636, 1197} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8267 Class LineGraphic Head ID 8265 ID 8223 Points {315, 783} {729, 783} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8269 Class LineGraphic Head ID 8268 ID 8222 Points {781.2, 792} {694.8, 864} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8265 Class LineGraphic Head ID 8266 ID 8221 Points {233.1, 918} {149.4, 945} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8267 Class LineGraphic Head ID 8264 ID 8220 Points {776.571, 792} {699.429, 837} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8265 Class LineGraphic Head ID 8257 ID 8219 Points {215.5, 189} {369.5, 126} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 8249 Class LineGraphic Head ID 8249 ID 8218 Points {126, 198} {153, 198} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 8251 Class LineGraphic Head ID 8249 ID 8217 Points {193.5, 135} {193.5, 189} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 8250 Class LineGraphic Head ID 8251 ID 8216 Points {85.5, 576} {85.5, 207} Style stroke HeadArrow FilledDiamond LineType 1 TailArrow 0 Tail ID 8339 GridInfo HPages 4 ImageCounter 1 IsPalette NO Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo AutoAdjust YES HierarchicalOrientation 0 MagneticFieldCenter {0, 0} MagnetsEnabled YES PageBreakColor w 3.333333e-01 PageBreaks YES PageSetup BAt0eXBlZHN0cmVhbYED6IQBQISEhAtOU1ByaW50SW5mbwGEhAhOU09iamVjdACFkoSE hBNOU011dGFibGVEaWN0aW9uYXJ5AISEDE5TRGljdGlvbmFyeQCUhAFpEpKEhIQITlNT dHJpbmcBlIQBKxBOU0pvYkRpc3Bvc2l0aW9uhpKEmZkPTlNQcmludFNwb29sSm9ihpKE mZkOTlNCb3R0b21NYXJnaW6GkoSEhAhOU051bWJlcgCEhAdOU1ZhbHVlAJSEASqEhAFm nSSGkoSZmQtOU1BhcGVyTmFtZYaShJmZBkxldHRlcoaShJmZD05TUHJpbnRBbGxQYWdl c4aShJ2chIQBc54AhpKEmZkNTlNSaWdodE1hcmdpboaShJ2cn50khpKEmZkITlNDb3Bp ZXOGkoSdnISEAVOfAYaShJmZD05TU2NhbGluZ0ZhY3RvcoaShJ2chIQBZKABhpKEmZkL TlNGaXJzdFBhZ2WGkoSdnKmfAYaShJmZFE5TVmVydGljYWxQYWdpbmF0aW9uhpKEnZyk ngCGkoSZmRVOU0hvcml6b25hbFBhZ2luYXRpb26GkoSdnKSeAIaShJmZFk5TSG9yaXpv bnRhbGx5Q2VudGVyZWSGkoSdnKSeAYaShJmZDE5TTGVmdE1hcmdpboaShJ2cn50khpKE mZkNTlNPcmllbnRhdGlvboaShJ2cpJ4AhpKEmZkZTlNQcmludFJldmVyc2VPcmllbnRh dGlvboaSo5KEmZkKTlNMYXN0UGFnZYaShJ2chJeXgn////+GkoSZmQtOU1RvcE1hcmdp boaShJ2cn50khpKEmZkUTlNWZXJ0aWNhbGx5Q2VudGVyZWSGkrSShJmZC05TUGFwZXJT aXplhpKEnpyEhAx7X05TU2l6ZT1mZn2hgQJkgQMYhoaG RowAlign 0 RowSpacing 9.000000e+00 VPages 2 WindowInfo Frame {{185, 90}, {794, 751}} VisibleRegion {{0, 0}, {1038.67, 898.667}} Zoom 0.75 SOPE/sope-core/NGStreams/GNUmakefile.preamble0000644000000000000000000000372415004363604017730 0ustar rootroot# compilation settings libNGStreams_INCLUDE_DIRS += \ -INGStreams \ -I../NGExtensions \ -I.. NGStreams_INCLUDE_DIRS += $(libNGStreams_INCLUDE_DIRS) # dependencies libNGStreams_LIBRARIES_DEPEND_UPON += \ -lz $(BASE_LIBS) NGStreams_LIBRARIES_DEPEND_UPON += \ -framework NGExtensions -framework EOControl \ -framework DOM -framework SaxObjC \ -lz # library/framework search pathes DEP_DIRS = \ ../NGExtensions \ ../EOControl \ ../../sope-xml/DOM ../../sope-xml/SaxObjC ifneq ($(frameworks),yes) ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),\ -L$(GNUSTEP_BUILD_DIR)/$(dir)/$(GNUSTEP_OBJ_DIR_NAME)) else ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir)) endif ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) ifeq ($(findstring openbsd, $(GNUSTEP_TARGET_OS)), openbsd) SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib else SYSTEM_LIB_DIR += -L/usr/local/lib64 -L/usr/lib64 endif else SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib endif # activating SSL support ifeq ($(HAS_LIBRARY_gnutls),yes) libNGStreams_OBJC_FILES += NGActiveSSLSocket.m NGStreams_OBJC_FILES += NGActiveSSLSocket.m ADDITIONAL_CPPFLAGS += -DHAVE_GNUTLS=1 libNGStreams_LIBRARIES_DEPEND_UPON += -lgnutls NGStreams_LIBRARIES_DEPEND_UPON += -lgnutls else ifeq ($(HAS_LIBRARY_ssl),yes) libNGStreams_OBJC_FILES += NGActiveSSLSocket.m NGStreams_OBJC_FILES += NGActiveSSLSocket.m ADDITIONAL_CPPFLAGS += -DHAVE_OPENSSL=1 -DOPENSSL_NO_KRB5 libNGStreams_LIBRARIES_DEPEND_UPON += -lssl -lcrypto NGStreams_LIBRARIES_DEPEND_UPON += -lssl -lcrypto endif endif # pass CA bundle ifdef CA_BUNDLE ADDITIONAL_CPPFLAGS += -DCA_BUNDLE="\"$(CA_BUNDLE)\"" endif ADDITIONAL_CPPFLAGS += -Wall -Wno-protocol # reentrant ifeq ($(reentrant),yes) ADDITIONAL_CPPFLAGS += -D_REENTRANT=1 endif # Apple ifeq ($(FOUNDATION_LIB),apple) libNGStreams_PREBIND_ADDR="0xC1400000" libNGStreams_LDFLAGS += -seg1addr $(libNGStreams_PREBIND_ADDR) NGStreams_LDFLAGS += -seg1addr $(libNGStreams_PREBIND_ADDR) endif SOPE/sope-core/NGStreams/NGPassiveSocket.m0000644000000000000000000001671415004363604017261 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGPassiveSocket.h" #include "NGSocketExceptions.h" #include "NGActiveSocket.h" #include "NGSocket+private.h" #if defined(__APPLE__) # include # include #endif #if HAVE_SYS_ERRNO_H || defined(__APPLE__) # include #endif #include "common.h" @interface NGActiveSocket(privateMethods) - (id)_initWithDescriptor:(int)_fd localAddress:(id)_local remoteAddress:(id)_remote; @end @implementation NGPassiveSocket + (id)socketBoundToAddress:(id)_address { volatile id sock; sock = [[[self alloc] initWithDomain:[_address domain]] autorelease]; [sock bindToAddress:_address]; return sock; } - (id)initWithDomain:(id)_domain { // designated initializer if ((self = [super initWithDomain:_domain])) { backlogSize = -1; // -1 means 'not listening' if ([NSThread isMultiThreaded]) acceptLock = [[NSLock allocWithZone:[self zone]] init]; else { acceptLock = nil; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskNowMultiThreaded:) name:NSWillBecomeMultiThreadedNotification object:nil]; } if (self->fd != NGInvalidSocketDescriptor) { int i_yes = 1; if (setsockopt(self->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&i_yes, sizeof(int)) != 0) { NSLog(@"WARNING: could not set SO_REUSEADDR option for socket %@: %s", self, strerror(errno)); } } } return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWillBecomeMultiThreadedNotification object:nil]; [self->acceptLock release]; [super dealloc]; } - (void)taskNowMultiThreaded:(NSNotification *)_notification { if (acceptLock == nil) acceptLock = [[NSLock alloc] init]; } // accessors - (BOOL)isListening { return (backlogSize != -1); } - (BOOL)isOpen { return [self isListening]; } - (id)localAddress { return localAddress; } - (int)socketType { return SOCK_STREAM; } /* operations */ #if defined(WIN32) && !defined(__CYGWIN32__) - (NSString *)reasonForLastError { int errorCode = WSAGetLastError(); switch (errorCode) { case WSAEBADF: return @"not a valid socket descriptor"; case WSAENOTSOCK: return @"descriptor is not a socket descriptor"; case WSAEOPNOTSUPP: return @"socket does not support listen"; case WSAEINTR: return @"interrupted by signal"; case WSAEMFILE: return @"descriptor table is full"; default: return [NSString stringWithCString:strerror(errorCode)]; } } #else - (NSString *)reasonForLastError { int errorCode = errno; switch (errorCode) { case EBADF: return @"not a valid socket descriptor"; case ENOTSOCK: return @"descriptor is not a socket descriptor"; case EOPNOTSUPP: return @"socket does not support listen"; case EINTR: return @"interrupted by signal"; case EMFILE: return @"descriptor table is full"; case EPROTONOSUPPORT: return @"The protocol is not supported by the address family or " @"implementation"; case EPROTOTYPE: return @"The socket type is not supported by the protocol"; default: return [NSString stringWithCString:strerror(errorCode)]; } } #endif - (BOOL)listenWithBacklog:(int)_backlogSize { // throws // NGSocketIsAlreadyListeningException when the socket is in the listen state // NGCouldNotListenException when the listen call failed if ([self isListening]) { [[[NGSocketIsAlreadyListeningException alloc] initWithReason:@"already called listen" socket:self] raise]; return NO; } if (listen([self fileDescriptor], _backlogSize) != 0) { NSString *reason; reason = [self reasonForLastError]; reason = [@"Could not listen: %@" stringByAppendingString:reason]; [[[NGCouldNotListenException alloc] initWithReason:reason socket:self] raise]; return NO; } /* set backlog size (and mark socket as 'listening') */ self->backlogSize = _backlogSize; return YES; } - (id)accept { // throws // NGCouldNotAcceptException when the socket is not listening // NGCouldNotAcceptException when the accept call failed id socket; *(&socket) = nil; if (![self isListening]) { [[[NGCouldNotAcceptException alloc] initWithReason:@"socket is not listening" socket:self] raise]; } SYNCHRONIZED(self->acceptLock) { id local = nil; id remote = nil; socklen_t len; char *data; int newFd = NGInvalidSocketDescriptor; fd_set read_fds; int activity = 0; len = [[self domain] addressRepresentationSize]; data = calloc(1, len + 1); struct timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; FD_ZERO(&read_fds); FD_SET(fd, &read_fds); activity = select(fd + 1, &read_fds, NULL, NULL, &timeout); if (activity > 0) { if ((newFd = accept(fd, (void *)data, &len)) == -1) { // call failed NSString *reason = nil; reason = [self reasonForLastError]; reason = [@"Could not accept: " stringByAppendingString:reason]; [[[NGCouldNotAcceptException alloc] initWithReason:reason socket:self] raise]; } /* produce remote socket address object */ remote = [[self domain] addressWithRepresentation:(void *)data size:len]; // getsockname if wildcard-IP-bind to get local IP address assigned // to the connection len = [[self domain] addressRepresentationSize]; if (getsockname(newFd, (void *)data, &len) != 0) { // function is MT-safe [[[NGSocketException alloc] initWithReason:@"could not get local socket name" socket:self] raise]; } local = [[self domain] addressWithRepresentation:(void *)data size:len]; if (data) { free(data); data = NULL; } socket = [[NGActiveSocket alloc] _initWithDescriptor:newFd localAddress:local remoteAddress:remote]; socket = [socket autorelease]; } } END_SYNCHRONIZED; return socket; } // description - (NSString *)description { return [NSString stringWithFormat:@"", [self localAddress]]; } @end /* NGPassiveSocket */ SOPE/sope-core/NGStreams/NGTextStream.m0000644000000000000000000001125515004363604016571 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGTextStream.h" #include "common.h" @implementation NGTextStream - (void)dealloc { [self->lastException release]; [super dealloc]; } /* NGTextInputStream */ - (NSException *)lastException { return nil; } - (void)setLastException:(NSException *)_exception { ASSIGN(self->lastException, _exception); } - (void)resetLastException { [self->lastException release]; self->lastException = nil; } - (unichar)readCharacter { [self subclassResponsibility:_cmd]; return 0; } - (BOOL)isOpen { return YES; } /* NGExtendedTextInputStream */ - (NSString *)readLineAsString { NSMutableString *str; unichar c; *(&str) = (id)[NSMutableString string]; NS_DURING { while ((c = [self readCharacter]) != '\n') [str appendString:[NSString stringWithCharacters:&c length:1]]; } NS_HANDLER { if ([localException isKindOfClass:[NGEndOfStreamException class]]) { if ([str length] == 0) str = nil; } else [localException raise]; } NS_ENDHANDLER; return str; } - (unsigned)readCharacters:(unichar *)_chars count:(unsigned)_count { /* Read up to _count characters, but one at the minimum. */ volatile unsigned pos; NS_DURING { for (pos = 0; pos < _count; pos++) _chars[pos] = [self readCharacter]; } NS_HANDLER { if ([localException isKindOfClass:[NGEndOfStreamException class]]) { if (pos == 0) [localException raise]; } else [localException raise]; } NS_ENDHANDLER; NSAssert1(pos > 0, @"invalid character count to be returned: %i", pos); return pos; } - (BOOL)safeReadCharacters:(unichar *)_chars count:(unsigned)_count { volatile unsigned pos; for (pos = 0; pos < _count; pos++) _chars[pos] = [self readCharacter]; return YES; } /* NGTextOutputStream */ - (BOOL)writeCharacter:(unichar)_character { [self subclassResponsibility:_cmd]; return NO; } - (BOOL)writeString:(NSString *)_string { unsigned length = [_string length], cnt = 0; unichar buffer[length]; void (*writeChar)(id, SEL, unichar); writeChar = (void (*)(id,SEL,unichar)) [self methodForSelector:@selector(writeCharacter:)]; [_string getCharacters:buffer]; for (cnt = 0; cnt < length; cnt++) writeChar(self, @selector(writeCharacter:), buffer[cnt]); return YES; } - (BOOL)flush { return YES; } /* NGExtendedTextOutputStream */ - (BOOL)writeFormat:(NSString *)_format arguments:(va_list)_ap { NSString *tmp; tmp = [[[NSString alloc] initWithFormat:_format arguments:_ap] autorelease]; [self writeString:tmp]; return YES; } - (BOOL)writeFormat:(NSString *)_format, ... { va_list ap; BOOL res = NO; va_start(ap, _format); #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 /* As soon as we add an exception handler on Leopard compilation * breaks. Probably some GCC bug. */ res = [self writeFormat:_format arguments:ap]; #else NS_DURING { res = [self writeFormat:_format arguments:ap]; } NS_HANDLER { va_end(ap); [localException raise]; } NS_ENDHANDLER; #endif va_end(ap); return res; } - (BOOL)writeNewline { if (![self writeString:@"\n"]) return NO; return [self flush]; } - (unsigned)writeCharacters:(const unichar *)_chars count:(unsigned)_count { /* Write up to _count characters, but one at the minimum. */ volatile unsigned pos; NS_DURING { for (pos = 0; pos < _count; pos++) [self writeCharacter:_chars[pos]]; } NS_HANDLER { if ([localException isKindOfClass:[NGEndOfStreamException class]]) { if (pos == 0) [localException raise]; } else [localException raise]; } NS_ENDHANDLER; NSAssert1(pos > 0, @"invalid character count to be returned: %i", pos); return pos; } - (BOOL)safeWriteCharacters:(const unichar *)_chars count:(unsigned)_count { unsigned pos; for (pos = 0; pos < _count; pos++) { if (![self writeCharacter:_chars[pos]]) return NO; } return YES; } @end /* NGTextStream */ SOPE/sope-core/NGStreams/NGBufferedStream.m0000644000000000000000000003171215004363604017367 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "common.h" #define NEWLINE_CHAR '\n' #define WRITE_WARN_SIZE (1024 * 1024 * 100) /* 100MB */ @implementation NGBufferedStream static const unsigned DEFAULT_BUFFER_SIZE = 512; static Class DataStreamClass = Nil; + (void)initialize { DataStreamClass = NSClassFromString(@"NGDataStream"); } // returns the number of bytes which where read from the buffer #define numberOfConsumedReadBufferBytes(self) \ ((self->readBufferSize == 0) ? 0 : (self->readBufferPos - self->readBuffer)) // returns the number of bytes which can be read from buffer (without source access) #define numberOfAvailableReadBufferBytes(self) \ (self->readBufferFillSize - numberOfConsumedReadBufferBytes(self)) // look whether all bytes in the buffer where consumed, if so, reset the buffer #define checkReadBufferFillState(self) \ if (numberOfAvailableReadBufferBytes(self) == 0) { \ self->readBufferPos = self->readBuffer; \ self->readBufferFillSize = 0; \ } // ******************** constructors ******************** + (id)filterWithSource:(id)_source bufferSize:(unsigned)_size { if (_source == nil) return nil; if (*(Class *)_source == DataStreamClass) return _source; return [[[self alloc] initWithSource:_source bufferSize:_size] autorelease]; } // TODO: can we reduced duplicate code here ... - (id)initWithSource:(id)_source bufferSize:(unsigned)_size { if (_source == nil) { [self release]; return nil; } if (*(Class *)_source == DataStreamClass) { [self release]; return (id)[_source retain]; } if ((self = [super initWithSource:_source])) { self->readBuffer = calloc(_size, 1); self->writeBuffer = calloc(_size, 1); self->readBufferPos = self->readBuffer; self->readBufferSize = _size; self->readBufferFillSize = 0; // no bytes are read from source self->writeBufferFillSize = 0; self->writeBufferSize = _size; self->flags._flushOnNewline = 1; } return self; } - (id)initWithInputSource:(id)_source bufferSize:(unsigned)_s { if (_source == nil) { [self release]; return nil; } if (*(Class *)_source == DataStreamClass) { [self release]; return (id)[_source retain]; } if ((self = [super initWithInputSource:_source])) { self->readBuffer = calloc(_s, 1); self->readBufferPos = self->readBuffer; self->readBufferSize = _s; self->readBufferFillSize = 0; // no bytes are read from source self->flags._flushOnNewline = 1; } return self; } - (id)initWithOutputSource:(id)_src bufferSize:(unsigned)_s { if (_src == nil) { [self release]; return nil; } if (*(Class *)_src == DataStreamClass) { [self release]; return (id)[_src retain]; } if ((self = [super initWithOutputSource:_src])) { self->writeBuffer = calloc(_s, 1); self->writeBufferFillSize = 0; self->writeBufferSize = _s; self->flags._flushOnNewline = 1; } return self; } - (id)initWithSource:(id)_source { return [self initWithSource:_source bufferSize:DEFAULT_BUFFER_SIZE]; } - (id)initWithInputSource:(id)_source { return [self initWithInputSource:_source bufferSize:DEFAULT_BUFFER_SIZE]; } - (id)initWithOutputSource:(id)_source { return [self initWithOutputSource:_source bufferSize:DEFAULT_BUFFER_SIZE]; } - (void)dealloc { [self flush]; if (self->readBuffer) { free(self->readBuffer); self->readBuffer = NULL; self->readBufferPos = NULL; } self->readBufferFillSize = 0; self->readBufferSize = 0; if (self->writeBuffer) { free(self->writeBuffer); self->writeBuffer = NULL; } self->writeBufferFillSize = 0; self->writeBufferSize = 0; [super dealloc]; } /* accessors */ - (void)setReadBufferSize:(unsigned)_size { [self flush]; if (_size == self->readBufferSize) return; if (_size == 0) { if (self->readBuffer != NULL) { free(self->readBuffer); self->readBuffer = NULL; } self->readBufferSize = _size; self->readBufferPos = NULL; } else { if (self->readBuffer != NULL) self->readBuffer = realloc(self->readBuffer, _size); else self->readBuffer = calloc(_size, 1); self->readBufferSize = _size; self->readBufferPos = self->readBuffer; self->readBufferFillSize = 0; // no bytes a read from source } } - (unsigned)readBufferSize { return self->readBufferSize; } - (void)setWriteBufferSize:(unsigned)_size { [self flush]; if (_size == self->writeBufferSize) return; self->writeBuffer = realloc(self->writeBuffer, _size); self->writeBufferSize = _size; } - (unsigned)writeBufferSize { return self->writeBufferSize; } /* blocking .. */ - (BOOL)wouldBlockInMode:(NGStreamMode)_mode { BOOL canRead, canWrite; if (self->readBufferSize == 0) canRead = NO; else canRead = (numberOfAvailableReadBufferBytes(self) > 0); canWrite = (self->writeBufferSize == 0) ? NO : (self->writeBufferFillSize > 0); if ((_mode == NGStreamMode_readWrite) && canRead && canWrite) return NO; if ((_mode == NGStreamMode_readOnly) && canRead) { return NO; } if ((_mode == NGStreamMode_writeOnly) && canWrite) return NO; return ([self->source respondsToSelector:@selector(wouldBlockInMode:)]) ? [(id)self->source wouldBlockInMode:_mode] : YES; } /* primitives */ - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { register unsigned availBytes = numberOfAvailableReadBufferBytes(self); if (self->readBufferSize == 0) { // no read buffering is done (buffersize==0) return (readBytes != NULL) ? readBytes(source, _cmd, _buf, _len) : [source readBytes:_buf count:_len]; } if (availBytes >= _len) { // there are enough bytes in the buffer to fulfill the request if (_len == 1) { *(unsigned char *)_buf = *(unsigned char *)self->readBufferPos; self->readBufferPos++; } else { memcpy(_buf, self->readBufferPos, _len); self->readBufferPos += _len; // update read position (consumed-size) } checkReadBufferFillState(self); // check whether all bytes where consumed return _len; } else if (availBytes > 0) { // there are some bytes in the buffer, these are returned memcpy(_buf, self->readBufferPos, availBytes);// copy all bytes from buffer self->readBufferPos = self->readBuffer; // reset position self->readBufferFillSize = 0; // no bytes available in buffer anymore return availBytes; } else if (_len > self->readBufferSize) { /* requested _len is bigger than the buffersize, so we can bypass the buffer (which is empty, as guaranteed by the previous 'ifs' */ NSAssert(self->readBufferPos == self->readBuffer, @"read buffer position is not reset"); NSAssert(self->readBufferFillSize == 0, @"there are bytes in the buffer"); availBytes = (readBytes != NULL) ? (unsigned)readBytes(source, _cmd, _buf, _len) : [source readBytes:_buf count:_len]; if (availBytes == NGStreamError) return NGStreamError; NSAssert(availBytes != 0, @"readBytes:count: may never return zero !"); return availBytes; // return the number of bytes which could be read } else { /* no bytes are available and the requested _len is smaller than the possible buffer size, we have to read the next block of input from the source */ NSAssert(self->readBufferPos == self->readBuffer, @"read buffer position is not reset"); NSAssert(self->readBufferFillSize == 0, @"there are bytes in the buffer"); self->readBufferFillSize = (readBytes != NULL) ? (unsigned)readBytes(source,_cmd, self->readBuffer,self->readBufferSize) : [source readBytes:self->readBuffer count:self->readBufferSize]; if (self->readBufferFillSize == NGStreamError) { self->readBufferFillSize = 0; return NGStreamError; } NSAssert(self->readBufferFillSize != 0, @"readBytes:count: may never return zero !"); /* now comes a section which is roughly the same like the first to conditionals in this method */ if (self->readBufferFillSize >= _len) { // there are enough bytes in the buffer to fulfill the request memcpy(_buf, self->readBufferPos, _len); self->readBufferPos += _len; // update read position (consumed-size) checkReadBufferFillState(self); // check whether all bytes where consumed return _len; } else { // (readBufferFillSize > 0) (this is ensured by the above assert) // there are some bytes in the buffer, these are returned availBytes = self->readBufferFillSize; // copy all bytes from buffer memcpy(_buf, self->readBufferPos, self->readBufferFillSize); self->readBufferPos = self->readBuffer; // reset position self->readBufferFillSize = 0; // no bytes available in buffer anymore return availBytes; } } } - (int)readByte { if (self->readBufferSize == 0) // no read buffering is done (buffersize==0) return [super readByte]; if (numberOfAvailableReadBufferBytes(self) >= 1) { unsigned char byte = *(unsigned char *)self->readBufferPos; self->readBufferPos++; checkReadBufferFillState(self); // check whether all bytes where consumed return byte; } return [super readByte]; } - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len { register unsigned tmp = 0; register unsigned remaining = _len; register void *track = (void *)_buf; #if DEBUG if (_len > WRITE_WARN_SIZE) { NSLog(@"WARNING(%s): got passed in length %uMB (%u bytes, errcode=%u) ...", __PRETTY_FUNCTION__, (_len / 1024 / 1024), _len, NGStreamError); } #endif while (remaining > 0) { // how much bytes available in buffer ? tmp = self->writeBufferSize - self->writeBufferFillSize; tmp = (tmp > remaining) ? remaining : tmp; memcpy((self->writeBuffer + self->writeBufferFillSize), track, tmp); track += tmp; remaining -= tmp; self->writeBufferFillSize += tmp; if (self->writeBufferFillSize == self->writeBufferSize) { BOOL ok; ok = [self->source safeWriteBytes:self->writeBuffer count:self->writeBufferFillSize]; if (!ok) return NGStreamError; self->writeBufferFillSize = 0; } } if (self->flags._flushOnNewline == 1) { // scan buffer for newlines, if one is found, flush buffer for (tmp = 0; tmp < _len; tmp++) { if (tmp == NEWLINE_CHAR) { if (![self flush]) return NGStreamError; break; } } } /* clean up for GC */ tmp = 0; track = NULL; // clean up for GC remaining = 0; return _len; } - (BOOL)close { if (![self flush]) return NO; if (self->readBuffer) { free(self->readBuffer); self->readBuffer = NULL; self->readBufferPos = NULL; } self->readBufferFillSize = 0; self->readBufferSize = 0; if (self->writeBuffer) { free(self->writeBuffer); self->writeBuffer = NULL; } self->writeBufferFillSize = 0; self->writeBufferSize = 0; return [super close]; } - (BOOL)flush { if (self->writeBufferFillSize > 0) { BOOL ok; #if DEBUG if (self->writeBufferFillSize > WRITE_WARN_SIZE) { NSLog(@"WARNING(%s): shall flush %uMB (%u bytes, errcode=%u) ...", __PRETTY_FUNCTION__, (self->writeBufferFillSize/1024/1024), self->writeBufferFillSize, NGStreamError); //abort(); } #endif ok = [self->source safeWriteBytes:self->writeBuffer count:self->writeBufferFillSize]; if (!ok) { /* should check exception for fill size ? ... */ return NO; } self->writeBufferFillSize = 0; } return YES; } @end /* NGBufferedStream */ @implementation NGStream(NGBufferedStreamExtensions) - (NGBufferedStream *)bufferedStream { return [NGBufferedStream filterWithSource:self]; } @end /* NGStream(NGBufferedStreamExtensions) */ @implementation NGBufferedStream(NGBufferedStreamExtensions) - (NGBufferedStream *)bufferedStream { return self; } @end /* NGBufferedStream(NGBufferedStreamExtensions) */ SOPE/sope-core/NGStreams/NGActiveSocket.m0000644000000000000000000007475415004363604017072 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "config.h" #if defined(HAVE_UNISTD_H) || defined(__APPLE__) # include #endif #ifdef HAVE_SYS_SELECT_H # include #endif #ifdef HAVE_SYS_FILIO_H # include #endif #if defined(HAVE_SYS_IOCTL_H) # include #endif #if defined(HAVE_TIME_H) || defined(__APPLE__) # include #endif #if defined(HAVE_SYS_TIME_H) || defined(__APPLE__) # include #endif #if defined(HAVE_FCNTL_H) || defined(__APPLE__) # include #endif #if defined(__APPLE__) # include # include # include #endif #if HAVE_WINDOWS_H && !defined(__CYGWIN32__) # include #endif #if defined(WIN32) && !defined(__CYGWIN32__) # include # define ioctl ioctlsocket #endif #include "common.h" #include #include #include #include "NGActiveSocket.h" #include "NGSocketExceptions.h" #include "NGSocket+private.h" #include "common.h" #if !defined(POLLRDNORM) # define POLLRDNORM POLLIN #endif @interface NGActiveSocket(PrivateMethods) - (id)_initWithDescriptor:(int)_fd localAddress:(id)_local remoteAddress:(id)_remote; @end @implementation NGActiveSocket #if !defined(WIN32) || defined(__CYGWIN32__) + (BOOL)socketPair:(id[2])_pair { int fds[2]; NGLocalSocketDomain *domain; _pair[0] = nil; _pair[1] = nil; domain = [NGLocalSocketDomain domain]; if (socketpair([domain socketDomain], SOCK_STREAM, [domain protocol], fds) == 0) { NGActiveSocket *s1 = nil; NGActiveSocket *s2 = nil; NGLocalSocketAddress *address; s1 = [[self alloc] _initWithDomain:domain descriptor:fds[0]]; s2 = [[self alloc] _initWithDomain:domain descriptor:fds[1]]; s1 = [s1 autorelease]; s2 = [s2 autorelease]; address = [NGLocalSocketAddress address]; if ((s1 != nil) && (s2 != nil)) { s1->mode = NGStreamMode_readWrite; s1->receiveTimeout = 0.0; s1->sendTimeout = 0.0; ASSIGN(s1->remoteAddress, address); s2->mode = NGStreamMode_readWrite; s2->receiveTimeout = 0.0; s2->sendTimeout = 0.0; ASSIGN(s2->remoteAddress, address); _pair[0] = s1; _pair[1] = s2; return YES; } else return NO; } else { int e = errno; NSString *reason = nil; switch (e) { case EACCES: reason = @"Not allowed to create socket of this type"; break; case ENOMEM: reason = @"Could not create socket: Insufficient user memory available"; break; case EPROTONOSUPPORT: reason = @"The protocol is not supported by the address family or " @"implementation"; break; case EPROTOTYPE: reason = @"The socket type is not supported by the protocol"; break; case EMFILE: reason = @"Could not create socket: descriptor table is full"; break; case EOPNOTSUPP: reason = @"The specified protocol does not permit creation of socket " @"pairs"; break; #if DEBUG case 0: NSLog(@"WARNING(%s): socketpair() call failed, but errno=0", __PRETTY_FUNCTION__); #endif default: reason = [NSString stringWithFormat:@"Could not create socketpair: %s", strerror(e)]; break; } [[[NGCouldNotCreateSocketException alloc] initWithReason:reason domain:domain] raise]; return NO; } } #endif + (id)socketConnectedToAddress:(id)_address { volatile id sock = [[self alloc] initWithDomain:[_address domain]]; if (sock != nil) { if (![sock connectToAddress:_address]) { NSException *e; /* this method needs to raise the exception, since no object is returned in which we could check the -lastException ... */ e = [[sock lastException] retain]; [sock autorelease]; [self release]; e = [e autorelease]; [e raise]; return nil; } sock = [sock autorelease]; } return sock; } - (id)initWithDomain:(id)_domain { // designated initializer if ((self = [super initWithDomain:_domain])) { self->mode = NGStreamMode_readWrite; self->receiveTimeout = 0.0; self->sendTimeout = 0.0; } return self; } - (id)_initWithDescriptor:(int)_fd localAddress:(id)_local remoteAddress:(id)_remote { if ((self = [self _initWithDomain:[_local domain] descriptor:_fd])) { ASSIGN(self->localAddress, _local); ASSIGN(self->remoteAddress, _remote); self->mode = NGStreamMode_readWrite; #if !defined(WIN32) || defined(__CYGWIN32__) NGAddDescriptorFlag(self->fd, O_NONBLOCK); #endif } return self; } - (void)dealloc { [self->remoteAddress release]; [super dealloc]; } /* operations */ - (NSException *)lastException { return [super lastException]; } - (void)raise:(NSString *)_name reason:(NSString *)_reason { Class clazz; NSException *e; clazz = NSClassFromString(_name); NSAssert1(clazz, @"did not find exception class %@", _name); e = [clazz alloc]; if (_reason) { if ([clazz instancesRespondToSelector:@selector(initWithReason:socket:)]) e = [(id)e initWithReason:_reason socket:self]; else if ([clazz instancesRespondToSelector:@selector(initWithStream:reason:)]) e = [(id)e initWithStream:self reason:_reason]; else if ([clazz instancesRespondToSelector:@selector(initWithSocket:)]) e = [(id)e initWithSocket:self]; else if ([clazz instancesRespondToSelector:@selector(initWithStream:)]) e = [(id)e initWithStream:self]; else e = [e initWithReason:_reason]; } else { if ([clazz instancesRespondToSelector:@selector(initWithSocket:)]) e = [(id)e initWithSocket:self]; else if ([clazz instancesRespondToSelector:@selector(initWithStream:)]) e = [(id)e initWithStream:self]; else e = [e init]; } [self setLastException:e]; [e release]; } - (void)raise:(NSString *)_name { [self raise:_name reason:nil]; } - (BOOL)markNonblockingAfterConnect { #if !defined(WIN32) || defined(__CYGWIN32__) // mark socket as non-blocking return YES; #else // on Win we only support blocking sockets right now ... return NO; #endif } - (BOOL)primaryConnectToAddress:(id)_address { // throws // NGCouldNotConnectException if the the connect() call fails [self resetLastException]; if (connect(fd, (struct sockaddr *)[_address internalAddressRepresentation], [_address addressRepresentationSize]) != 0) { NSString *reason = nil; int errorCode = errno; NSException *e; switch (errorCode) { case EACCES: reason = @"search permission denied for element in path"; break; #if defined(WIN32) && !defined(__CYGWIN32__) case WSAEADDRINUSE: reason = @"address already in use"; break; case WSAEADDRNOTAVAIL: reason = @"address is not available on remote machine"; break; case WSAEAFNOSUPPORT: reason = @"addresses in the specified family cannot be used with the socket"; break; case WSAEALREADY: reason = @"a previous non-blocking attempt has not yet been completed"; break; case WSAEBADF: reason = @"descriptor is invalid"; break; case WSAECONNREFUSED: reason = @"connection refused"; break; case WSAEINTR: reason = @"connect was interrupted"; break; case WSAEINVAL: reason = @"the address length is invalid"; break; case WSAEISCONN: reason = @"socket is already connected"; break; case WSAENETUNREACH: reason = @"network is unreachable"; break; case WSAETIMEDOUT: reason = @"timeout occured"; break; #else case EADDRINUSE: reason = @"address already in use"; break; case EADDRNOTAVAIL: reason = @"address is not available on remote machine"; break; case EAFNOSUPPORT: reason = @"addresses in the specified family cannot be used with the socket"; break; case EALREADY: reason = @"a previous non-blocking attempt has not yet been completed"; break; case EBADF: reason = @"descriptor is invalid"; break; case ECONNREFUSED: reason = @"connection refused"; break; case EINTR: reason = @"connect was interrupted"; break; case EINVAL: reason = @"the address length is invalid"; break; case EIO: reason = @"an IO error occured"; break; case EISCONN: reason = @"socket is already connected"; break; case ENETUNREACH: reason = @"network is unreachable"; break; case ETIMEDOUT: reason = @"timeout occured"; break; #endif #if DEBUG case 0: NSLog(@"WARNING(%s): connect() call failed, but errno=0", __PRETTY_FUNCTION__); #endif default: reason = [NSString stringWithCString:strerror(errorCode)]; break; } reason = [NSString stringWithFormat:@"Could not connect to address %@: %@", _address, reason]; e = [[NGCouldNotConnectException alloc] initWithReason:reason socket:self address:_address]; [self setLastException:e]; [e release]; return NO; } /* connect was successful */ ASSIGN(self->remoteAddress, _address); if ([self markNonblockingAfterConnect]) { /* mark socket as non-blocking */ NGAddDescriptorFlag(self->fd, O_NONBLOCK); NSAssert((NGGetDescriptorFlags(self->fd) & O_NONBLOCK), @"could not enable non-blocking mode .."); } return YES; } - (BOOL)connectToAddress:(id)_address { // throws // NGSocketAlreadyConnectedException if the socket is already connected // NGInvalidSocketDomainException if the remote domain != local domain // NGCouldNotCreateSocketException if the socket creation failed if ([self isConnected]) { [[[NGSocketAlreadyConnectedException alloc] initWithReason:@"Could not connected: socket is already connected" socket:self] raise]; return NO; } // check whether the remote address is in the same domain like the bound one if (flags.isBound) { if (![[localAddress domain] isEqual:[_address domain]]) { [[[NGInvalidSocketDomainException alloc] initWithReason:@"local and remote socket domains are different" socket:self domain:[_address domain]] raise]; return NO; } } // connect, remote-address is non-nil if this returns if (![self primaryConnectToAddress:_address]) return NO; // if the socket wasn't bound before (normal case), bind it now if (!flags.isBound) if (![self kernelBoundAddress]) return NO; return YES; } - (void)_shutdownDuringOperation { [self shutdown]; } - (BOOL)shutdown { if (self->fd != NGInvalidSocketDescriptor) { if (self->mode != NGStreamMode_undefined) { if (shutdown(self->fd, SHUT_RDWR) == 0) self->mode = NGStreamMode_undefined; } if (self->flags.closeOnFree) { #if defined(WIN32) && !defined(__CYGWIN32__) if (closesocket(self->fd) == 0) { #else if (close(self->fd) == 0) { #endif self->fd = NGInvalidSocketDescriptor; } else { NSLog(@"ERROR(%s): close of socket %@ (fd=%i) alive=%s failed: %s", __PRETTY_FUNCTION__, self, self->fd, [self isAlive] ? "YES" : "NO", strerror(errno)); } } else { self->fd = NGInvalidSocketDescriptor; } ASSIGN(self->remoteAddress, (id)nil); } return YES; } - (BOOL)shutdownSendChannel { if (NGCanWriteInStreamMode(self->mode)) { shutdown(self->fd, SHUT_WR); if (self->mode == NGStreamMode_readWrite) self->mode = NGStreamMode_readOnly; else { self->mode = NGStreamMode_undefined; if (self->flags.closeOnFree) { #if defined(WIN32) && !defined(__CYGWIN32__) closesocket(self->fd); #else close(self->fd); #endif } self->fd = NGInvalidSocketDescriptor; } } return YES; } - (BOOL)shutdownReceiveChannel { if (NGCanReadInStreamMode(self->mode)) { shutdown(self->fd, SHUT_RD); if (self->mode == NGStreamMode_readWrite) self->mode = NGStreamMode_writeOnly; else { self->mode = NGStreamMode_undefined; if (self->flags.closeOnFree) { #if defined(WIN32) && !defined(__CYGWIN32__) closesocket(self->fd); #else close(self->fd); #endif } self->fd = NGInvalidSocketDescriptor; } } return YES; } // ******************** accessors ****************** - (id)remoteAddress { return self->remoteAddress; } - (BOOL)isConnected { return (self->remoteAddress != nil); } - (BOOL)isOpen { return [self isConnected]; } - (int)socketType { return SOCK_STREAM; } - (void)disableNagle:(BOOL)_disable { int on; if ([self isConnected]) { on = _disable ? 1 : 0; setsockopt(self->fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); } } - (void)setSendTimeout:(NSTimeInterval)_timeout { struct timeval tv; if ([self isConnected]) { tv.tv_sec = (int) _timeout; tv.tv_usec = 0; setsockopt(self->fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof (struct timeval)); } self->sendTimeout = _timeout; } - (NSTimeInterval)sendTimeout { return self->sendTimeout; } - (void)setReceiveTimeout:(NSTimeInterval)_timeout { struct timeval tv; if ([self isConnected]) { tv.tv_sec = (int) _timeout; tv.tv_usec = 0; setsockopt(self->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof (struct timeval)); } self->receiveTimeout = _timeout; } - (NSTimeInterval)receiveTimeout { return self->receiveTimeout; } - (BOOL)wouldBlockInMode:(NGStreamMode)_mode { short events = 0; if ((![self isConnected]) || (fd == NGInvalidSocketDescriptor)) return NO; if (NGCanReadInStreamMode(_mode)) events |= POLLRDNORM; if (NGCanWriteInStreamMode(_mode)) events |= POLLWRNORM; // timeout of 0 means return immediatly return (NGPollDescriptor([self fileDescriptor], events, 0) == 1 ? NO : YES); } - (int)waitForMode:(NGStreamMode)_mode timeout:(NSTimeInterval)_timeout { short events = 0; if (NGCanReadInStreamMode(_mode)) events |= POLLRDNORM; if (NGCanWriteInStreamMode(_mode)) events |= POLLWRNORM; // timeout of 0 means return immediatly return NGPollDescriptor([self fileDescriptor], events, (int)(_timeout * 1000.0)); } - (unsigned)numberOfAvailableBytesForReading { int len; // need to check whether socket is connected if (self->remoteAddress == nil) { [self raise:@"NGSocketNotConnectedException" reason:@"socket is not connected"]; return NGStreamError; } if (!NGCanReadInStreamMode(self->mode)) { [self raise:@"NGWriteOnlyStreamException"]; return NGStreamError; } #if !defined(WIN32) && !defined(__CYGWIN32__) while (ioctl(self->fd, FIONREAD, &len) == -1) { if (errno == EINTR) continue; [self raise:@"NGSocketException" reason:@"could not get number of available bytes"]; return NGStreamError; } #else // PeekNamedPipe() on Win ... len = 0; #endif return len; } - (BOOL)isAlive { if (self->fd == NGInvalidSocketDescriptor) return NO; /* poll socket for input */ struct pollfd pfd; int ret; pfd.fd = self->fd; pfd.events = POLLIN; while (YES) { ret = poll(&pfd, 1, 0); if (ret >= 0) break; switch (errno) { case EINTR: continue; default: NSLog(@"ERROR(%s) poll(%d) failed: %s", __PRETTY_FUNCTION__, pfd.fd, strerror(errno)); return NO; } } /* Invalid file descriptor, Error or Hangup */ if (pfd.revents & (POLLNVAL|POLLERR|POLLHUP)) { NSLog(@"INFO(%s) poll(): fd=%d revents=0x%04x)", __PRETTY_FUNCTION__, pfd.fd, pfd.revents); return NO; } return YES; } // ******************** NGStream ******************** - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { // throws // NGStreamReadErrorException when the read call failed // NGSocketNotConnectedException when the socket is not connected // NGEndOfStreamException when the end of the stream is reached // NGWriteOnlyStreamException when the receive channel was shutdown NSException *e = nil; if (self->fd == NGInvalidSocketDescriptor) { [self raise:@"NGSocketException" reason:@"NGActiveSocket is not open"]; return NGStreamError; } // need to check whether socket is connected if (self->remoteAddress == nil) { [self raise:@"NGSocketNotConnectedException" reason:@"socket is not connected"]; return NGStreamError; } if (!NGCanReadInStreamMode(self->mode)) { [self raise:@"NGWriteOnlyStreamException"]; return NGStreamError; } if (_len == 0) return 0; { #if defined(WIN32) && !defined(__CYGWIN32__) int readResult; readResult = recv(self->fd, _buf, _len, 0); if (readResult == 0) { [self _shutdownDuringOperation]; [self raise:@"NGSocketShutdownDuringReadException"]; return NGStreamError; } else if (readResult < 0) { int errorCode = WSAGetLastError(); switch (errorCode) { case WSAECONNRESET: e = [[NGSocketConnectionResetException alloc] initWithStream:self]; break; case WSAETIMEDOUT: e = [[NGSocketTimedOutException alloc] initWithStream:self]; break; case WSAEWOULDBLOCK: NSLog(@"WARNING: descriptor would block .."); default: e = [[NGStreamReadErrorException alloc] initWithStream:self errorCode:errorCode]; break; } if (e) { [self setLastException:e]; [e release]; return NGStreamError; } } #else /* !WIN32 */ int readResult; NSAssert(_buf, @"invalid buffer"); NSAssert1(_len > 0, @"invalid length: %i", _len); retry: readResult = NGDescriptorRecv(self->fd, _buf, _len, 0, (self->receiveTimeout == 0.0) ? -1 // block until data : (int)(self->receiveTimeout * 1000.0)); #if DEBUG if ((readResult < 0) && (errno == EINVAL)) { NSLog(@"%s: invalid argument in NGDescriptorRecv(%i, 0x%p, %i, %i)", __PRETTY_FUNCTION__, self->fd, _buf, _len, 0); } #endif if (readResult == 0) { [self _shutdownDuringOperation]; [self raise:@"NGSocketShutdownDuringReadException"]; return NGStreamError; } else if (readResult == -2) { [self raise:@"NGSocketTimedOutException"]; return NGStreamError; } else if (readResult < 0) { int errorCode = errno; e = nil; switch (errorCode) { case 0: #if DEBUG /* this happens with the Oracle7 adaptor !!! */ NSLog(@"WARNING(%s): readResult<0 (%i), but errno=0 - retry", __PRETTY_FUNCTION__, readResult); #endif goto retry; break; case ECONNRESET: e = [[NGSocketConnectionResetException alloc] initWithStream:self]; break; case ETIMEDOUT: e = [[NGSocketTimedOutException alloc] initWithStream:self]; break; case EWOULDBLOCK: NSLog(@"WARNING: descriptor would block .."); default: e = [[NGStreamReadErrorException alloc] initWithStream:self errorCode:errorCode]; break; } if (e) { [self setLastException:e]; [e release]; return NGStreamError; } } #endif /* !WIN32 */ return readResult; } } #if defined(WIN32) && !defined(__CYGWIN32__) #warning fix exception handling - (unsigned)_winWriteBytes:(const void *)_buf count:(unsigned)_len { NSException *e = nil; int writeResult; writeResult = send(self->fd, _buf, _len, 0); if (writeResult == 0) { [self _shutdownDuringOperation]; [self raise:@"NGSocketShutdownDuringWriteException"]; return NGStreamError; } else if (writeResult < 0) { int errorCode = WSAGetLastError(); switch (errorCode) { case WSAECONNRESET: e = [[NGSocketConnectionResetException alloc] initWithStream:self]; break; case WSAETIMEDOUT: e = [[NGSocketTimedOutException alloc] initWithStream:self]; break; case WSAEWOULDBLOCK: NSLog(@"WARNING: descriptor would block .."); default: e = [[NGStreamWriteErrorException alloc] initWithStream:self errorCode:errno]; break; } if (e) { [self setLastException:e]; [e release]; return NGStreamError; } } return writeResult; } #else - (unsigned)_unixWriteBytes:(const void *)_buf count:(unsigned)_len { int writeResult; int timeOut; int retryCount; retryCount = 0; timeOut = (self->sendTimeout == 0.0) ? -1 // block until data : (int)(self->sendTimeout * 1000.0); wretry: writeResult = NGDescriptorSend(self->fd, _buf, _len, MSG_NOSIGNAL, timeOut); if (writeResult == 0) { [self _shutdownDuringOperation]; [self raise:@"NGSocketShutdownDuringWriteException"]; return NGStreamError; } else if (writeResult == -2) { [self raise:@"NGSocketTimedOutException"]; return NGStreamError; } else if (writeResult < 0) { int errorCode = errno; switch (errorCode) { case 0: #if DEBUG /* this happens with the Oracle7 (on SuSE < 7.1??) adaptor !!! */ NSLog(@"WARNING(%s): writeResult<0 (%i), but errno=0 - retry", __PRETTY_FUNCTION__, writeResult); #endif retryCount++; if (retryCount > 200000) { NSLog(@"WARNING(%s): writeResult<0 (%i), but errno=0 - cancel retry " @"(already tried %i times !!!)", __PRETTY_FUNCTION__, writeResult, retryCount); [self _shutdownDuringOperation]; [self raise:@"NGSocketShutdownDuringWriteException"]; return NGStreamError; break; } sleep(retryCount); goto wretry; break; case ECONNRESET: [self raise:@"NGSocketConnectionResetException"]; return NGStreamError; case ETIMEDOUT: [self raise:@"NGSocketTimedOutException"]; return NGStreamError; case EPIPE: [self _shutdownDuringOperation]; [self raise:@"NGSocketShutdownDuringWriteException"]; return NGStreamError; case EWOULDBLOCK: NSLog(@"WARNING: descriptor would block .."); default: { NSException *e; e = [[NGStreamWriteErrorException alloc] initWithStream:self errorCode:errno]; [self setLastException:e]; [e release]; return NGStreamError; } } } return writeResult; } #endif - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len { // throws // NGStreamWriteErrorException when the write call failed // NGSocketNotConnectedException when the socket is not connected // NGReadOnlyStreamException when the send channel was shutdown if (_len == NGStreamError) { NSLog(@"ERROR(%s): got NGStreamError passed in as length ...", __PRETTY_FUNCTION__); return NGStreamError; } #if DEBUG if (_len > (1024 * 1024 * 100 /* 100MB */)) { NSLog(@"WARNING(%s): got passed in length %uMB (%u bytes, errcode=%u) ...", __PRETTY_FUNCTION__, (_len / 1024 / 1024), _len, NGStreamError); } #endif if (self->fd == NGInvalidSocketDescriptor) { [self raise:@"NGSocketException" reason:@"NGActiveSocket is not open"]; return NGStreamError; } // need to check whether socket is connected if (self->remoteAddress == nil) { [self raise:@"NGSocketNotConnectedException" reason:@"socket is not connected"]; return NGStreamError; } if (!NGCanWriteInStreamMode(self->mode)) { [self raise:@"NGReadOnlyStreamException"]; return NGStreamError; } //NSLog(@"writeBytes: count:%u", _len); #if defined(WIN32) && !defined(__CYGWIN32__) return [self _winWriteBytes:_buf count:_len]; #else return [self _unixWriteBytes:_buf count:_len]; #endif } - (BOOL)flush { return YES; } #if 0 - (BOOL)close { return [self shutdown]; } #endif - (NGStreamMode)mode { return self->mode; } /* methods method which write exactly _len bytes or fail */ - (BOOL)safeReadBytes:(void *)_buf count:(unsigned)_len { volatile int toBeRead; int readResult; void *pos; unsigned (*readBytes)(id, SEL, void *, unsigned); *(&readBytes) = (void *)[self methodForSelector:@selector(readBytes:count:)]; *(&toBeRead) = _len; *(&readResult) = 0; *(&pos) = _buf; while (YES) { *(&readResult) = readBytes(self, @selector(readBytes:count:), pos, toBeRead); if (readResult == NGStreamError) { NSException *localException; NSData *data; data = [NSData dataWithBytes:_buf length:(_len - toBeRead)]; localException = [[NGEndOfStreamException alloc] initWithStream:self readCount:(_len - toBeRead) safeCount:_len data:data]; [self setLastException:localException]; RELEASE(localException); } NSAssert(readResult != 0, @"ERROR: readBytes may not return '0' .."); if (readResult == toBeRead || ![self isOpen]) { // all bytes were read successfully or socket, return break; } if (readResult < 1) { [NSException raise:NSInternalInconsistencyException format:@"readBytes:count: returned a value < 1"]; } toBeRead -= readResult; pos += readResult; } return YES; } - (BOOL)safeWriteBytes:(const void *)_buf count:(unsigned)_len { int toBeWritten = _len; int writeResult; void *pos = (void *)_buf; /* method cache (THREAD, reentrant) */ static Class lastClass = Nil; static int (*writeBytes)(id,SEL,const void*,unsigned) = NULL; if (lastClass == *(Class *)self) { if (writeBytes == NULL) writeBytes = (void *)[self methodForSelector:@selector(writeBytes:count:)]; } else { lastClass = *(Class *)self; writeBytes = (void *)[self methodForSelector:@selector(writeBytes:count:)]; } while (YES) { writeResult = (int)writeBytes(self, @selector(writeBytes:count:), pos, toBeWritten); if (writeResult == NGStreamError) { /* remember number of written bytes ??? */ return NO; } else if (writeResult == toBeWritten) { // all bytes were written successfully, return break; } if (writeResult < 1) { [NSException raise:NSInternalInconsistencyException format:@"writeBytes:count: returned a value < 1 in stream %@", self]; return NO; } toBeWritten -= writeResult; pos += writeResult; } return YES; } - (BOOL)mark { return NO; } - (BOOL)rewind { [self raise:@"NGStreamException" reason:@"stream doesn't support a mark"]; return NO; } - (BOOL)markSupported { return NO; } // convenience methods - (int)readByte { // java semantics (-1 returned on EOF) int result; unsigned char c; result = [self readBytes:&c count:sizeof(unsigned char)]; if (result != 1) { static Class EOFExcClass = Nil; if (EOFExcClass == Nil) EOFExcClass = [NGEndOfStreamException class]; if ([[self lastException] isKindOfClass:EOFExcClass]) [self resetLastException]; return -1; } return (int)c; } /* description */ - (NSString *)modeDescription { NSString *result = @""; switch ([self mode]) { case NGStreamMode_undefined: result = @""; break; case NGStreamMode_readOnly: result = @"r"; break; case NGStreamMode_writeOnly: result = @"w"; break; case NGStreamMode_readWrite: result = @"rw"; break; default: [[[NGUnknownStreamModeException alloc] initWithStream:self] raise]; break; } return result; } - (NSString *)description { NSMutableString *d = [NSMutableString stringWithCapacity:64]; [d appendFormat:@"<%@[0x%p]: mode=%@ address=%@", NSStringFromClass([self class]), self, [self modeDescription], [self localAddress]]; if ([self isConnected]) [d appendFormat:@" connectedTo=%@", [self remoteAddress]]; if ([self sendTimeout] != 0.0) [d appendFormat:@" send-timeout=%4.3fs", [self sendTimeout]]; if ([self receiveTimeout] != 0.0) [d appendFormat:@" receive-timeout=%4.3fs", [self receiveTimeout]]; [d appendString:@">"]; return d; } @end /* NGActiveSocket */ @implementation NGActiveSocket(DataMethods) - (NSData *)readDataOfLength:(unsigned int)_length { unsigned readCount; char buf[_length]; if (_length == 0) return [NSData data]; readCount = [self readBytes:buf count:_length]; return [NSData dataWithBytes:buf length:readCount]; } - (NSData *)safeReadDataOfLength:(unsigned int)_length { char buf[_length]; if (_length == 0) return [NSData data]; [self safeReadBytes:buf count:_length]; return [NSData dataWithBytes:buf length:_length]; } - (unsigned int)writeData:(NSData *)_data { return [self writeBytes:[_data bytes] count:[_data length]]; } - (BOOL)safeWriteData:(NSData *)_data { return [self safeWriteBytes:[_data bytes] count:[_data length]]; } @end /* NGActiveSocket(DataMethods) */ #include @implementation NGBufferedStream(FastSocketForwarders) - (BOOL)isConnected { return [(id)self->source isConnected]; } - (int)fileDescriptor { return [(NSFileHandle *)self->source fileDescriptor]; } @end /* NGBufferedStream(FastSocketForwarders) */ SOPE/sope-core/NGStreams/DESIGN0000644000000000000000000000045515004363604014762 0ustar rootrootDESIGN ====== This library was roughly designed after the Java IO package. Additionally it fully supports Unix socket abstractions (domains, addresses and sockets). Some ObjC design decisions: - do not throw exceptions (but keep them in -lastException) - use protocols - support streaming operation SOPE/sope-core/umbrella.make0000644000000000000000000000162015004363604014660 0ustar rootroot# build umbrella framework for this subproject ifeq ($(frameworks),yes) FRAMEWORK_NAME = sope-core sope-core_C_FILES = dummy.c sope-core_UMBRELLA_FRAMEWORKS = \ SaxObjC DOM \ EOControl \ EOCoreData \ NGExtensions \ NGStreams \ sope-core_PREBIND_ADDR = # TODO # generic (consolidate in gstep-make) $(FRAMEWORK_NAME)_LDFLAGS += \ $(foreach fwname,$($(FRAMEWORK_NAME)_UMBRELLA_FRAMEWORKS),\ -framework $(fwname)) \ $(foreach fwname,$($(FRAMEWORK_NAME)_UMBRELLA_FRAMEWORKS),\ -sub_umbrella $(fwname)) \ -headerpad_max_install_names ifneq ($($(FRAMEWORK_NAME)_PREBIND_ADDR),) $(FRAMEWORK_NAME)_LDFLAGS += -seg1addr $($(FRAMEWORK_NAME)_PREBIND_ADDR) endif # library/framework search pathes DEP_DIRS += \ EOControl EOCoreData NGExtensions NGStreams \ ../sope-xml/SaxObjC ../sope-xml/DOM ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir)) endif SOPE/sope-core/COPYRIGHT0000644000000000000000000000010515004363604013506 0ustar rootrootCopyright (C) 2000-2005 SKYRIX Software AG Contact: info@skyrix.com SOPE/sope-core/README-OSX.txt0000644000000000000000000000053315004363604014365 0ustar rootrootPlease refer to ../README-OSX.txt for compilation directives. Building Notes ============== Prerequisites: - sope-xml Prebinding Notes (DEPRECATED, for reference only) ================================================= sope-core: 0xC1000000 - 0xC2FFFFFF 0xC1000000 EOControl 0xC1200000 NGExtensions 0xC1400000 NGStreams 0xC2E00000 EOCoreData SOPE/sope-core/common.make0000644000000000000000000000111115004363604014340 0ustar rootroot# GNUstep makefile SKYROOT=.. include $(GNUSTEP_MAKEFILES)/common.make include $(SKYROOT)/Version -include ./Version ADDITIONAL_CPPFLAGS += -pipe -Wall -Wno-protocol ifeq ($(reentrant),yes) ADDITIONAL_CPPFLAGS += -D_REENTRANT=1 endif ADDITIONAL_INCLUDE_DIRS += \ -I.. -I../NGStreams/ \ -I../../sope-xml ADDITIONAL_LIB_DIRS += \ -L./$(GNUSTEP_OBJ_DIR) \ -L../../sope-xml/SaxObjC/$(GNUSTEP_OBJ_DIR) \ -L../../sope-xml/DOM/$(GNUSTEP_OBJ_DIR) \ -L../../sope-xml/XmlRpc/$(GNUSTEP_OBJ_DIR) ifeq ($(FOUNDATION_LIB),nx) ADDITIONAL_LDFLAGS += -framework Foundation endif SOPE/sope-core/EOControl/0000755000000000000000000000000015004363604014063 5ustar rootrootSOPE/sope-core/EOControl/EOSQLParser.m0000644000000000000000000005063215004363604016307 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOSQLParser.h" #include "EOQualifier.h" #include "EOFetchSpecification.h" #include "EOSortOrdering.h" #include "EOClassDescription.h" #include "common.h" // TODO: better error output @interface EOSQLParser(Logging) /* this is available in NGExtensions */ - (void)logWithFormat:(NSString *)_fmt,...; @end @implementation EOSQLParser + (id)sharedSQLParser { static EOSQLParser *sharedParser = nil; // THREAD if (sharedParser == nil) sharedParser = [[EOSQLParser alloc] init]; return sharedParser; } - (void)dealloc { [super dealloc]; } /* top level parsers */ - (EOFetchSpecification *)parseSQLSelectStatement:(NSString *)_sql { EOFetchSpecification *fs; unichar *us, *pos; unsigned len, remainingLen; if ((len = [_sql length]) == 0) return nil; us = calloc(len + 10, sizeof(unichar)); [_sql getCharacters:us]; us[len] = 0; pos = us; remainingLen = len; if (![self parseSQL:&fs from:&pos length:&remainingLen strict:NO]) [self logWithFormat:@"parsing of SQL failed."]; free(us); return [fs autorelease]; } - (EOQualifier *)parseSQLWhereExpression:(NSString *)_sql { // TODO: process %=>* and %%, and $ unichar *buf; unsigned i, len; BOOL didReplace; if ((len = [_sql length]) == 0) return nil; // TODO: improve, real parsing in qualifier parser ! buf = calloc(len + 3, sizeof(unichar)); NSAssert(buf, @"could not allocate char buffer"); [_sql getCharacters:buf]; for (i = 0, didReplace = NO; i < len; i++) { if (buf[i] != '%') { if (buf[i] == '*') { NSLog(@"WARNING(%s): SQL string contains a '*': %@", __PRETTY_FUNCTION__, _sql); } continue; } buf[i] = '%'; didReplace = YES; } if (didReplace) _sql = [NSString stringWithCharacters:buf length:len]; if (buf) free(buf); return [EOQualifier qualifierWithQualifierFormat:_sql]; } /* parsing parts (exported for overloading in subclasses) */ static inline BOOL uniIsCEq(unichar *haystack, const unsigned char *needle, unsigned len) { register unsigned idx; for (idx = 0; idx < len; idx++) { if (*needle == '\0') return YES; if (toupper(haystack[idx]) != needle[idx]) return NO; } return YES; } static inline void skipSpaces(unichar **pos, unsigned *len) { while (*len > 0) { if (!isspace(*pos[0])) return; (*len)--; (*pos)++; } } static void printUniStr(unichar *pos, unsigned len) __attribute__((unused)); static void printUniStr(unichar *pos, unsigned len) { unsigned i; for (i = 0; i < len && i < 80; i++) putchar(pos[i]); putchar('\n'); } static inline BOOL isTokStopChar(unichar c) { switch (c) { case 0: case ')': case '(': case '"': case '\'': return YES; default: if (isspace(c)) return YES; return NO; } } - (BOOL)parseToken:(const unsigned char *)tk from:(unichar **)pos length:(unsigned *)len consume:(BOOL)consume { /* ...[space] (strlen(tk)+1 chars) */ unichar *scur; unsigned slen, tlen; tlen = strlen((const char *)tk); scur=*pos; slen=*len; // begin transaction skipSpaces(&scur, &slen); if (slen < tlen) return NO; if (toupper(scur[0]) != tk[0]) return NO; if (tlen < slen) { /* if tok is not at the end */ if (!isTokStopChar(scur[tlen])) return NO; /* not followed by a token stopper */ } if (!uniIsCEq(scur, tk, tlen)) return NO; scur+=tlen; slen-=tlen; if (consume) { *pos = scur; *len = slen; } // end tx return YES; } - (BOOL)parseIdentifier:(NSString **)result from:(unichar **)pos length:(unsigned *)len consume:(BOOL)consume { /* "attr" or attr (at least 1 char or 2 for ") */ unichar *scur; unsigned slen; if (result) *result = nil; scur=*pos; slen=*len; // begin transaction skipSpaces(&scur, &slen); if (*scur == '"') { /* quoted attr */ unichar *start; //printf("try quoted attr\n"); if (slen < 2) return NO; scur++; slen--; /* skip quote */ if (*scur == '"') { /* empty name */ scur++; slen--; if (consume) { *pos = scur; *len = slen; } // end transaction *result = @""; //printf("is empty quoted\n"); return YES; } if (slen < 2) return NO; start = scur; while ((slen > 0) && (*scur != '"')) { if (*scur == '\\' && (slen > 1)) { /* quoted char */ scur++; slen--; // skip one more (still needs to be filtered in result } scur++; slen--; } if (slen > 0) { scur++; slen--; } /* skip quote */ // TODO: xhandle contained quoted chars ? *result = [[NSString alloc] initWithCharacters:start length:(scur-start-1)]; //NSLog(@"found qattr: %@", *result); } else { /* non-quoted attr */ unichar *start; if (slen < 1) return NO; if ([self parseToken:(const unsigned char *)"FROM" from:&scur length:&slen consume:NO]) { /* not an attribute, the from starts ... */ // printf("rejected unquoted attr, is a FROM\n"); return NO; } if ([self parseToken:(const unsigned char *)"WHERE" from:&scur length:&slen consume:NO]) { /* not an attribute, the where starts ... */ // printf("rejected unquoted attr, is a WHERE\n"); return NO; } start = scur; while ((slen > 0) && !isspace(*scur) && (*scur != ',')) { slen--; scur++; } *result = [[NSString alloc] initWithCharacters:start length:(scur-start)]; //NSLog(@"found attr: %@ (len=%i)", *result, (scur-start)); } if (consume && result) { *pos = scur; *len = slen; } // end transaction return *result ? YES : NO; } - (BOOL)parseColumnName:(NSString **)result from:(unichar **)pos length:(unsigned *)len consume:(BOOL)consume { return [self parseIdentifier:result from:pos length:len consume:consume]; } - (BOOL)parseTableName:(NSString **)result from:(unichar **)pos length:(unsigned *)len consume:(BOOL)consume { return [self parseIdentifier:result from:pos length:len consume:consume]; } - (BOOL)parseIdentifierList:(NSArray **)result from:(unichar **)pos length:(unsigned *)len selector:(SEL)_sel { /* attr[,attr] */ NSMutableArray *attrs = nil; unichar *scur; unsigned slen; id attr; BOOL (*parser)(id, SEL, NSString **, unichar **, unsigned *, BOOL); if (result) *result = nil; scur=*pos; slen=*len; // begin transaction skipSpaces(&scur, &slen); parser = (void *)[self methodForSelector:_sel]; if (slen < 1) return NO; // not enough chars if (*scur == '*') { /* a wildcard list, return 'nil' as result */ //printf("try wildcard\n"); scur++; slen--; // skip '*' if (!(slen == 0 || isspace(*scur))) { /* not followed by space or at end */ return NO; } *pos = scur; *len = slen; // end transaction *result = nil; return YES; } if (!parser(self, _sel, &attr,&scur,&slen,YES)) /* well, we need at least one attribute to make it a list */ return NO; attrs = [[NSMutableArray alloc] initWithCapacity:32]; [attrs addObject:attr]; [attr release]; /* all the remaining attributes must be prefixed with a "," */ while (slen > 1) { //printf("try next list attr comma\n"); skipSpaces(&scur, &slen); if (slen < 2) break; if (*scur != ',') break; scur++; slen--; // skip ',' //printf("try next list attr\n"); if (!parser(self, _sel, &attr,&scur,&slen,YES)) break; [attrs addObject:attr]; [attr release]; } *pos = scur; *len = slen; // end transaction *result = attrs; return YES; } - (BOOL)parseContainsQualifier:(EOQualifier **)q_ from:(unichar **)pos length:(unsigned *)len { /* contains('"hh@"') [12+ chars] */ unichar *scur; unsigned slen; NSString *s; if (q_) *q_ = nil; skipSpaces(&scur, &slen); if (slen < 12) return NO; // not enough chars if (![self parseToken:(const unsigned char *)"CONTAINS" from:pos length:len consume:YES]) return NO; skipSpaces(&scur, &slen); [self parseToken:(const unsigned char *)"('" from:&scur length:&slen consume:YES]; if (![self parseIdentifier:&s from:&scur length:&slen consume:YES]) return NO; skipSpaces(&scur, &slen); [self parseToken:(const unsigned char *)"')" from:&scur length:&slen consume:YES]; *q_ = [[EOQualifier qualifierWithQualifierFormat: @"contentAsString doesContain: %@", s] retain]; if (*q_) { *pos = scur; *len = slen; // end transaction return YES; } else return NO; } - (BOOL)parseQualifier:(EOQualifier **)result from:(unichar **)pos length:(unsigned *)len { unichar *scur; unsigned slen; if (result) *result = nil; scur=*pos; slen=*len; // begin transaction skipSpaces(&scur, &slen); if (slen < 3) return NO; // not enough chars // for now should scan till we find either ORDER BY order GROUP BY { unichar *start = scur; while (slen > 0) { if (*scur == 'O' || *scur == 'o') { if ([self parseToken:(const unsigned char *)"ORDER" from:&scur length:&slen consume:NO]) { //printf("FOUND ORDER TOKEN ...\n"); break; } } else if (*scur == 'G' || *scur == 'g') { if ([self parseToken:(const unsigned char *)"GROUP" from:&scur length:&slen consume:NO]) { //printf("FOUND GROUP TOKEN ...\n"); break; } } scur++; slen--; } { EOQualifier *q; NSString *s; s = [[NSString alloc] initWithCharacters:start length:(scur-start)]; if ([s length] == 0) { [s release]; return NO; } if ((q = [self parseSQLWhereExpression:s]) == nil) { [s release]; return NO; } *result = [q retain]; [s release]; } } *pos = scur; *len = slen; // end transaction return YES; } - (BOOL)parseScope:(NSString **)_scope :(NSString **)_entity from:(unichar **)pos length:(unsigned *)len { /* "('shallow traversal of "..."')" "('hierarchical traversal of "..."')" */ unichar *scur; unsigned slen; NSString *entityName; BOOL isShallow = NO; // BOOL isDeep = NO; if (_scope) *_scope = nil; if (_entity) *_entity = nil; scur=*pos; slen=*len; // begin transaction skipSpaces(&scur, &slen); if (slen < 14) return NO; // not enough chars if (*scur != '(') return NO; // does not start with '(' scur++; slen--; // skip '(' skipSpaces(&scur, &slen); if (*scur != '\'') return NO; // does not start with '('' scur++; slen--; // skip single quote /* next the depth */ if ([self parseToken:(const unsigned char *)"SHALLOW" from:&scur length:&slen consume:YES]) isShallow = YES; else if ([self parseToken:(const unsigned char *)"HIERARCHICAL" from:&scur length:&slen consume:YES]) ; // isDeep = YES; else if ([self parseToken:(const unsigned char *)"DEEP" from:&scur length:&slen consume:YES]) ; // isDeep = YES; else /* unknown traveral key */ return NO; /* some syntactic sugar (not strict about that ...) */ [self parseToken:(const unsigned char *)"TRAVERSAL" from:&scur length:&slen consume:YES]; [self parseToken:(const unsigned char *)"OF" from:&scur length:&slen consume:YES]; if (slen < 1) return NO; // not enough chars /* now the entity */ skipSpaces(&scur, &slen); if (![self parseTableName:&entityName from:&scur length:&slen consume:YES]) return NO; // failed to parse entity from scope /* trailer */ skipSpaces(&scur, &slen); if (slen > 0 && *scur == '\'') { scur++; slen--; // skip single quote } skipSpaces(&scur, &slen); if (slen > 0 && *scur == ')') { scur++; slen--; // skip ')' } if (_scope) *_scope = isShallow ? @"flat" : @"deep"; if (_entity) *_entity = entityName; *pos = scur; *len = slen; // end transaction return YES; } - (BOOL)parseSELECT:(EOFetchSpecification **)result from:(unichar **)pos length:(unsigned *)len strict:(BOOL)beStrict { EOFetchSpecification *fs; NSMutableDictionary *lHints; NSString *scope = nil; NSArray *attrs = nil; NSArray *fromList = nil; NSArray *orderList = nil; NSArray *lSortOrderings = nil; EOQualifier *q = nil; BOOL hasSelect = NO; BOOL hasFrom = NO; BOOL missingByOfOrder = NO; *result = nil; if (![self parseToken:(const unsigned char *)"SELECT" from:pos length:len consume:YES]) { /* must begin with SELECT */ if (beStrict) return NO; } else hasSelect = YES; if (![self parseIdentifierList:&attrs from:pos length:len selector:@selector(parseColumnName:from:length:consume:)]) { [self logWithFormat:@"missing ID list .."]; return NO; } //[self debugWithFormat:@"parsed attrs (%i): %@", [attrs count], attrs]; /* now a from is expected */ if ([self parseToken:(const unsigned char *)"FROM" from:pos length:len consume:YES]) hasFrom = YES; else { if (beStrict) return NO; } /* check whether it's followed by a scope */ if ([self parseToken:(const unsigned char *)"SCOPE" from:pos length:len consume:YES]) { NSString *scopeEntity = nil; if (![self parseScope:&scope:&scopeEntity from:pos length:len]) { if (beStrict) return NO; } #if DEBUG_PARSING else [self logWithFormat:@"FOUND SCOPE: '%@'", scope]; #endif if (scopeEntity) fromList = [[NSArray alloc] initWithObjects:scopeEntity, nil]; [scopeEntity release]; } else { if (![self parseIdentifierList:&fromList from:pos length:len selector:@selector(parseTableName:from:length:consume:)]) { [self logWithFormat:@"missing from list .."]; return NO; } #if DEBUG_PARSING [self logWithFormat:@"parsed FROM list (%i): %@", [fromList count], fromList]; #endif } /* check where */ if ([self parseToken:(const unsigned char *)"WHERE" from:pos length:len consume:YES]) { /* parse qualifier ... */ if ([self parseToken:(const unsigned char *)"CONTAINS" from:pos length:len consume:NO]) { if (![self parseContainsQualifier:&q from:pos length:len]) { if (beStrict) return NO; } } else if (![self parseQualifier:&q from:pos length:len]) { if (beStrict) return NO; } #if DEBUG_PARSING [self logWithFormat:@"FOUND Qualifier: '%@'", q]; #endif } /* check order-by */ if ([self parseToken:(const unsigned char *)"ORDER" from:pos length:len consume:YES]) { if (![self parseToken:(const unsigned char *)"BY" from:pos length:len consume:YES]) { if (beStrict) return NO; missingByOfOrder = YES; } if (![self parseIdentifierList:&orderList from:pos length:len selector:@selector(parseColumnName:from:length:consume:)]) return NO; #if DEBUG_PARSING [self logWithFormat:@"parsed ORDER list (%i): %@", [orderList count], orderList]; #endif } /* check group-by */ if ([self parseToken:(const unsigned char *)"GROUP" from:pos length:len consume:YES]) { if (![self parseToken:(const unsigned char *)"BY" from:pos length:len consume:YES]) { if (beStrict) return NO; } } //printUniStr(*pos, *len); // DEBUG if (!hasSelect) [self logWithFormat:@"missing SELECT !"]; if (!hasFrom) [self logWithFormat:@"missing FROM !"]; if (missingByOfOrder) [self logWithFormat:@"missing BY in ORDER BY !"]; /* build fetchspec */ lHints = [[NSMutableDictionary alloc] initWithCapacity:16]; if (scope) { [lHints setObject:scope forKey:@"scope"]; [scope release]; scope = nil; } if (attrs) { [lHints setObject:attrs forKey:@"attributes"]; [attrs release]; attrs = nil; } if (orderList) { NSMutableArray *ma; unsigned len; len = [orderList count]; ma = [[NSMutableArray alloc] initWithCapacity:len]; // for (i = 0; i < len; i++) { // EOSortOrdering *so; // so = [EOSortOrdering sortOrderingWithKey:[orderList objectAtIndex:i] // selector:EOCompareAscending]; // } lSortOrderings = [ma shallowCopy]; [ma release]; [orderList release]; orderList = nil; } fs = [[EOFetchSpecification alloc] initWithEntityName:[fromList componentsJoinedByString:@","] qualifier:q sortOrderings:lSortOrderings usesDistinct:NO isDeep:NO hints:lHints]; [lHints release]; [q release]; [fromList release]; *result = fs; return fs ? YES : NO; } - (BOOL)parseSQL:(id *)result from:(unichar **)pos length:(unsigned *)len strict:(BOOL)beStrict { if (*len < 1) return NO; if ([self parseToken:(const unsigned char *)"SELECT" from:pos length:len consume:NO]) return [self parseSELECT:result from:pos length:len strict:beStrict]; //if ([self parseToken:"UPDATE" from:pos length:len consume:NO]) //if ([self parseToken:"INSERT" from:pos length:len consume:NO]) //if ([self parseToken:"DELETE" from:pos length:len consume:NO]) [self logWithFormat:@"tried to parse an unsupported SQL statement."]; return NO; } @end /* EOSQLParser */ @implementation EOSQLParser(Tests) + (void)testDAVQuery { EOFetchSpecification *fs; NSString *sql; NSLog(@"testing: %@ --------------------", self); sql = @"\n" @"select \n" @" \"http://schemas.microsoft.com/mapi/proptag/x0e230003\", \n" @" \"urn:schemas:mailheader:subject\", \n" @" \"urn:schemas:mailheader:from\",\n" @" \"urn:schemas:mailheader:to\", \n" @" \"urn:schemas:mailheader:cc\", \n" @" \"urn:schemas:httpmail:read\", \n" @" \"urn:schemas:httpmail:hasattachment\", \n" @" \"DAV:getcontentlength\", \n" @" \"urn:schemas:mailheader:date\", \n" @" \"urn:schemas:httpmail:date\", \n" @" \"urn:schemas:mailheader:received\", \n" @" \"urn:schemas:mailheader:message-id\", \n" @" \"urn:schemas:mailheader:in-reply-to\", \n" @" \"urn:schemas:mailheader:references\" \n" @"from \n" @" scope('shallow traversal of \"http://127.0.0.1:9000/o/ol/helge/INBOX\"')\n" @"where \n" @" \"DAV:iscollection\" = False \n" @" and \n" @" \"http://schemas.microsoft.com/mapi/proptag/x0c1e001f\" != 'SMTP'\n" @" and \n" @" \"http://schemas.microsoft.com/mapi/proptag/x0e230003\" > 0 \n" @" \n"; fs = [[self sharedSQLParser] parseSQLSelectStatement:sql]; NSLog(@" FS: %@", fs); if (fs == nil) { NSLog(@" ERROR: could not parse SQL: %@", sql); } else { EOQualifier *q; NSString *scope; NSArray *props; if ((scope = [[fs hints] objectForKey:@"scope"]) == nil) NSLog(@" INVALID: got no scope !"); if (![scope isEqualToString:@"flat"]) NSLog(@" INVALID: got scope %@, expected flat !", scope); #if 0 if ([fs queryWebDAVPropertyNamesOnly]) NSLog(@" INVALID: name query only, but queried several attrs !"); #endif /* check qualifier */ if ((q = [fs qualifier]) == nil) NSLog(@" INVALID: got not qualifier (expected one) !"); else if (![q isKindOfClass:[EOAndQualifier class]]) { NSLog(@" INVALID: expected AND qualifier, got %@ !", NSStringFromClass([q class])); } else if ([[(EOAndQualifier *)q qualifiers] count] != 3) { NSLog(@" INVALID: expected 3 subqualifiers, got %"PRIuPTR" !", [[(EOAndQualifier *)q qualifiers] count]); } /* check sortordering */ if ([fs sortOrderings] != nil) { NSLog(@" INVALID: got sort orderings, specified none: %@ !", [fs sortOrderings]); } /* attributes */ if ((props = [[fs hints] objectForKey:@"attributes"]) == nil) NSLog(@" INVALID: got not attributes (expected some) !"); else if (![props isKindOfClass:[NSArray class]]) { NSLog(@" INVALID: attributes not delivered as array ?: %@", NSStringFromClass([props class])); } else if ([props count] != 14) { NSLog(@" INVALID: invalid attribute count, expected 14, got %"PRIuPTR".", [props count]); } } NSLog(@"done test: %@ ------------------", self); } @end /* EOSQLParser(Tests) */ SOPE/sope-core/EOControl/EOKeyValueCoding.m0000644000000000000000000013315215004363604017343 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOKeyValueCoding.h" #include "EONull.h" #include "common.h" #if GNU_RUNTIME #if __GNU_LIBOBJC__ >= 20100911 # include #else # include # include #endif #endif static EONull *null = nil; #if LIB_FOUNDATION_LIBRARY static id idMethodGetFunc(void* info1, void* info2, id self); static id idIvarGetFunc(void* info1, void* info2, id self); static void idMethodSetFunc(void* info1, void* info2, id self, id val); static void idIvarSetFunc(void* info1, void* info2, id self, id val); static id charMethodGetFunc(void* info1, void* info2, id self); static id charIvarGetFunc(void* info1, void* info2, id self); static void charMethodSetFunc(void* info1, void* info2, id self, id val); static void charIvarSetFunc(void* info1, void* info2, id self, id val); static id unsignedCharMethodGetFunc(void* info1, void* info2, id self); static id unsignedCharIvarGetFunc(void* info1, void* info2, id self); static void unsignedCharMethodSetFunc(void* info1, void* info2, id self, id val); static void unsignedCharIvarSetFunc(void* info1, void* info2, id self, id val); static id shortMethodGetFunc(void* info1, void* info2, id self); static id shortIvarGetFunc(void* info1, void* info2, id self); static void shortMethodSetFunc(void* info1, void* info2, id self, id val); static void shortIvarSetFunc(void* info1, void* info2, id self, id val); static id unsignedShortMethodGetFunc(void* info1, void* info2, id self); static id unsignedShortIvarGetFunc(void* info1, void* info2, id self); static void unsignedShortMethodSetFunc(void* info1, void* info2, id self, id val); static void unsignedShortIvarSetFunc(void* info1, void* info2, id self, id val); static id intMethodGetFunc(void* info1, void* info2, id self); static id intIvarGetFunc(void* info1, void* info2, id self); static void intMethodSetFunc(void* info1, void* info2, id self, id val); static void intIvarSetFunc(void* info1, void* info2, id self, id val); static id unsignedIntMethodGetFunc(void* info1, void* info2, id self); static id unsignedIntIvarGetFunc(void* info1, void* info2, id self); static void unsignedIntMethodSetFunc(void* info1, void* info2, id self, id val); static void unsignedIntIvarSetFunc(void* info1, void* info2, id self, id val); static id longMethodGetFunc(void* info1, void* info2, id self); static id longIvarGetFunc(void* info1, void* info2, id self); static void longMethodSetFunc(void* info1, void* info2, id self, id val); static void longIvarSetFunc(void* info1, void* info2, id self, id val); static id unsignedLongMethodGetFunc(void* info1, void* info2, id self); static id unsignedLongIvarGetFunc(void* info1, void* info2, id self); static void unsignedLongMethodSetFunc(void* info1, void* info2, id self, id val); static void unsignedLongIvarSetFunc(void* info1, void* info2, id self, id val); static id longLongMethodGetFunc(void* info1, void* info2, id self); static id longLongIvarGetFunc(void* info1, void* info2, id self); static void longLongMethodSetFunc(void* info1, void* info2, id self, id val); static void longLongIvarSetFunc(void* info1, void* info2, id self, id val); static id unsignedLongLongMethodGetFunc(void* info1, void* info2, id self); static id unsignedLongLongIvarGetFunc(void* info1, void* info2, id self); static void unsignedLongLongMethodSetFunc(void* info1, void* info2, id self, id val); static void unsignedLongLongIvarSetFunc(void* info1, void* info2, id self, id val); static id floatMethodGetFunc(void* info1, void* info2, id self); static id floatIvarGetFunc(void* info1, void* info2, id self); static void floatMethodSetFunc(void* info1, void* info2, id self, id val); static void floatIvarSetFunc(void* info1, void* info2, id self, id val); static id doubleMethodGetFunc(void* info1, void* info2, id self); static id doubleIvarGetFunc(void* info1, void* info2, id self); static void doubleMethodSetFunc(void* info1, void* info2, id self, id val); static void doubleIvarSetFunc(void* info1, void* info2, id self, id val); static Class NumberClass = Nil; static Class StringClass = Nil; @implementation NSObject(EOKeyValueCoding) /* * Types */ typedef struct _KeyValueMethod { NSString* key; Class class; } KeyValueMethod; typedef struct _GetKeyValueBinding { /* info1, info2, self */ id (*access)(void *, void *, id); void *info1; void *info2; } GetKeyValueBinding; typedef struct _SetKeyValueBinding { /* info1, info2, self, val */ void (*access)(void *, void *, id, id); void *info1; void *info2; } SetKeyValueBinding; /* * Globals */ static NSMapTable* getValueBindings = NULL; static NSMapTable* setValueBindings = NULL; static BOOL keyValueDebug = NO; static BOOL keyValueInit = NO; /* * KeyValueMapping */ static GetKeyValueBinding* newGetBinding(NSString* key, id instance) { GetKeyValueBinding *ret = NULL; void *info1 = NULL; void *info2 = NULL; id (*fptr)(void*, void*, id) = NULL; // Lookup method name [-(type)key] { Class class = [instance class]; unsigned clen = [key cStringLength]; char *cbuf; const char *ckey; SEL sel; struct objc_method* mth; cbuf = malloc(clen + 1); [key getCString:cbuf]; cbuf[clen] = '\0'; ckey = cbuf; sel = sel_registerName(ckey); if (sel && (mth = class_get_instance_method(class, sel)) && method_get_number_of_arguments(mth) == 2) { switch(*objc_skip_type_qualifiers(mth->method_types)) { case _C_ID: fptr = (id (*)(void*, void*, id))idMethodGetFunc; break; case _C_CHR: fptr = (id (*)(void*, void*, id))charMethodGetFunc; break; case _C_UCHR: fptr = (id (*)(void*, void*, id))unsignedCharMethodGetFunc; break; case _C_SHT: fptr = (id (*)(void*, void*, id))shortMethodGetFunc; break; case _C_USHT: fptr = (id (*)(void*, void*, id))unsignedShortMethodGetFunc; break; case _C_INT: fptr = (id (*)(void*, void*, id))intMethodGetFunc; break; case _C_UINT: fptr = (id (*)(void*, void*, id))unsignedIntMethodGetFunc; break; case _C_LNG: fptr = (id (*)(void*, void*, id))longMethodGetFunc; break; case _C_ULNG: fptr = (id (*)(void*, void*, id))unsignedLongMethodGetFunc; break; case 'q': fptr = (id (*)(void*, void*, id))longLongMethodGetFunc; break; case 'Q': fptr = (id (*)(void*, void*, id))unsignedLongLongMethodGetFunc; break; case _C_FLT: fptr = (id (*)(void*, void*, id))floatMethodGetFunc; break; case _C_DBL: fptr = (id (*)(void*, void*, id))doubleMethodGetFunc; break; } if (fptr) { info1 = (void*)(mth->method_imp); info2 = (void*)(mth->method_name); } } if (cbuf != NULL) free(cbuf); } // Lookup ivar name if (fptr == NULL) { Class class = [instance class]; unsigned clen; char *cbuf; const char *ckey; int i; clen = [key cStringLength]; cbuf = malloc(clen + 1); [key getCString:cbuf]; cbuf[clen] = '\0'; ckey = cbuf; while (class != Nil) { for (i = 0; class->ivars && i < class->ivars->ivar_count; i++) { if (!Strcmp(ckey, class->ivars->ivar_list[i].ivar_name)) { switch(*objc_skip_type_qualifiers(class->ivars->ivar_list[i].ivar_type)) { case _C_ID: fptr = (id (*)(void*, void*, id))idIvarGetFunc; break; case _C_CHR: fptr = (id (*)(void*, void*, id))charIvarGetFunc; break; case _C_UCHR: fptr = (id (*)(void*, void*, id))unsignedCharIvarGetFunc; break; case _C_SHT: fptr = (id (*)(void*, void*, id))shortIvarGetFunc; break; case _C_USHT: fptr = (id (*)(void*, void*, id))unsignedShortIvarGetFunc; break; case _C_INT: fptr = (id (*)(void*, void*, id))intIvarGetFunc; break; case _C_UINT: fptr = (id (*)(void*, void*, id))unsignedIntIvarGetFunc; break; case _C_LNG: fptr = (id (*)(void*, void*, id))longIvarGetFunc; break; case _C_ULNG: fptr = (id (*)(void*, void*, id))unsignedLongIvarGetFunc; break; case 'q': fptr = (id (*)(void*, void*, id))longLongIvarGetFunc; break; case 'Q': fptr = (id (*)(void*, void*, id))unsignedLongLongIvarGetFunc; break; case _C_FLT: fptr = (id (*)(void*, void*, id))floatIvarGetFunc; break; case _C_DBL: fptr = (id (*)(void*, void*, id))doubleIvarGetFunc; break; } if (fptr) { info2 = (void *)(unsigned long) (class->ivars->ivar_list[i].ivar_offset); break; } } } class = class->super_class; } if (cbuf != NULL) free(cbuf); } // Make binding and insert into map if (fptr) { KeyValueMethod *mkey; GetKeyValueBinding *bin; mkey = Malloc(sizeof(KeyValueMethod)); bin = Malloc(sizeof(GetKeyValueBinding)); mkey->key = [key copy]; mkey->class = [instance class]; bin->access = fptr; bin->info1 = info1; bin->info2 = info2; NSMapInsert(getValueBindings, mkey, bin); ret = bin; } // If no way to access value warn if (!ret && keyValueDebug) NSLog(@"cannnot get key `%@' for instance of class `%@'", key, NSStringFromClass([instance class])); return ret; } static SetKeyValueBinding* newSetBinding(NSString* key, id instance) { SetKeyValueBinding *ret = NULL; void *info1 = NULL; void *info2 = NULL; void (*fptr)(void*, void*, id, id) = NULL; // Lookup method name [-(void)setKey:(type)arg] { Class class = [instance class]; unsigned clen = [key cStringLength]; char *cbuf; const char *ckey; SEL sel; struct objc_method* mth; char sname[clen + 7]; cbuf = malloc(clen + 1); [key getCString:cbuf]; cbuf[clen] = '\0'; ckey = cbuf; // Make sel from name Strcpy(sname, "set"); Strcat(sname, ckey); Strcat(sname, ":"); sname[3] = islower((int)sname[3]) ? toupper((int)sname[3]) : sname[3]; sel = sel_registerName(sname); if (sel && (mth = class_get_instance_method(class, sel)) && method_get_number_of_arguments(mth) == 3 && *objc_skip_type_qualifiers(mth->method_types) == _C_VOID) { char* argType = (char*)(mth->method_types); argType = (char*)objc_skip_argspec(argType); // skip return argType = (char*)objc_skip_argspec(argType); // skip self argType = (char*)objc_skip_argspec(argType); // skip SEL switch(*objc_skip_type_qualifiers(argType)) { case _C_ID: fptr = (void (*)(void*, void*, id, id))idMethodSetFunc; break; case _C_CHR: fptr = (void (*)(void*, void*, id, id))charMethodSetFunc; break; case _C_UCHR: fptr = (void (*)(void*, void*, id, id))unsignedCharMethodSetFunc; break; case _C_SHT: fptr = (void (*)(void*, void*, id, id))shortMethodSetFunc; break; case _C_USHT: fptr = (void (*)(void*, void*, id, id))unsignedShortMethodSetFunc; break; case _C_INT: fptr = (void (*)(void*, void*, id, id))intMethodSetFunc; break; case _C_UINT: fptr = (void (*)(void*, void*, id, id))unsignedIntMethodSetFunc; break; case _C_LNG: fptr = (void (*)(void*, void*, id, id))longMethodSetFunc; break; case _C_ULNG: fptr = (void (*)(void*, void*, id, id))unsignedLongMethodSetFunc; break; case 'q': fptr = (void (*)(void*, void*, id, id))longLongMethodSetFunc; break; case 'Q': fptr = (void (*)(void*, void*, id, id))unsignedLongLongMethodSetFunc; break; case _C_FLT: fptr = (void (*)(void*, void*, id, id))floatMethodSetFunc; break; case _C_DBL: fptr = (void (*)(void*, void*, id, id))doubleMethodSetFunc; break; } if (fptr) { info1 = (void*)(mth->method_imp); info2 = (void*)(mth->method_name); } } if (cbuf) free(cbuf); } // Lookup ivar name if (!fptr) { Class class = [instance class]; unsigned clen = [key cStringLength]; char *cbuf; const char *ckey; int i; cbuf = malloc(clen + 1); [key getCString:cbuf]; cbuf[clen] = '\0'; ckey = cbuf; while (class) { for (i = 0; class->ivars && i < class->ivars->ivar_count; i++) { if (!Strcmp(ckey, class->ivars->ivar_list[i].ivar_name)) { switch(*objc_skip_type_qualifiers(class->ivars->ivar_list[i].ivar_type)) { case _C_ID: fptr = (void (*)(void*, void*, id, id))idIvarSetFunc; break; case _C_CHR: fptr = (void (*)(void*, void*, id, id))charIvarSetFunc; break; case _C_UCHR: fptr = (void (*)(void*, void*, id, id))unsignedCharIvarSetFunc; break; case _C_SHT: fptr = (void (*)(void*, void*, id, id))shortIvarSetFunc; break; case _C_USHT: fptr = (void (*)(void*, void*, id, id))unsignedShortIvarSetFunc; break; case _C_INT: fptr = (void (*)(void*, void*, id, id))intIvarSetFunc; break; case _C_UINT: fptr = (void (*)(void*, void*, id, id))unsignedIntIvarSetFunc; break; case _C_LNG: fptr = (void (*)(void*, void*, id, id))longIvarSetFunc; break; case _C_ULNG: fptr = (void (*)(void*, void*, id, id))unsignedLongIvarSetFunc; break; case 'q': fptr = (void (*)(void*, void*, id, id))longLongIvarSetFunc; break; case 'Q': fptr = (void (*)(void*, void*, id, id))unsignedLongLongIvarSetFunc; break; case _C_FLT: fptr = (void (*)(void*, void*, id, id))floatIvarSetFunc; break; case _C_DBL: fptr = (void (*)(void*, void*, id, id))doubleIvarSetFunc; break; } if (fptr != NULL) { info2 = (void *)(unsigned long) (class->ivars->ivar_list[i].ivar_offset); break; } } } class = class->super_class; } if (cbuf) free(cbuf); } // Make binding and insert into map if (fptr) { KeyValueMethod *mkey; SetKeyValueBinding *bin; mkey = Malloc(sizeof(KeyValueMethod)); bin = Malloc(sizeof(SetKeyValueBinding)); mkey->key = [key copy]; mkey->class = [instance class]; bin->access = fptr; bin->info1 = info1; bin->info2 = info2; NSMapInsert(setValueBindings, mkey, bin); ret = bin; } // If no way to access value warn if (!ret && keyValueDebug) NSLog(@"cannnot set key `%@' for instance of class `%@'", key, NSStringFromClass([instance class])); return ret; } /* * MapTable initialization */ static unsigned keyValueMapHash(NSMapTable* table, KeyValueMethod* map) { return [map->key hash] + (((unsigned long)(map->class)) >> 4L); } static BOOL keyValueMapCompare(NSMapTable* table, KeyValueMethod* map1, KeyValueMethod* map2) { return (map1->class == map2->class) && [map1->key isEqual:map2->key]; } static void mapRetainNothing(NSMapTable* table, KeyValueMethod* map) { } static void keyValueMapKeyRelease(NSMapTable* table, KeyValueMethod* map) { [map->key release]; Free(map); } static void keyValueMapValRelease(NSMapTable* table, void* map) { Free(map); } static NSString* keyValueMapDescribe(NSMapTable* table, KeyValueMethod* map) { if (StringClass == Nil) StringClass = [NSString class]; return [StringClass stringWithFormat:@"%@:%@", NSStringFromClass(map->class), map->key]; } static NSString* describeBinding(NSMapTable* table, GetKeyValueBinding* bin) { if (StringClass == Nil) StringClass = [NSString class]; return [StringClass stringWithFormat:@"%08x:%08x", bin->info1, bin->info2]; } static NSMapTableKeyCallBacks keyValueKeyCallbacks = { (unsigned(*)(NSMapTable *, const void *))keyValueMapHash, (BOOL(*)(NSMapTable *, const void *, const void *))keyValueMapCompare, (void (*)(NSMapTable *, const void *anObject))mapRetainNothing, (void (*)(NSMapTable *, void *anObject))keyValueMapKeyRelease, (NSString *(*)(NSMapTable *, const void *))keyValueMapDescribe, (const void *)NULL }; const NSMapTableValueCallBacks keyValueValueCallbacks = { (void (*)(NSMapTable *, const void *))mapRetainNothing, (void (*)(NSMapTable *, void *))keyValueMapValRelease, (NSString *(*)(NSMapTable *, const void *))describeBinding }; static void initKeyValueBindings(void) { getValueBindings = NSCreateMapTable(keyValueKeyCallbacks, keyValueValueCallbacks, 31); setValueBindings = NSCreateMapTable(keyValueKeyCallbacks, keyValueValueCallbacks, 31); keyValueInit = YES; } /* * Access Methods */ static inline void removeAllBindings(void) { NSResetMapTable(getValueBindings); NSResetMapTable(setValueBindings); } static inline id getValue(NSString* key, id instance) { KeyValueMethod mkey = { key, [instance class] }; GetKeyValueBinding *bin; id value = nil; if (NumberClass == Nil) NumberClass = [NSNumber class]; // Check Init if (!keyValueInit) initKeyValueBindings(); // Get existing binding bin = (GetKeyValueBinding *)NSMapGet(getValueBindings, &mkey); // Create new binding if (bin == NULL) bin = newGetBinding(key, instance); // Get value if binding is ok if (bin) value = bin->access(bin->info1, bin->info2, instance); return value; } static inline BOOL setValue(NSString* key, id instance, id value) { KeyValueMethod mkey = {key, [instance class]}; SetKeyValueBinding* bin; if (NumberClass == Nil) NumberClass = [NSNumber class]; // Check Init if (!keyValueInit) initKeyValueBindings(); // Get existing binding bin = (SetKeyValueBinding *)NSMapGet(setValueBindings, &mkey); // Create new binding if (bin == NULL) bin = newSetBinding(key, instance); // Get value if binding is ok if (bin) bin->access(bin->info1, bin->info2, instance, value); return (bin != NULL); } + (BOOL)accessInstanceVariablesDirectly { return NO; } - (void)handleTakeValue:(id)_value forUnboundKey:(NSString *)_key { NSDictionary *ui; ui = [NSDictionary dictionaryWithObjectsAndKeys: self, @"EOTargetObjectUserInfoKey", [self class], @"EOTargetObjectClassUserInfoKey", _key, @"EOUnknownUserInfoKey", nil]; [[NSException exceptionWithName:@"EOUnknownKeyException" reason:@"called -takeValue:forKey: with unknown key" userInfo:ui] raise]; } - (id)handleQueryWithUnboundKey:(NSString *)_key { NSDictionary *ui; ui = [NSDictionary dictionaryWithObjectsAndKeys: self, @"EOTargetObjectUserInfoKey", _key, @"EOUnknownUserInfoKey", nil]; [[NSException exceptionWithName:@"EOUnknownKeyException" reason:@"called -valueForKey: with unknown key" userInfo:ui] raise]; return nil; } - (void)unableToSetNullForKey:(NSString *)_key { [NSException raise:@"NSInvalidArgumentException" format: @"EOKeyValueCoding cannot set EONull value for key %@," @"in instance of %@ class.", _key, NSStringFromClass([self class])]; } + (void)flushAllKeyBindings { removeAllBindings(); } - (void)flushKeyBindings { // EOF 1.1 method removeAllBindings(); } - (void)setKeyValueCodingWarnings:(BOOL)aFlag { keyValueDebug = aFlag; } - (void)takeValuesFromDictionary:(NSDictionary *)dictionary { NSEnumerator *keyEnum; id key; if (null == nil) null = [EONull null]; keyEnum = [dictionary keyEnumerator]; while ((key = [keyEnum nextObject])) { id value; value = [dictionary objectForKey:key]; /* automagically convert EONull to nil */ if (value == null) value = nil; [self takeValue:value forKey:key]; #if 0 // this doesn't support overridden methods ... if (!setValue(key, self, value)) { [self handleTakeValue:value forUnboundKey:key]; } #endif } } - (NSDictionary *)valuesForKeys:(NSArray *)keys { static Class NSDictionaryClass = Nil; int n = [keys count]; if (NSDictionaryClass == Nil) NSDictionaryClass = [NSDictionary class]; if (null == nil) null = [EONull null]; if (n == 0) return [NSDictionaryClass dictionary]; else if (n == 1) { NSString *key; id value; key = [keys objectAtIndex:0]; //value = getValue(key, self); value = [self valueForKey:key]; /* automagically convert 'nil' to EONull */ if (value == nil) value = null; return [NSDictionaryClass dictionaryWithObject:value forKey:key]; } else { id newKeys[n]; id newVals[n]; int i; for (i = 0; i < n; i++) { id key; id val; key = [keys objectAtIndex:i]; //val = getValue(key, self); val = [self valueForKey:key]; /* automagically convert 'nil' to EONull */ if (val == nil) val = null; newKeys[i] = key; newVals[i] = val; } return [NSDictionaryClass dictionaryWithObjects:newVals forKeys:newKeys count:n]; } } - (void)takeValue:(id)_value forKey:(NSString *)_key { if (!setValue(_key, self, _value)) { //NSLog(@"ERROR(%s): couldn't take value for key %@", key); [self handleTakeValue:_value forUnboundKey:_key]; } } - (id)valueForKey:(NSString *)key { id val; if ((val = getValue(key, self)) != nil) return val; return nil; } /* stored values */ + (BOOL)useStoredAccessor { return YES; } - (void)takeStoredValue:(id)_value forKey:(NSString *)_key { if ([[self class] useStoredAccessor]) { BOOL ok = YES; /* this should be different */ ok = setValue(_key, self, _value); if (!ok) [self handleTakeValue:_value forUnboundKey:_key]; } else [self takeValue:_value forKey:_key]; } - (id)storedValueForKey:(NSString *)_key { if ([[self class] useStoredAccessor]) { id val; /* this should be different */ if ((val = getValue(_key, self))) return val; /* val = [self handleQueryWithUnboundKey:_key] */ return nil; } else return [self valueForKey:_key]; } @end /* NSObject(EOKeyValueCoding) */ @implementation NSObject(EOKeyPathValueCoding) - (void)takeValue:(id)_value forKeyPath:(NSString *)_keyPath { NSArray *keyPath; unsigned i, count; id target; keyPath = [_keyPath componentsSeparatedByString:@"."]; count = [keyPath count]; if (count < 2) [self takeValue:_value forKey:_keyPath]; else { target = self; for (i = 0; i < (count - 1) ; i++) { if ((target = [target valueForKey:[keyPath objectAtIndex:i]]) == nil) /* nil component */ return; } [target takeValue:_value forKey:[keyPath lastObject]]; } } - (id)valueForKeyPath:(NSString *)_keyPath { #if 1 const unsigned char *buf; unsigned int i, start, len; id value; if ((len = [_keyPath cStringLength]) == 0) return [self valueForKey:_keyPath]; if (StringClass == Nil) StringClass = [NSString class]; value = self; buf = (const unsigned char *)[_keyPath cString]; if (index((const char *)buf, '.') == NULL) /* no point contained .. */ return [self valueForKey:_keyPath]; for (i = start = 0; i < len; i++) { if (buf[i] == '.') { /* found a pt */ NSString *key; key = (start < i) ? [[StringClass alloc] initWithCString:(const char *)&(buf[start]) length:(i - start)] : (id)@""; value = [value valueForKey:key]; [key release]; key = nil; if (value == nil) return nil; start = (i + 1); /* next part is after the pt */ } } /* check last part */ { NSString *key; id v; key = (start < i) ? [[StringClass alloc] initWithCString:(const char *)&(buf[start]) length:(i - start)] : (id)@""; v = [value valueForKey:key]; [key release]; key = nil; return v; } #else /* naive implementation */ NSEnumerator *keyPath; NSString *key; id value; value = self; keyPath = [[_keyPath componentsSeparatedByString:@"."] objectEnumerator]; while ((key = [keyPath nextObject]) && (value != nil)) value = [value valueForKey:key]; return value; #endif } @end /* NSObject(EOKeyPathValueCoding) */ @implementation NSArray(EOKeyValueCoding) - (id)computeSumForKey:(NSString *)_key { unsigned i, cc = [self count]; id (*objAtIdx)(id, SEL, unsigned int); double sum; if (cc == 0) return [NSNumber numberWithDouble:0.0]; objAtIdx = (void*)[self methodForSelector:@selector(objectAtIndex:)]; for (i = 0, sum = 0.0; i < cc; i++) { register id o; o = objAtIdx(self, @selector(objectAtIndex:), i); o = [o valueForKey:_key]; sum += [o doubleValue]; } return [NSNumber numberWithDouble:sum]; } - (id)computeAvgForKey:(NSString *)_key { unsigned cc = [self count]; NSNumber *sum; if (cc == 0) return nil; sum = [self computeSumForKey:_key]; return [NSNumber numberWithDouble:([sum doubleValue] / (double)cc)]; } - (id)computeCountForKey:(NSString *)_key { return [NSNumber numberWithUnsignedInt:[self count]]; } - (id)computeMaxForKey:(NSString *)_key { unsigned i, cc = [self count]; id (*objAtIdx)(id, SEL, unsigned int); double max; if (cc == 0) return nil; objAtIdx = (void *)[self methodForSelector:@selector(objectAtIndex:)]; max = [[objAtIdx(self, @selector(objectAtIndex:), 0) valueForKey:_key] doubleValue]; for (i = 1; i < cc; i++) { register double ov; ov = [[objAtIdx(self, @selector(objectAtIndex:), i) valueForKey:_key] doubleValue]; if (ov > max) max = ov; } return [NSNumber numberWithDouble:max]; } - (id)computeMinForKey:(NSString *)_key { unsigned i, cc = [self count]; id (*objAtIdx)(id, SEL, unsigned int); double min; if (cc == 0) return nil; objAtIdx = (void *)[self methodForSelector:@selector(objectAtIndex:)]; min = [[objAtIdx(self, @selector(objectAtIndex:), 0) valueForKey:_key] doubleValue]; for (i = 1; i < cc; i++) { register double ov; ov = [[objAtIdx(self, @selector(objectAtIndex:), i) valueForKey:_key] doubleValue]; if (ov < min) min = ov; } return [NSNumber numberWithDouble:min]; } - (id)valueForKey:(NSString *)_key { if ([_key hasPrefix:@"@"]) { /* process a computed function */ const char *keyStr; char *bufPtr; unsigned keyLen = [_key cStringLength]; char *kbuf, *buf; SEL sel; kbuf = malloc(keyLen + 4); buf = malloc(keyLen + 20); [_key getCString:kbuf]; keyStr = kbuf; bufPtr = buf; strcpy(buf, "compute"); bufPtr += 7; *bufPtr = toupper(keyStr[1]); bufPtr++; strncpy(&(buf[8]), &(keyStr[2]), keyLen - 2); bufPtr += (keyLen - 2); strcpy(bufPtr, "ForKey:"); if (kbuf) free(kbuf); sel = sel_registerName(buf); if (buf) free(buf); return sel != NULL ? [self performSelector:sel withObject:_key] : nil; } else { /* process the _key in a map function */ unsigned i, cc = [self count]; id objects[cc]; id (*objAtIdx)(id, SEL, unsigned int); #if DEBUG if ([_key isEqualToString:@"count"]) { NSLog(@"WARNING(%s): USED -valueForKey(@\"count\") ON NSArray, YOU" @"PROBABLY WANT TO USE @count INSTEAD !", __PRETTY_FUNCTION__); return [self valueForKey:@"@count"]; } #endif objAtIdx = (void *)[self methodForSelector:@selector(objectAtIndex:)]; for (i = 0; i < cc; i++) { register id o; o = [objAtIdx(self, @selector(objectAtIndex:), i) valueForKey:_key]; if (o) objects[i] = o; else { if (null == nil) null = [EONull null]; objects[i] = null; } } // TODO: possibly this checks fails on OSX return [self isKindOfClass:[NSMutableArray class]] ? [NSMutableArray arrayWithObjects:objects count:cc] : [NSArray arrayWithObjects:objects count:cc]; } } @end /* NSArray(EOKeyValueCoding) */ @implementation NSDictionary(EOKeyValueCoding) - (NSDictionary *)valuesForKeys:(NSArray *)keys { int n = [keys count]; if (n == 0) return [NSDictionary dictionary]; else if (n == 1) { NSString *key = [keys objectAtIndex:0]; return [NSDictionary dictionaryWithObject:[self objectForKey:key] forKey:key]; } else { NSMutableArray *newKeys, *newVals; int i; newKeys = [NSMutableArray arrayWithCapacity:n]; newVals = [NSMutableArray arrayWithCapacity:n]; for (i = 0; i < n; i++) { id key = [keys objectAtIndex:i]; id val = [self objectForKey:key]; if (val) { [newKeys addObject:key]; [newVals addObject:val]; } } return [NSDictionary dictionaryWithObjects:newVals forKeys:newKeys]; } } - (void)takeValue:(id)_value forKey:(NSString *)_key { //#warning takeValue:forKey: is ignored in NSDictionaries ! // ignore //[self handleTakeValue:_value forUnboundKey:_key]; } - (id)valueForKey:(NSString *)_key { id obj; if (_key == nil) // TODO: warn about nil key? return nil; if ((obj = [self objectForKey:_key]) == nil) return nil; if (null == nil) null = [[NSNull null] retain]; if (obj == null) return nil; return obj; } @end /* NSDictionary(EOKeyValueCoding) */ @implementation NSMutableDictionary(EOKeyValueCoding) - (void)takeValuesFromDictionary:(NSDictionary*)dictionary { [self addEntriesFromDictionary:dictionary]; } - (void)takeValue:(id)_value forKey:(NSString *)_key { if (_value == nil) _value = [NSNull null]; [self setObject:_value forKey:_key]; } @end /* NSMutableDictionary(EOKeyValueCoding) */ /* * Accessor functions */ /* ACCESS to keys of id type. */ static id idMethodGetFunc(void *info1, void *info2, id self) { id (*fptr)(id, SEL) = (id(*)(id, SEL))info1; id val = fptr(self, (SEL)info2); return val; } static id idIvarGetFunc(void *info1, void *info2, id self) { id *ptr = (id *)((char *)self + (unsigned long)info2); return *ptr; } static void idMethodSetFunc(void* info1, void* info2, id self, id val) { void (*fptr)(id, SEL, id) = (void(*)(id, SEL, id))info1; fptr(self, (SEL)info2, val); } static void idIvarSetFunc(void* info1, void* info2, id self, id val) { id *ptr = (id *)((char*)self + (unsigned long)info2); ASSIGN(*ptr, val); } /* ACCESS to keys of char type. */ static id charMethodGetFunc(void* info1, void* info2, id self) { char (*fptr)(id, SEL) = (char(*)(id, SEL))info1; char val = fptr(self, (SEL)info2); return [NumberClass numberWithChar:val]; } static id charIvarGetFunc(void* info1, void* info2, id self) { char *ptr = (char *)((char *)self + (unsigned long)info2); return [NumberClass numberWithChar:*ptr]; } static void charMethodSetFunc(void *info1, void *info2, id self, id val) { void (*fptr)(id, SEL, char) = (void(*)(id, SEL, char))info1; fptr(self, (SEL)info2, [val charValue]); } static void charIvarSetFunc(void *info1, void *info2, id self, id val) { char *ptr = (char *)((char *)self + (unsigned long)info2); *ptr = [val charValue]; } /* ACCESS to keys of unsigned char type. */ static id unsignedCharMethodGetFunc(void* info1, void* info2, id self) { unsigned char (*fptr)(id, SEL) = (unsigned char(*)(id, SEL))info1; unsigned char val = fptr(self, (SEL)info2); return [NumberClass numberWithUnsignedChar:val]; } static id unsignedCharIvarGetFunc(void* info1, void* info2, id self) { unsigned char *ptr = (unsigned char *)((char *)self + (unsigned long)info2); return [NumberClass numberWithUnsignedChar:*ptr]; } static void unsignedCharMethodSetFunc(void* info1, void* info2, id self, id val) { void (*fptr)(id, SEL, unsigned char) = (void(*)(id, SEL, unsigned char))info1; fptr(self, (SEL)info2, [val unsignedCharValue]); } static void unsignedCharIvarSetFunc(void* info1, void* info2, id self, id val) { unsigned char *ptr = (unsigned char *)((char *)self + (unsigned long)info2); *ptr = [val unsignedCharValue]; } /* ACCESS to keys of short type. */ static id shortMethodGetFunc(void* info1, void* info2, id self) { short (*fptr)(id, SEL) = (short(*)(id, SEL))info1; short val = fptr(self, (SEL)info2); return [NumberClass numberWithShort:val]; } static id shortIvarGetFunc(void* info1, void* info2, id self) { short *ptr = (short *)((char *)self + (unsigned long)info2); return [NumberClass numberWithShort:*ptr]; } static void shortMethodSetFunc(void* info1, void* info2, id self, id val) { void (*fptr)(id, SEL, short) = (void(*)(id, SEL, short))info1; fptr(self, (SEL)info2, [val shortValue]); } static void shortIvarSetFunc(void* info1, void* info2, id self, id val) { short *ptr = (short *)((char *)self + (unsigned long)info2); *ptr = [val shortValue]; } /* ACCESS to keys of unsigned short type. */ static id unsignedShortMethodGetFunc(void* info1, void* info2, id self) { unsigned short (*fptr)(id, SEL) = (unsigned short(*)(id, SEL))info1; unsigned short val = fptr(self, (SEL)info2); return [NumberClass numberWithUnsignedShort:val]; } static id unsignedShortIvarGetFunc(void* info1, void* info2, id self) { unsigned short *ptr = (unsigned short*)((char *)self + (unsigned long)info2); return [NumberClass numberWithUnsignedShort:*ptr]; } static void unsignedShortMethodSetFunc(void* info1, void* info2, id self, id val) { void (*fptr)(id, SEL, unsigned short) = (void(*)(id, SEL, unsigned short))info1; fptr(self, (SEL)info2, [val unsignedShortValue]); } static void unsignedShortIvarSetFunc(void* info1, void* info2, id self, id val) { unsigned short *ptr = (unsigned short*)((char *)self + (unsigned long)info2); *ptr = [val unsignedShortValue]; } /* ACCESS to keys of int type. */ static id intMethodGetFunc(void* info1, void* info2, id self) { int (*fptr)(id, SEL) = (int(*)(id, SEL))info1; int val = fptr(self, (SEL)info2); return [NumberClass numberWithInt:val]; } static id intIvarGetFunc(void *info1, void *info2, id self) { int *ptr = (int *)((char *)self + (unsigned long)info2); return [NumberClass numberWithInt:*ptr]; } static void intMethodSetFunc(void* info1, void* info2, id self, id val) { void (*fptr)(id, SEL, int) = (void(*)(id, SEL, int))info1; fptr(self, (SEL)info2, [val intValue]); } static void intIvarSetFunc(void* info1, void* info2, id self, id val) { int *ptr = (int *)((char *)self + (unsigned long)info2); *ptr = [val intValue]; } /* ACCESS to keys of unsigned int type. */ static id unsignedIntMethodGetFunc(void* info1, void* info2, id self) { unsigned int (*fptr)(id, SEL) = (unsigned int(*)(id, SEL))info1; unsigned int val = fptr(self, (SEL)info2); return [NumberClass numberWithUnsignedInt:val]; } static id unsignedIntIvarGetFunc(void* info1, void* info2, id self) { unsigned int* ptr = (unsigned int*)((char*)self + (unsigned long)info2); return [NumberClass numberWithUnsignedInt:*ptr]; } static void unsignedIntMethodSetFunc(void* info1, void* info2, id self, id val) { void (*fptr)(id, SEL, unsigned int) = (void(*)(id, SEL, unsigned int))info1; fptr(self, (SEL)info2, [val unsignedIntValue]); } static void unsignedIntIvarSetFunc(void* info1, void* info2, id self, id val) { unsigned int* ptr = (unsigned int*)((char*)self + (unsigned long)info2); *ptr = [val unsignedIntValue]; } /* ACCESS to keys of long type. */ static id longMethodGetFunc(void* info1, void* info2, id self) { long (*fptr)(id, SEL) = (long(*)(id, SEL))info1; long val = fptr(self, (SEL)info2); return [NumberClass numberWithLong:val]; } static id longIvarGetFunc(void* info1, void* info2, id self) { long* ptr = (long*)((char*)self + (unsigned long)info2); return [NumberClass numberWithLong:*ptr]; } static void longMethodSetFunc(void* info1, void* info2, id self, id val) { void (*fptr)(id, SEL, long) = (void(*)(id, SEL, long))info1; fptr(self, (SEL)info2, [val longValue]); } static void longIvarSetFunc(void* info1, void* info2, id self, id val) { long* ptr = (long*)((char*)self + (unsigned long)info2); *ptr = [val longValue]; } /* unsigned long type */ static id unsignedLongMethodGetFunc(void* info1, void* info2, id self) { unsigned long (*fptr)(id, SEL) = (unsigned long(*)(id, SEL))info1; unsigned long val = fptr(self, (SEL)info2); return [NumberClass numberWithUnsignedLong:val]; } static id unsignedLongIvarGetFunc(void* info1, void* info2, id self) { unsigned long* ptr = (unsigned long*)((char*)self + (unsigned long)info2); return [NumberClass numberWithUnsignedLong:*ptr]; } static void unsignedLongMethodSetFunc(void* info1, void* info2, id self, id val) { void (*fptr)(id, SEL, unsigned long) = (void(*)(id, SEL, unsigned long))info1; fptr(self, (SEL)info2, [val unsignedLongValue]); } static void unsignedLongIvarSetFunc(void* info1, void* info2, id self, id val) { unsigned long* ptr = (unsigned long*)((char*)self + (unsigned long)info2); *ptr = [val unsignedLongValue]; } /* long long type */ static id longLongMethodGetFunc(void* info1, void* info2, id self) { long long (*fptr)(id, SEL) = (long long(*)(id, SEL))info1; long long val = fptr(self, (SEL)info2); return [NumberClass numberWithLongLong:val]; } static id longLongIvarGetFunc(void* info1, void* info2, id self) { long long* ptr = (long long*)((char*)self + (unsigned long)info2); return [NumberClass numberWithLongLong:*ptr]; } static void longLongMethodSetFunc(void* info1, void* info2, id self, id val) { void (*fptr)(id, SEL, long long) = (void(*)(id, SEL, long long))info1; fptr(self, (SEL)info2, [val longLongValue]); } static void longLongIvarSetFunc(void* info1, void* info2, id self, id val) { long long* ptr = (long long*)((char*)self + (unsigned long)info2); *ptr = [val longLongValue]; } /* unsigned long long type */ static id unsignedLongLongMethodGetFunc(void* info1, void* info2, id self) { unsigned long long (*fptr)(id, SEL) = (unsigned long long(*)(id, SEL))info1; unsigned long long val = fptr(self, (SEL)info2); return [NumberClass numberWithUnsignedLongLong:val]; } static id unsignedLongLongIvarGetFunc(void* info1, void* info2, id self) { unsigned long long* ptr = (unsigned long long*)((char*)self + (unsigned long)info2); return [NumberClass numberWithUnsignedLongLong:*ptr]; } static void unsignedLongLongMethodSetFunc(void* info1, void* info2, id self, id val) { void (*fptr)(id, SEL, unsigned long long) = (void(*)(id, SEL, unsigned long long))info1; fptr(self, (SEL)info2, [val unsignedLongLongValue]); } static void unsignedLongLongIvarSetFunc(void* info1, void* info2, id self, id val) { unsigned long long* ptr = (unsigned long long*)((char*)self + (unsigned long)info2); *ptr = [val unsignedLongLongValue]; } /* float */ static id floatMethodGetFunc(void* info1, void* info2, id self) { float (*fptr)(id, SEL) = (float(*)(id, SEL))info1; float val = fptr(self, (SEL)info2); return [NumberClass numberWithFloat:val]; } static id floatIvarGetFunc(void* info1, void* info2, id self) { float* ptr = (float*)((char*)self + (unsigned long)info2); return [NumberClass numberWithFloat:*ptr]; } static void floatMethodSetFunc(void* info1, void* info2, id self, id val) { void (*fptr)(id, SEL, float) = (void(*)(id, SEL, float))info1; fptr(self, (SEL)info2, [val floatValue]); } static void floatIvarSetFunc(void* info1, void* info2, id self, id val) { float* ptr = (float*)((char*)self + (unsigned long)info2); *ptr = [val floatValue]; } /* double */ static id doubleMethodGetFunc(void* info1, void* info2, id self) { double (*fptr)(id, SEL) = (double(*)(id, SEL))info1; double val = fptr(self, (SEL)info2); return [NumberClass numberWithDouble:val]; } static id doubleIvarGetFunc(void* info1, void* info2, id self) { double* ptr = (double*)((char*)self + (unsigned long)info2); return [NumberClass numberWithDouble:*ptr]; } static void doubleMethodSetFunc(void* info1, void* info2, id self, id val) { void (*fptr)(id, SEL, double) = (void(*)(id, SEL, double))info1; fptr(self, (SEL)info2, [val doubleValue]); } static void doubleIvarSetFunc(void* info1, void* info2, id self, id val) { double* ptr = (double*)((char*)self + (unsigned long)info2); *ptr = [val doubleValue]; } #else /* NeXT_Foundation_LIBRARY */ @implementation NSArray(EOKeyValueCoding) - (id)computeSumForKey:(NSString *)_key { static Class NSDecimalNumberClass; id (*objAtIdx)(id, SEL, unsigned int); unsigned i, cc = [self count]; NSDecimalNumber *sum; if (NSDecimalNumberClass == Nil) NSDecimalNumberClass = [NSDecimalNumber class]; sum = [NSDecimalNumber zero]; if (cc == 0) return sum; objAtIdx = (void*)[self methodForSelector:@selector(objectAtIndex:)]; for (i = 0; i < cc; i++) { register id o; o = objAtIdx(self, @selector(objectAtIndex:), i); o = [o valueForKey:_key]; if (![o isKindOfClass:NSDecimalNumberClass]) o = (NSDecimalNumber *)[NSDecimalNumber numberWithDouble:[o doubleValue]]; sum = [sum decimalNumberByAdding:o]; } return sum; } - (id)computeAvgForKey:(NSString *)_key { unsigned cc = [self count]; NSDecimalNumber *sum, *div; if (cc == 0) return nil; sum = [self computeSumForKey:_key]; div = (NSDecimalNumber *)[NSDecimalNumber numberWithUnsignedInt:cc]; return [sum decimalNumberByDividingBy:div]; } - (id)computeCountForKey:(NSString *)_key { return [NSNumber numberWithUnsignedInt:[self count]]; } - (id)computeMaxForKey:(NSString *)_key { id (*objAtIdx)(id, SEL, unsigned int); unsigned i, cc = [self count]; NSDecimalNumber *max; if (cc == 0) return nil; objAtIdx = (void*)[self methodForSelector:@selector(objectAtIndex:)]; max = [objAtIdx(self, @selector(objectAtIndex:), 0) valueForKey:_key]; for (i = 1; i < cc; i++) { register id o; o = [objAtIdx(self, @selector(objectAtIndex:), i) valueForKey:_key]; if ([max compare:o] == NSOrderedAscending) max = o; } return max; } - (id)computeMinForKey:(NSString *)_key { id (*objAtIdx)(id, SEL, unsigned int); unsigned i, cc = [self count]; NSDecimalNumber *min; if (cc == 0) return nil; objAtIdx = (void*)[self methodForSelector:@selector(objectAtIndex:)]; min = [objAtIdx(self, @selector(objectAtIndex:), 0) valueForKey:_key]; for (i = 1; i < cc; i++) { register id o; o = [objAtIdx(self, @selector(objectAtIndex:), i) valueForKey:_key]; if ([min compare:o] == NSOrderedDescending) min = o; } return min; } - (id)valueForKey:(NSString *)_key { if (null == nil) null = [[EONull null] retain]; if ([_key hasPrefix:@"@"]) { /* process a computed function */ const char *keyStr; char *bufPtr; unsigned keyLen = [_key cStringLength]; char *kbuf, *buf; SEL sel; kbuf = malloc(keyLen + 1); buf = malloc(keyLen + 16); [_key getCString:kbuf]; keyStr = kbuf; bufPtr = buf; strcpy(buf, "compute"); bufPtr += 7; *bufPtr = toupper(keyStr[1]); bufPtr++; strncpy(&(buf[8]), &(keyStr[2]), keyLen - 2); bufPtr += (keyLen - 2); strcpy(bufPtr, "ForKey:"); if (kbuf) free(kbuf); sel = sel_registerName(buf); if (buf) free(buf); return sel != NULL ? [self performSelector:sel withObject:_key] : nil; } else { /* process the _key in a map function */ unsigned i, cc = [self count]; NSArray *result; id *objects; id (*objAtIdx)(id, SEL, unsigned int); #if DEBUG if ([_key isEqualToString:@"count"]) { NSLog(@"WARNING(%s): USED -valueForKey(@\"count\") ON NSArray, YOU" @"PROBABLY WANT TO USE @count INSTEAD !", __PRETTY_FUNCTION__); return [self valueForKey:@"@count"]; } #endif if (cc == 0) return [NSArray array]; objects = calloc(cc + 2, sizeof(id)); objAtIdx = (void *)[self methodForSelector:@selector(objectAtIndex:)]; for (i = 0; i < cc; i++) { register id o; o = [objAtIdx(self, @selector(objectAtIndex:), i) valueForKey:_key]; objects[i] = o ? o : (id)null; } result = [NSArray arrayWithObjects:objects count:cc]; if (objects) free(objects); return result; } } @end /* NSArray(EOKeyValueCoding) */ #endif /* !NeXT_Foundation_LIBRARY */ SOPE/sope-core/EOControl/EOControl.h0000644000000000000000000000256415004363604016107 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOControl_H__ #define __EOControl_H__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif /* __EOControl_H__ */ SOPE/sope-core/EOControl/EOObserver.m0000644000000000000000000002663315004363604016266 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOObserver.h" #include "common.h" // THREAD, MT typedef struct _EOObserverList { struct _EOObserverList *next; id observer; void (*notify)(id, SEL, id); } EOObserverList; static void mapValRetain(NSMapTable *self, const void *_value); static void mapValRelease(NSMapTable *self, void *_value); static NSString *mapDescribe(NSMapTable *self, const void *_value); const NSMapTableValueCallBacks EOObserverListMapValueCallBacks = { (void (*)(NSMapTable *, const void *))mapValRetain, (void (*)(NSMapTable *, void *))mapValRelease, (NSString *(*)(NSMapTable *, const void *))mapDescribe }; @implementation NSObject(EOObserver) - (void)willChange { static Class EOObserverCenterClass = Nil; if (EOObserverCenterClass == Nil) EOObserverCenterClass = [EOObserverCenter class]; [EOObserverCenterClass notifyObserversObjectWillChange:self]; } @end /* NSObject(EOObserver) */ @implementation EOObserverCenter static unsigned observerNotificationSuppressCount = 0; static EOObserverList *omniscientObservers = NULL; static NSMapTable *objectToObservers = NULL; + (void)initialize { if (objectToObservers == NULL) { objectToObservers = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks, EOObserverListMapValueCallBacks, 256); } } + (void)notifyObserversObjectWillChange:(id)_object { static id lastObject = nil; register EOObserverList *l; /* check if notifications are suppressed */ if (observerNotificationSuppressCount > 0) return; /* compress notifications for the same object */ if (_object == lastObject) return; /* notify usual observers */ for (l = NSMapGet(objectToObservers, _object); l != NULL; l = l->next) { if (l->notify) l->notify(l->observer, @selector(objectWillChange:), _object); else [l->observer objectWillChange:_object]; } /* notify omniscient observers */ for (l = omniscientObservers; l != NULL; l = l->next) { if (l->notify) l->notify(l->observer, @selector(objectWillChange:), _object); else [l->observer objectWillChange:_object]; } } + (void)addObserver:(id)_observer forObject:(id)_object { register EOObserverList *l, *nl; if ((l = NSMapGet(objectToObservers, _object))) { /* check whether the observer is already registered */ for (nl = l; nl != NULL; nl = nl->next) { if (nl->observer == _object) return; } } nl = malloc(sizeof(EOObserverList)); nl->observer = [_observer retain]; nl->notify = (void*) [(id)_observer methodForSelector:@selector(objectWillChange:)]; if (l == NULL) { /* this is the first observer defined */ nl->next = NULL; NSMapInsert(objectToObservers, _object, nl); } else { /* insert at second position (so that we don't need to remove/add the new entry in table or traverse the list to the end) */ nl->next = l->next; l->next = nl; } } + (void)removeObserver:(id)_observer forObject:(id)_object { register EOObserverList *l, *ll, *first; if ((first = NSMapGet(objectToObservers, _object)) == NULL) /* no observers registered for object */ return; l = first; ll = NULL; while (l) { if (l->observer == _observer) { /* found matching list entry */ if (l != first) { /* entry is not the first entry */ ll->next = l->next; [l->observer release]; free(l); break; } else if (l->next) { /* entry is the first entry, but there are more than one entries. In this case we copy the second to the first and remove the second, this way we save removing/inserting in the hash table. */ [l->observer release]; ll = l->next; l->observer = ll->observer; l->notify = ll->notify; l->next = ll->next; free(ll); break; } else { /* entry is the lone entry */ NSMapRemove(objectToObservers, _object); [l->observer release]; free(l); break; } } ll = l; l = ll->next; } } + (NSArray *)observersForObject:(id)_object { EOObserverList *observers; NSMutableArray *result; if ((observers = NSMapGet(objectToObservers, _object)) == NULL) return [NSArray array]; result = [NSMutableArray arrayWithCapacity:16]; while ((observers)) { if (observers->observer) [result addObject:observers->observer]; observers = observers->next; } return [[result copy] autorelease]; } + (id)observerForObject:(id)_object ofClass:(Class)_targetClass { register EOObserverList *observers; if ((observers = NSMapGet(objectToObservers, _object)) == NULL) return nil; while ((observers)) { if ([observers->observer class] == _targetClass) return observers->observer; observers = observers->next; } return nil; } + (void)addOmniscientObserver:(id)_observer { EOObserverList *l; /* first check whether we already added this observer to the list */ for (l = omniscientObservers; l != NULL; l = l->next) { if (l->observer == _observer) return; } l = malloc(sizeof(EOObserverList)); l->next = omniscientObservers; l->observer = [_observer retain]; l->notify = (void*)[(id)_observer methodForSelector:@selector(willChange:)]; omniscientObservers = l; } + (void)removeOmniscientObserver:(id)_observer { EOObserverList *l, *ll; /* first check whether we already added this observer to the list */ for (l = omniscientObservers, ll = NULL; l != NULL; ) { if (l->observer == _observer) { /* matched */ if (ll == NULL) omniscientObservers = l->next; else ll->next = l->next; [l->observer release]; free(l); return; } ll = l; l = ll->next; } } /* suppressing notifications */ + (void)suppressObserverNotification { observerNotificationSuppressCount++; } + (void)enableObserverNotification { observerNotificationSuppressCount--; } + (unsigned)observerNotificationSuppressCount { return observerNotificationSuppressCount; } @end /* EOObserverCenter */ @implementation EODelayedObserverQueue static EODelayedObserverQueue *defaultQueue = nil; + (EODelayedObserverQueue *)defaultObserverQueue { if (defaultQueue == nil) defaultQueue = [[EODelayedObserverQueue alloc] init]; return defaultQueue; } - (id)init { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_notify:) name:@"EODelayedNotify" object:self]; return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [self->runLoopModes release]; [super dealloc]; } /* accessors */ - (void)setRunLoopModes:(NSArray *)_modes { ASSIGN(self->runLoopModes, _modes); } - (NSArray *)runLoopModes { return self->runLoopModes; } /* single queue */ static inline void _enqueue(EODelayedObserverQueue *self, EODelayedObserver **list, EODelayedObserver *newEntry) { if (*list == nil) { /* first entry in this list */ *list = [newEntry retain]; } else { EODelayedObserver *e, *le; for (e = *list, le = NULL; e != NULL; e = e->next) { if (e == newEntry) { /* already in queue */ return; } le = e; } le->next = [e retain]; e->next = NULL; } } static inline void _dequeue(EODelayedObserverQueue *self, EODelayedObserver **list, EODelayedObserver *entry) { EODelayedObserver *e, *le; for (e = *list, le = NULL; e != NULL; e = e->next) { if (e == entry) { /* found entry */ le->next = e->next; [e release]; return; } le = e; } } static inline void _notify(EODelayedObserverQueue *self, EODelayedObserver *list) { while (list) { [list subjectChanged]; list = list->next; } } /* managing queue */ - (void)enqueueObserver:(EODelayedObserver *)_observer { if (_observer == nil) return; _enqueue(self, &(self->queues[[_observer priority]]), _observer); if (!self->hasObservers) { /* register for ASAP notification */ NSNotification *notification; notification = [NSNotification notificationWithName:@"EODelayedNotify" object:self]; [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP coalesceMask:NSNotificationCoalescingOnSender forModes:[self runLoopModes]]; self->hasObservers = YES; } } - (void)dequeueObserver:(EODelayedObserver *)_observer { if (_observer == nil) return; _dequeue(self, &(self->queues[[_observer priority]]), _observer); } /* notification */ - (void)notifyObserversUpToPriority:(EOObserverPriority)_lastPriority { unsigned i; for (i = 0; i < _lastPriority; i++) _notify(self, self->queues[i]); } - (void)_notify:(NSNotification *)_notification { [self notifyObserversUpToPriority:EOObserverPrioritySixth]; } @end /* EODelayedObserverQueue */ @implementation EODelayedObserver /* accessors */ - (EOObserverPriority)priority { return EOObserverPriorityThird; } - (EODelayedObserverQueue *)observerQueue { return [EODelayedObserverQueue defaultObserverQueue]; } /* notifications */ - (void)subjectChanged { [self doesNotRecognizeSelector:_cmd]; } - (void)objectWillChange:(id)_object { [[self observerQueue] enqueueObserver:self]; } - (void)discardPendingNotification { [[self observerQueue] dequeueObserver:self]; } @end /* EODelayedObserver */ @implementation EOObserverProxy - (id)initWithTarget:(id)_target action:(SEL)_action priority:(EOObserverPriority)_priority { if ((self = [super init])) { self->target = [_target retain]; self->action = _action; self->priority = _priority; } return self; } - (id)init { return [self initWithTarget:nil action:NULL priority:EOObserverPriorityThird]; } - (void)dealloc { [self->target release]; [super dealloc]; } /* accessors */ - (EOObserverPriority)priority { return self->priority; } /* notifications */ - (void)subjectChanged { [self->target performSelector:self->action withObject:self]; } @end /* EOObserverProxy */ /* value functions for mapping table */ static void mapValRetain(NSMapTable *self, const void *_value) { /* do nothing */ } static void mapValRelease(NSMapTable *self, void *_value) { /* do nothing */ } static NSString *mapDescribe(NSMapTable *self, const void *_value) { return @""; } SOPE/sope-core/EOControl/EOGlobalID.m0000644000000000000000000000536715004363604016115 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOGlobalID.h" #include "common.h" #include #include #if !defined(__MINGW32__) # include #endif @implementation EOGlobalID - (BOOL)isTemporary { return NO; } - (id)copyWithZone:(NSZone *)_zone { [self doesNotRecognizeSelector:_cmd]; return nil; } @end /* EOGlobalID */ @implementation EOTemporaryGlobalID static unsigned short sequence = 0; static unsigned int ip; + (void)initialize { static BOOL isInitialized = NO; if (!isInitialized) { char buf[1024]; struct hostent *hostEntry; isInitialized = YES; gethostname(buf, 1024); // THREADING if ((hostEntry = gethostbyname(buf))) { char **ptr; ptr = hostEntry->h_addr_list; if (*ptr) { NSAssert((unsigned)hostEntry->h_length >= sizeof(ip), @"invalid host address !"); memcpy(&ip, *ptr, sizeof(ip)); } else { NSLog(@"WARNING: set IP address for EO key generation to 0.0.0.0 !"); ip = 0; } } else { NSLog(@"WARNING: set IP address for EO key generation to 0.0.0.0 !"); ip = 0; } } } + (void)assignGloballyUniqueBytes:(unsigned char *)_buffer { struct { unsigned short sequence; unsigned short pid; unsigned int time; unsigned int ip; } *bufPtr; bufPtr = (void *)_buffer; bufPtr->sequence = sequence++; #if defined(__WIN32__) bufPtr->pid = (unsigned short)GetCurrentProcessId(); #else bufPtr->pid = getpid(); #endif bufPtr->time = time(NULL); bufPtr->ip = ip; } - (id)init { [object_getClass(self) assignGloballyUniqueBytes:&(self->idbuffer[0])]; return self; } - (BOOL)isTemporary { return YES; } - (BOOL)isEqual:(id)_other { return _other == self ? YES : NO; #if 0 EOTemporaryGlobalID *otherKey; if (_other == nil) return NO; if (_other == self) return YES; otherKey = _other; if (otherKey->isa != self->isa) return NO; // compare bytes return NO; #endif } @end /* EOTemporaryGlobalID */ SOPE/sope-core/EOControl/GNUmakefile0000644000000000000000000000370115004363604016136 0ustar rootroot# GNUstep makefile include ../../config.make include ../common.make ifneq ($(frameworks),yes) LIBRARY_NAME = libEOControl else FRAMEWORK_NAME = EOControl endif libEOControl_PCH_FILE = common.h libEOControl_DLL_DEF = libEOControl.def libEOControl_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION) libEOControl_INSTALL_DIR=$(SOPE_SYSLIBDIR) libEOControl_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION) libEOControl_HEADER_FILES_DIR = . libEOControl_HEADER_FILES_INSTALL_DIR = /EOControl libEOControl_HEADER_FILES = \ EOArrayDataSource.h \ EOClassDescription.h \ EOControl.h \ EOControlDecls.h \ EODataSource.h \ EODetailDataSource.h \ EOFetchSpecification.h \ EOGenericRecord.h \ EOGlobalID.h \ EOKeyGlobalID.h \ EOKeyValueArchiver.h \ EOKeyValueCoding.h \ EONull.h \ EOObserver.h \ EOQualifier.h \ EOSortOrdering.h \ EOSQLParser.h \ libEOControl_OBJC_FILES = \ EOAndQualifier.m \ EOArrayDataSource.m \ EOClassDescription.m \ EODataSource.m \ EODetailDataSource.m \ EOFetchSpecification.m \ EOGenericRecord.m \ EOGlobalID.m \ EOKeyComparisonQualifier.m \ EOKeyGlobalID.m \ EOKeyValueArchiver.m \ EOKeyValueCoding.m \ EOKeyValueQualifier.m \ EONotQualifier.m \ EONull.m \ EOObserver.m \ EOOrQualifier.m \ EOQualifier.m \ EOQualifierParser.m \ EOSortOrdering.m \ EOValidation.m \ NSArray+EOQualifier.m \ NSObject+EOQualifierOps.m \ EOSQLParser.m \ EOQualifierVariable.m \ NSObject+QualDesc.m \ # framework support EOControl_PCH_FILE = $(libEOControl_PCH_FILE) EOControl_HEADER_FILES = $(libEOControl_HEADER_FILES) EOControl_OBJC_FILES = $(libEOControl_OBJC_FILES) # building -include GNUmakefile.preamble ifneq ($(FHS_INSTALL_ROOT),) GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include endif ifneq ($(frameworks),yes) include $(GNUSTEP_MAKEFILES)/library.make else include $(GNUSTEP_MAKEFILES)/framework.make endif -include GNUmakefile.postamble SOPE/sope-core/EOControl/EOSQLParser.h0000644000000000000000000000525215004363604016300 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOControl_EOSQLParser_H__ #define __EOControl_EOSQLParser_H__ #import #import /* This is parser can be used to parse simple SQL statements. It's not a full SQL implementation, but should be sufficient for simple applications. Additional hints: - the selected attributes are added to the 'attributes' hint, if a wildcard select is used (*), the hint is not set - the depth of WebDAV scope from-queries are set in the depth-hint, valid values are "deep", "flat", "flat+self", "self" - if multiple entities are queried in the FROM, they are joined using "," and set as the entityName of the fetch spec */ @class EOFetchSpecification, EOQualifier; @interface EOSQLParser : NSObject { } + (id)sharedSQLParser; /* top level parser entry points */ - (EOFetchSpecification *)parseSQLSelectStatement:(NSString *)_sql; - (EOQualifier *)parseSQLWhereExpression:(NSString *)_sql; /* parsing parts (exported for overloading in subclasses) */ - (BOOL)parseSQL:(id *)result from:(unichar **)pos length:(unsigned *)len strict:(BOOL)beStrict; - (BOOL)parseToken:(const unsigned char *)tk from:(unichar **)pos length:(unsigned *)len consume:(BOOL)consume; - (BOOL)parseIdentifier:(NSString **)result from:(unichar **)pos length:(unsigned *)len consume:(BOOL)consume; - (BOOL)parseQualifier:(EOQualifier **)result from:(unichar **)pos length:(unsigned *)len; - (BOOL)parseScope:(NSString **)_scope :(NSString **)_entity from:(unichar **)pos length:(unsigned *)len; - (BOOL)parseColumnName:(NSString **)result from:(unichar **)pos length:(unsigned *)len consume:(BOOL)consume; - (BOOL)parseTableName:(NSString **)result from:(unichar **)pos length:(unsigned *)len consume:(BOOL)consume; - (BOOL)parseIdentifierList:(NSArray **)result from:(unichar **)pos length:(unsigned *)len selector:(SEL)_sel; @end #endif /* __EOControl_EOSQLParser_H__ */ SOPE/sope-core/EOControl/EOKeyComparisonQualifier.m0000644000000000000000000001715315004363604021121 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "common.h" @implementation EOKeyComparisonQualifier static EONull *null = nil; + (void)initialize { if (null == nil) null = [[EONull null] retain]; } - (id)initWithLeftKey:(NSString *)_leftKey operatorSelector:(SEL)_selector rightKey:(NSString *)_rightKey; { self->leftKey = [_leftKey copyWithZone:NULL]; self->rightKey = [_rightKey copyWithZone:NULL]; self->operator = _selector; return self; } - (void)dealloc { [self->leftKey release]; [self->rightKey release]; [super dealloc]; } /* accessors */ - (NSString *)leftKey { return self->leftKey; } - (NSString *)rightKey { return self->rightKey; } - (SEL)selector { return self->operator; } /* bindings */ - (EOQualifier *)qualifierWithBindings:(NSDictionary *)_bindings requiresAllVariables:(BOOL)_reqAll { static Class VarClass = Nil; NSString *newLeftKey; id newRightKey; BOOL needNew; if (VarClass == Nil) VarClass = [EOQualifierVariable class]; needNew = NO; if ([self->leftKey class] == VarClass) { newLeftKey = [_bindings objectForKey:[(EOQualifierVariable *)self->leftKey key]]; if (newLeftKey == nil) { if (_reqAll) // throw exception ; else newLeftKey = self->leftKey; } else needNew = YES; } else newLeftKey = self->leftKey; if ([self->rightKey class] == VarClass) { newRightKey = [_bindings objectForKey:[(EOQualifierVariable *)self->rightKey key]]; if (newRightKey == nil) { if (_reqAll) // throw exception ; else newRightKey = self->rightKey; } else needNew = YES; } else newRightKey = self->rightKey; if (!needNew) return self; return [[[[self class] alloc] initWithLeftKey:newLeftKey operatorSelector:self->operator rightKey:newRightKey] autorelease]; } - (NSArray *)bindingKeys { static Class VarClass = Nil; Class lkClass, rkClass; if (VarClass == Nil) VarClass = [EOQualifierVariable class]; lkClass = [self->leftKey class]; rkClass = [self->rightKey class]; if ((lkClass == VarClass) && (rkClass == VarClass)) { id o[2]; o[0] = [(EOQualifierVariable *)self->leftKey key]; o[1] = [(EOQualifierVariable *)self->rightKey key]; return [NSArray arrayWithObjects:o count:2]; } if (lkClass == VarClass) return [NSArray arrayWithObject:[(EOQualifierVariable *)self->leftKey key]]; if (rkClass == VarClass) { return [NSArray arrayWithObject: [(EOQualifierVariable *)self->rightKey key]]; } return [NSArray array]; } /* keys */ - (void)addQualifierKeysToSet:(NSMutableSet *)_keys { /* new in WO 4.5 */ [_keys addObject:self->leftKey]; [_keys addObject:self->rightKey]; } /* evaluation */ - (BOOL)evaluateWithObject:(id)_object inEvalContext:(id)_ctx { id lv, rv; BOOL (*m)(id, SEL, id); if (_ctx == nil) _ctx = [NSMutableDictionary dictionaryWithCapacity:16]; if ((lv = [(NSDictionary *)_ctx objectForKey:self->leftKey]) == nil) { lv = [_object valueForKeyPath:self->leftKey]; if (lv == nil) lv = null; [(NSMutableDictionary *)_ctx setObject:lv forKey:self->leftKey]; } if ((rv = [(NSDictionary *)_ctx objectForKey:self->rightKey]) == nil) { rv = [_object valueForKeyPath:self->rightKey]; if (rv == nil) rv = null; [(NSMutableDictionary *)_ctx setObject:rv forKey:self->rightKey]; } if ((m = (void *)[lv methodForSelector:self->operator]) == NULL) { /* no such operator method ! */ [lv doesNotRecognizeSelector:self->operator]; return NO; } return m(lv, self->operator, rv); } - (BOOL)evaluateWithObject:(id)_object { return [self evaluateWithObject:_object inEvalContext:nil]; } /* NSCoding */ - (void)encodeWithCoder:(NSCoder *)_coder { [_coder encodeObject:self->leftKey]; [_coder encodeObject:self->rightKey]; [_coder encodeValueOfObjCType:@encode(SEL) at:&(self->operator)]; } - (id)initWithCoder:(NSCoder *)_coder { self->leftKey = [[_coder decodeObject] copyWithZone:[self zone]]; self->rightKey = [[_coder decodeObject] copyWithZone:[self zone]]; [_coder decodeValueOfObjCType:@encode(SEL) at:&(self->operator)]; return self; } /* Comparing */ - (BOOL)isEqualToQualifier:(EOQualifier *)_qual { if (![self->leftKey isEqual:[(EOKeyComparisonQualifier *)_qual leftKey]]) return NO; if (![self->rightKey isEqual:[(EOKeyComparisonQualifier *)_qual rightKey]]) return NO; if (sel_isEqual(self->operator, [(EOKeyComparisonQualifier *)_qual selector])) return YES; return NO; } /* remapping keys */ - (EOQualifier *)qualifierByApplyingTransformer:(id)_transformer inContext:(id)_ctx { if ([_transformer respondsToSelector: @selector(transformKeyComparisonQualifier:inContext:)]) { return [_transformer transformKeyComparisonQualifier:self inContext:_ctx]; } else return [[self retain] autorelease]; } - (EOQualifier *)qualifierByApplyingKeyMap:(NSDictionary *)_map { EOKeyComparisonQualifier *kcq; NSString *l, *r; l = [_map objectForKey:self->leftKey]; if (l == nil) l = self->leftKey; r = [_map objectForKey:self->rightKey]; if (r == nil) r = self->rightKey; kcq = [[EOKeyComparisonQualifier alloc] initWithLeftKey:l operatorSelector:self->operator rightKey:r]; return [kcq autorelease]; } /* key/value archiving */ - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { if ((self = [super initWithKeyValueUnarchiver:_unarchiver]) != nil) { NSString *s; self->leftKey = [[_unarchiver decodeObjectForKey:@"leftKey"] retain]; self->rightKey = [[_unarchiver decodeObjectForKey:@"rightKey"] retain]; if ((s = [_unarchiver decodeObjectForKey:@"selectorName"]) != nil) { if (![s hasSuffix:@":"]) s = [s stringByAppendingString:@":"]; self->operator = NSSelectorFromString(s); } else if ((s = [_unarchiver decodeObjectForKey:@"selector"]) != nil) self->operator = NSSelectorFromString(s); } return self; } - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver { NSString *s; [super encodeWithKeyValueArchiver:_archiver]; [_archiver encodeObject:[self leftKey] forKey:@"leftKey"]; [_archiver encodeObject:[self rightKey] forKey:@"rightKey"]; s = NSStringFromSelector([self selector]); if ([s hasSuffix:@":"]) s = [s substringToIndex:[s length] - 1]; [_archiver encodeObject:s forKey:@"selectorName"]; } /* description */ - (NSString *)description { NSMutableString *s; s = [NSMutableString stringWithCapacity:64]; [s appendString:self->leftKey]; [s appendString:@" "]; [s appendString:[EOQualifier stringForOperatorSelector:self->operator]]; [s appendString:@" "]; [s appendString:self->rightKey]; return s; } @end /* EOKeyComparisonQualifier */ SOPE/sope-core/EOControl/EOKeyValueQualifier.m0000644000000000000000000002207315004363604020060 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "common.h" @interface NSObject(QualifierDescription) - (NSString *)qualifierDescription; @end @implementation EOKeyValueQualifier static BOOL debugEval = NO; static BOOL debugTransform = NO; static EONull *null = nil; + (void)initialize { if (null == nil) null = [[EONull null] retain]; debugEval = [EOQualifier isEvaluationDebuggingEnabled]; } - (id)initWithKey:(NSString *)_key operatorSelector:(SEL)_selector value:(id)_value { self->key = [_key copyWithZone:NULL]; self->value = [_value retain]; self->operator = _selector; self->formatted = NO; if (_selector == NULL) { NSLog(@"WARNING(%s): got no selector for kv qualifier (key=%@)", __PRETTY_FUNCTION__, _key); } return self; } - (id)init { return [self initWithKey:nil operatorSelector:NULL value:nil]; } - (void)dealloc { [self->key release]; [self->value release]; [super dealloc]; } /* accessors */ - (NSString *)key { return self->key; } - (SEL)selector { return self->operator; } - (id)value { return self->value; } - (void) setValue: (id) _value { [self->value release]; self->value = [_value retain]; } - (BOOL) formatted { return self->formatted; } - (void) setFormatted: (BOOL) _formatted { self->formatted = _formatted; } /* bindings */ - (EOQualifier *)qualifierWithBindings:(NSDictionary *)_bindings requiresAllVariables:(BOOL)_reqAll { static Class VarClass = Nil; NSString *newKey; id newValue; BOOL needNew; if (VarClass == Nil) VarClass = [EOQualifierVariable class]; needNew = NO; if ([self->key class] == VarClass) { newKey = [_bindings objectForKey:[(EOQualifierVariable *)self->key key]]; if (newKey == nil) { if (_reqAll) // throw exception ; else newKey = self->key; } else needNew = YES; } else newKey = self->key; if ([self->value class] == VarClass) { newValue = [_bindings objectForKey:[self->value key]]; if (newValue == nil) { if (_reqAll) // throw exception ; else newValue = self->value; } else needNew = YES; } else newValue = self->value; if (!needNew) return self; return [[[[self class] alloc] initWithKey:newKey operatorSelector:self->operator value:newValue] autorelease]; } - (NSArray *)bindingKeys { static Class VarClass = Nil; Class keyClass, vClass; if (VarClass == Nil) VarClass = [EOQualifierVariable class]; keyClass = [self->key class]; vClass = [self->value class]; if ((keyClass == VarClass) && (vClass == VarClass)) { id o[2]; o[0] = [(EOQualifierVariable *)self->key key]; o[1] = [(EOQualifierVariable *)self->value key]; return [NSArray arrayWithObjects:o count:2]; } if (keyClass == VarClass) return [NSArray arrayWithObject:[(EOQualifierVariable *)self->key key]]; if (vClass == VarClass) return [NSArray arrayWithObject:[(EOQualifierVariable *)self->value key]]; return [NSArray array]; } /* keys */ - (void)addQualifierKeysToSet:(NSMutableSet *)_keys { /* new in WO 4.5 */ [_keys addObject:self->key]; } /* evaluation */ - (BOOL)evaluateWithObject:(id)_object inEvalContext:(id)_ctx { id lv, rv; BOOL (*m)(id, SEL, id); BOOL result; if (_ctx == nil) _ctx = [NSMutableDictionary dictionaryWithCapacity:16]; if ((lv = [(NSDictionary *)_ctx objectForKey:self->key]) == nil) { lv = [_object valueForKeyPath:self->key]; if (lv == nil) lv = null; [(NSMutableDictionary *)_ctx setObject:lv forKey:self->key]; } rv = self->value != nil ? self->value : (id)null; if (debugEval) { NSLog(@"Eval: EOKeyValueQualifier:(%@ %@)\n" @" compare %@<%@>\n with %@<%@>", self->key, NSStringFromSelector(self->operator), lv, NSStringFromClass([lv class]), rv, NSStringFromClass([rv class])); } if ((m = (void *)[lv methodForSelector:self->operator]) == NULL) { /* no such operator method ! */ [lv doesNotRecognizeSelector:self->operator]; return NO; } result = m(lv, self->operator, rv); if (debugEval) NSLog(@" %@", result ? @"MATCHES" : @"DOES NOT MATCH"); return result; } - (BOOL)evaluateWithObject:(id)_object { return [self evaluateWithObject:_object inEvalContext:nil]; } /* NSCoding */ - (void)encodeWithCoder:(NSCoder *)_coder { [_coder encodeObject:self->key]; [_coder encodeObject:self->value]; [_coder encodeValueOfObjCType:@encode(SEL) at:&(self->operator)]; } - (id)initWithCoder:(NSCoder *)_coder { self->key = [[_coder decodeObject] copyWithZone:[self zone]]; self->value = [[_coder decodeObject] retain]; [_coder decodeValueOfObjCType:@encode(SEL) at:&(self->operator)]; if (self->operator == NULL) { NSLog(@"WARNING(%s): decoded no selector for kv qualifier (key=%@)", __PRETTY_FUNCTION__, self->key); } return self; } /* Comparing */ - (BOOL)isEqualToQualifier:(EOQualifier *)_qual { if (![self->key isEqual:[(EOKeyValueQualifier *)_qual key]]) return NO; if (![self->value isEqual:[(EOKeyValueQualifier *)_qual value]]) return NO; if (sel_isEqual(self->operator, [(EOKeyValueQualifier *)_qual selector])) return YES; return NO; } /* remapping keys */ - (EOQualifier *)qualifierByApplyingTransformer:(id)_transformer inContext:(id)_ctx { if ([_transformer respondsToSelector: @selector(transformKeyValueQualifier:inContext:)]) { if (debugTransform) NSLog(@"transformer: %@\n transform: %@", _transformer, self); return [_transformer transformKeyValueQualifier:self inContext:_ctx]; } else { if (debugTransform) NSLog(@"EOKeyValueQualifier: not transforming using %@", _transformer); return [[self retain] autorelease]; } } - (EOQualifier *)qualifierByApplyingKeyMap:(NSDictionary *)_map { EOKeyValueQualifier *kvq; NSString *k; k = [_map objectForKey:self->key]; if (k == nil) k = self->key; kvq = [[EOKeyValueQualifier alloc] initWithKey:k operatorSelector:self->operator value:self->value]; return [kvq autorelease]; } /* key/value archiving */ - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { if ((self = [super initWithKeyValueUnarchiver:_unarchiver]) != nil) { NSString *s; self->key = [[_unarchiver decodeObjectForKey:@"key"] copy]; self->value = [[_unarchiver decodeObjectForKey:@"value"] retain]; if ((s = [_unarchiver decodeObjectForKey:@"selectorName"]) != nil) { if (![s hasSuffix:@":"]) s = [s stringByAppendingString:@":"]; self->operator = NSSelectorFromString(s); } else if ((s = [_unarchiver decodeObjectForKey:@"selector"]) != nil) self->operator = NSSelectorFromString(s); else { NSLog(@"WARNING(%s): decoded no selector/selectorName for kv qualifier " @"(key=%@)", __PRETTY_FUNCTION__, self->key); self->operator = EOQualifierOperatorEqual; } if (self->operator == NULL) { NSLog(@"WARNING(%s): decoded no selector for kv qualifier (key=%@)", __PRETTY_FUNCTION__, self->key); self->operator = EOQualifierOperatorEqual; } } return self; } - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver { NSString *s; [super encodeWithKeyValueArchiver:_archiver]; [_archiver encodeObject:[self key] forKey:@"key"]; [_archiver encodeObject:[self value] forKey:@"value"]; s = NSStringFromSelector([self selector]); if ([s hasSuffix:@":"]) s = [s substringToIndex:[s length] - 1]; [_archiver encodeObject:s forKey:@"selectorName"]; } /* description */ - (NSString *)description { NSMutableString *s; NSString *tmp; s = [NSMutableString stringWithCapacity:64]; if (self->key != nil) [s appendString:self->key]; else [s appendString:@"[NO KEY]"]; [s appendString:@" "]; if ((tmp = [EOQualifier stringForOperatorSelector:self->operator]) != nil) [s appendString:tmp]; else if (self->operator != NULL) [s appendString:@"[NO STR OPERATOR]"]; else [s appendString:@"[NO OPERATOR]"]; [s appendString:@" "]; if ((tmp = [self->value qualifierDescription]) != nil) [s appendString:tmp]; else [s appendString:@"nil"]; return s; } @end /* EOKeyValueQualifier */ SOPE/sope-core/EOControl/EONull.m0000644000000000000000000000247415004363604015406 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EONull.h" #include "common.h" #ifdef EONull # undef EONull #endif @interface EONull : NSNull @end @implementation EONull + (id)allocWithZone:(NSZone *)_zone { return (EONull*)[NSNull allocWithZone:_zone]; } + (NSNull *)null { return (EONull*)[NSNull null]; } - (id)self { return (EONull*)[NSNull null]; } @end @implementation NSNull(ExprValue) - (BOOL)boolValue { return NO; } - (NSString *)expressionValueForContext:(id)context { /* context is really EOExpressionArray .. */ return @"NULL"; } @end /* EONull(ExprValue) */ SOPE/sope-core/EOControl/ChangeLog0000644000000000000000000002073315004363604015642 0ustar rootroot2009-03-24 Wolfgang Sourdeau * EOGenericRecord.m: special support for gstep-base (v4.7.74) 2007-04-17 Helge Hess * EOKeyValueCoding.m: fixed a gcc4 warning (v4.7.73) 2007-01-15 Stephane Corthesy * EOQualifierParser.m (_parseValue): fixed a bug in the qualifier parser (v4.5.72) 2006-12-17 Marcus Mueller * EOKeyValueCoding.m: fixed a runtime portability issue - removed +initialize on NSArray category (v4.5.71) 2006-12-02 Marcus Mueller * EOKeyValueCoding.m: fixed numerous bugs in the computeXXX: methods and provided proper implementations according to the WO4.5 specs for gnustep-base and Apple Foundation (v4.5.70) 2006-12-02 Helge Hess * EOKeyValueCoding.m: added NSDecimalNumber implementation for -computeSumForKey: (TBD: implementations for the other methods) (v4.5.69) 2006-09-30 Helge Hess * EOKeyGlobalID.m: print a warning if a key-gid is created with a nil value, improved -description (v4.5.68) 2006-08-18 Helge Hess * EOKeyValueCoding.m: -valueForKey: now returns mutable arrays when being called on mutable arrays (WO 4.5 compatibility) (v4.5.67) 2006-07-04 Helge Hess * 64bit fixes (v4.5.66) 2006-07-03 Helge Hess * v4.5.65 * EOKeyValueCoding.m: reduced autorelease usage in KVC key creation * use %p for pointer formats, fixed gcc 4.1 warnings 2006-05-02 Marcus Mueller * EOSortOrdering.m: use keyPaths instead of just keys in keyOrderComparator() function - this is feature compatible with Apple's EOF 4.5 (v4.5.64) 2006-02-20 Helge Hess * EOKeyValueCoding.m: do not use EOKeyValueCoding with gstep-base (KVC implemented directly in base) (v4.5.63) 2005-11-17 Helge Hess * v4.5.62 * EOKeyValueQualifier.m: fixed some SEL related warnings * common.h: properly include string.h 2005-10-03 Helge Hess * EOKeyValueQualifier.m: improved -description in edge conditions, added warnings if the qualifier is initialized with insufficient values (v4.5.61) 2005-08-23 Helge Hess * EOQualifier.m: added NSCopying (v4.5.60) 2005-08-06 Helge Hess * EOKeyValueArchiver.m: improved decoding of bools (v4.5.59) 2005-08-05 Helge Hess * v4.5.58 * EODetailDataSource.m: added EOKeyValueArchiving * EOSortOrdering.m: use 'selectorName' instead of 'selector' for kv archiving * EOKeyValueArchiver.m: fixed decoding of arrays 2005-08-04 Helge Hess * EOKeyValueArchiver.m: fixed a bug with decoding references (v4.5.57) * EOKeyValueArchiver.m: print a warning if a class specified in the archive could not be found (v4.5.56) 2005-08-04 Helge Hess * v4.5.55 * EOSortOrdering.m, EOFetchSpecification.m: added EOKeyValueArchiving * EO*Qualifier.m: added EOKeyValueArchiving to EOQualifier classes * NSObject+EOQualifierOps.m: fixed gcc 4.0 warnings 2005-08-04 Helge Hess * EOKeyValueArchiver.m: process class names containing a dot by first looking up the class using the last dot-component and then by trying to map some known prefixes (eg D2W) (v4.5.54) 2005-05-03 Helge Hess * EOQualifier.h: fixed prototypes of -isLike/-isCaseInsensitiveLike: (v4.5.53) * NSObject+EOQualifierOps.m: fixed signature of -isLike: and -isCaseInsensitiveLike: to match Tiger (v4.5.52) 2005-04-24 Helge Hess * fixed gcc 4.0 signed/unsigned warnings (v4.5.51) 2005-01-14 Helge Hess * EOFetchSpecification.m: minor code cleanups (v4.5.50) 2004-12-14 Marcus Mueller * EOControl.xcode: minor changes and updated 2004-12-05 Helge Hess * EOKeyGlobalID.m: minor code cleanup (v4.5.49) 2004-08-29 Helge Hess * added hack to install the project in FHS locations - the library, its headers, the tools and the resources will be installed in FHS_INSTALL_ROOT if specified (eg make FHS_INSTALL_ROOT=/usr/local) (v4.3.48) 2004-08-29 Marcus Mueller * EOControl.xcode: various fixes for project settings 2004-08-23 Marcus Mueller * added new Xcode project 2004-08-20 Helge Hess * moved to SOPE 4.3 (v4.3.47) 2004-07-22 Helge Hess * EOKeyComparisonQualifier.m, EOKeyValueQualifier.m, EOKeyValueArchiver.m, EOFetchSpecification.m: fixed gcc 3.4 warnings (v4.2.46) 2004-06-09 Helge Hess * v4.2.45 * GNUmakefile.preamble: added prebinding * GNUmakefile: minor cleanups 2004-05-16 Helge Hess * EOKeyComparisonQualifier.m, EOKeyValueQualifier.m, EOQualifier.m, EOQualifierVariable.m: minor code cleanups, fixed some "== YES" comparisons (v4.2.44) 2004-04-07 Helge Hess * EOQualifierParser.m: minor code cleanups (==YES) (v4.2.43) 2004-03-15 Helge Hess * EOFetchSpecification, EOQualifier, EOSortOrdering: moved property list initializer methods to NGExtensions to improve GDL2 compatibility (v4.2.42) 2004-03-11 Helge Hess * EOFetchSpecification, EOQualifier, EOSortOrdering: deprecated -initWithPropertyList: method, added new -initWithPropertyList:owner: method (like in EOPropertyListEncoding) (v4.2.41) 2004-03-09 Helge Hess * EOFetchSpecification.m: subminor improvement in -copyWithZone: method (v4.2.40) 2004-03-03 Helge Hess * EOFetchSpecification.m: fixed a recursion introduced in v4.2.38 (v4.2.39) 2004-03-02 Helge Hess * v4.2.38 * EOQualifier.m: added -qualifierByApplyingBindings: to improve GDL2 compatibility (should not be used) * EOFetchSpecification.m: added -fetchSpecificationByApplyingBindings: to improve GDL2 compatibility (should not be used) * EOQualifier.m: moved EOQualifierVariable to separate file, moved qualifier-description categories to separate files * EOFetchSpecification.m, EOSQLParser.m: improved GDL2/EOF 3 compatibility (different -init method, deprecated old) 2003-12-29 Helge Hess * EOKeyValueCoding.m: do not invoke NSDictionary -objectForKey: with 'nil' key (v4.2.37) 2003-11-25 Helge Hess * removed unused source files (v4.2.36) [what was v4.2.35?, missing] 2003-11-14 Helge Hess * EOSortOrdering.m: added an assertion to prevent index overflows (v4.2.34) Tue Nov 11 12:01:10 2003 Jan Reichmann * common.h: fixed Free marcro declaration (introduced in 4.2.33) (v4.2.34) 2003-11-09 Helge Hess * v4.2.33 * common.h: always use malloc/free for allocating instead of objc_malloc/objc_free to clean up the code * EOAndQualifier.m: some minor tweaks for Xcode * EOFault.m: removed support for Boehm GC to clean up the code 2003-09-06 Helge Hess * EOGenericRecord.m: fixed a warning on MacOSX (used return in dealloc ...) (v4.2.32) * v4.2.31 * EOSQLParser.m: do not use stringByReplacingString:withString: * EOClassDescription.m: fixed some warning on OSX 2003-09-06 Marcus Mueller * EOFault.m/EOFaultHandler.m: ported to NeXT runtime (v4.2.30) 2003-09-01 Helge Hess * changed not to require FoundationExt on MacOSX (v4.2.29) 2003-08-07 Helge Hess * EOQualifierParser.m: added facility to register own classes for complex cast expressions (eg "cast(xxxx as myValue)"), required for Evolution 1.4.4. Also less restrictive about whitespace between "cast" and the "(" (v4.2.28) Fri Jul 4 17:00:54 2003 Helge Hess * added to OpenGroupware.org * stripped out old ChangeLogs, unimportant for OGo Wed Dec 8 18:35:40 1999 Helge Hess * created ChangeLog SOPE/sope-core/EOControl/common.h0000644000000000000000000001051415004363604015525 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOControl_COMMON_H__ #define __EOControl_COMMON_H__ #include #include #include #include #import #import #ifndef ASSIGN # define ASSIGN(object, value) \ ({id __object = (id)object; \ id __value = (id)value; \ if (__value != __object) { if (__value) [__value retain]; \ if (__object) [__object release]; \ object = __value;}}) #endif #ifndef ASSIGNCOPY # define ASSIGNCOPY(object, value) \ ({id __object = (id)object; \ id __value = (id)value; \ if (__value != __object) { if (__value) __value = [__value copy]; \ if (__object) [__object release]; \ object = __value;}}) #endif // ******************** common functions ******************** static inline char* Strdup(const char*) __attribute__((unused)); static inline char* Strcpy (char*, const char*) __attribute__((unused)); static inline char* Strncpy (char*, const char*, unsigned) __attribute__((unused)); static inline char* Strcat (char*, const char*) __attribute__((unused)); static inline char* Strncat (char*, const char*, unsigned) __attribute__((unused)); static inline int Strcmp(const char*, const char*) __attribute__((unused)); static inline int Strncmp(const char*, const char*, unsigned) __attribute__((unused)); static inline int Atoi(const char*) __attribute__((unused)); static inline long Atol(const char*) __attribute__((unused)); #define Malloc malloc #define Calloc calloc #define Realloc realloc #define Free(__p__) if(__p__) { free(__p__); __p__ = NULL; } #define Strlen(__s__) (__s__?strlen(__s__):0) static inline char *Strdup(const char *s) { return s ? strcpy(Malloc(strlen(s) + 1), s) : NULL; } static inline char* Strcpy (char *d, const char *s) { return s && d ? strcpy(d, s) : d; } static inline char* Strncpy (char* d, const char* s, unsigned size) { return s && d ? strncpy(d, s, size) : d; } static inline char* Strcat (char* d, const char* s) { return s && d ? strcat(d, s) : d; } static inline char* Strncat (char* d, const char* s , unsigned size) { return s && d ? strncat(d, s , size) : d; } static inline int Strcmp(const char* p, const char* q) { if(p == NULL) { if(!q) return 0; else return -1; } else { if(!q) return 1; else return strcmp(p, q); } } static inline int Strncmp(const char* p, const char* q, unsigned size) { if(!p) { if(!q) return 0; else return -1; } else { if(!q) return 1; else return strncmp(p, q, size); } } static inline int Atoi(const char* str) { return str ? atoi(str) : 0; } static inline long Atol(const char *str) { return str ? atol(str) : 0; } #ifndef MAX #define MAX(a, b) \ ({typedef _ta = (a), _tb = (b); \ _ta _a = (a); _tb _b = (b); \ _a > _b ? _a : _b; }) #endif #ifndef MIN #define MIN(a, b) \ ({typedef _ta = (a), _tb = (b); \ _ta _a = (a); _tb _b = (b); \ _a < _b ? _a : _b; }) #endif static inline char *Ltoa(long nr, char *str, int base) { char buff[34], rest, is_negative; int ptr; ptr = 32; buff[33] = '\0'; if (nr < 0) { is_negative = 1; nr = -nr; } else is_negative = 0; while (nr != 0) { rest = nr % base; if (rest > 9) rest += 'A' - 10; else rest += '0'; buff[ptr--] = rest; nr /= base; } if (ptr == 32) buff[ptr--] = '0'; if (is_negative) buff[ptr--] = '-'; Strcpy(str, &buff[ptr+1]); return(str); } #endif /* __EOControl_COMMON_H__ */ SOPE/sope-core/EOControl/EOAndQualifier.m0000644000000000000000000001734315004363604017041 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "common.h" @interface EOQualifier(EvalContext) - (BOOL)evaluateWithObject:(id)_object inEvalContext:(id)_ctx; @end @implementation EOAndQualifier static BOOL debugEval = NO; static BOOL debugTransform = NO; + (void)initialize { debugEval = [EOQualifier isEvaluationDebuggingEnabled]; } - (id)initWithQualifierArray:(NSArray *)_qualifiers { self->count = [_qualifiers count]; self->qualifiers = [_qualifiers copyWithZone:[self zone]]; return self; } - (id)initWithQualifiers:(EOQualifier *)_qual1, ... { va_list va; EOQualifier *q; id *qs; unsigned c; NSArray *a; va_start(va, _qual1); for (c = 0, q = _qual1; q != nil; q = va_arg(va, id), c++) ; va_end(va); if (c == 0) return [self initWithQualifierArray:nil]; qs = calloc(c, sizeof(id)); va_start(va, _qual1); for (c = 0, q = _qual1; q != nil; q = va_arg(va, id), c++) { qs[c] = q; } va_end(va); a = [NSArray arrayWithObjects:qs count:c]; if (qs) free(qs); return [self initWithQualifierArray:a]; } - (void)dealloc { [self->qualifiers release]; [super dealloc]; } - (NSArray *)qualifiers { return self->qualifiers; } - (NSArray *)subqualifiers { return [self qualifiers]; } /* bindings */ - (EOQualifier *)qualifierWithBindings:(NSDictionary *)_bindings requiresAllVariables:(BOOL)_reqAll { NSArray *array; id objects[self->count + 1]; unsigned i; id (*objAtIdx)(id,SEL,unsigned); objAtIdx = (void *) [self->qualifiers methodForSelector:@selector(objectAtIndex:)]; for (i = 0; i < self->count; i++) { id q, newq; q = objAtIdx(self->qualifiers, @selector(objectAtIndex:), i); newq = [q qualifierWithBindings:_bindings requiresAllVariables:_reqAll]; if (newq == nil) newq = q; objects[i] = newq; } array = [NSArray arrayWithObjects:objects count:self->count]; return [[[[self class] alloc] initWithQualifierArray:array] autorelease]; } - (NSArray *)bindingKeys { NSMutableSet *keys = nil; unsigned i; IMP objAtIdx; objAtIdx = [self->qualifiers methodForSelector:@selector(objectAtIndex:)]; for (i = 0; i < self->count; i++) { NSArray *qb; id q; q = objAtIdx(self->qualifiers, @selector(objectAtIndex:), i); qb = [q bindingKeys]; if ([qb count] > 0) { if (keys == nil) keys = [NSMutableSet setWithCapacity:16]; [keys addObjectsFromArray:qb]; } } return keys ? [keys allObjects] : (NSArray *)[NSArray array]; } /* keys */ - (void)addQualifierKeysToSet:(NSMutableSet *)_keys { /* new in WO 4.5 */ [self->qualifiers makeObjectsPerformSelector:_cmd withObject:_keys]; } /* evaluation */ - (BOOL)evaluateWithObject:(id)_object inEvalContext:(id)_ctx { unsigned i; IMP objAtIdx; if ((_ctx == nil) && (self->count > 1)) _ctx = [NSMutableDictionary dictionaryWithCapacity:16]; objAtIdx = [self->qualifiers methodForSelector:@selector(objectAtIndex:)]; for (i = 0; i < self->count; i++) { id q; q = objAtIdx(self->qualifiers, @selector(objectAtIndex:), i); if (![q evaluateWithObject:_object inEvalContext:_ctx]) { if (debugEval) { NSLog(@"Eval: EOAndQualifier '%@':\n qualifier[%i]: '%@'\n" @" failed on object '%@'", self, i+1, q, _object); } return NO; } } if (debugEval) { NSLog(@"Eval: EOAndQualifier '%@':\n true on object '%@'", self, _object); } return YES; } - (BOOL)evaluateWithObject:(id)_object { return [self evaluateWithObject:_object inEvalContext:nil]; } /* NSCoding */ - (void)encodeWithCoder:(NSCoder *)_coder { [_coder encodeObject:self->qualifiers]; } - (id)initWithCoder:(NSCoder *)_coder { self->qualifiers = [[_coder decodeObject] retain]; return self; } /* Comparing */ - (BOOL)isEqualToQualifier:(EOQualifier *)_qual { return [self->qualifiers isEqualToArray:[(EOAndQualifier *)_qual qualifiers]]; } /* remapping keys */ - (EOQualifier *)qualifierByApplyingTransformer:(id)_transformer inContext:(id)_ctx { if ([_transformer respondsToSelector: @selector(transformAndQualifier:inContext:)]) { if (debugTransform) NSLog(@"transformer: %@\n transform: %@", _transformer, self); return [_transformer transformAndQualifier:self inContext:_ctx]; } else { EOAndQualifier *aq; NSArray *a; id *qs; unsigned i; BOOL didTransform = NO; if (debugTransform) { NSLog(@"EOAndQualifier: transform %i using %@ ...", self->count, _transformer); } qs = calloc(self->count + 1, sizeof(id)); for (i = 0; i < self->count; i++) { EOQualifier *q; q = [self->qualifiers objectAtIndex:i]; qs[i] = [q qualifierByApplyingTransformer:_transformer inContext:_ctx]; if (qs[i] == nil) qs[i] = q; else if (qs[i] != q) { if (debugTransform) NSLog(@"EOAndQualifier: subqualifier %i did transform", i); didTransform = YES; } else if (debugTransform) NSLog(@"EOAndQualifier: subqualifier %i did not transform", i); } if (didTransform) { a = [[NSArray alloc] initWithObjects:qs count:self->count]; if (qs) free(qs); aq = [[EOAndQualifier alloc] initWithQualifierArray:a]; [a release]; return [aq autorelease]; } else { if (qs) free(qs); return [[self retain] autorelease]; } } } - (EOQualifier *)qualifierByApplyingKeyMap:(NSDictionary *)_map { EOAndQualifier *aq; NSArray *a; id *qs; unsigned i; qs = calloc(self->count + 1, sizeof(id)); for (i = 0; i < self->count; i++) { EOQualifier *q; q = [self->qualifiers objectAtIndex:i]; qs[i] = [q qualifierByApplyingKeyMap:_map]; if (qs[i] == nil) qs[i] = q; } a = [[NSArray alloc] initWithObjects:qs count:self->count]; if (qs) free(qs); aq = [[EOAndQualifier alloc] initWithQualifierArray:a]; [a release]; return [aq autorelease]; } /* key/value archiving */ - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { if ((self = [super initWithKeyValueUnarchiver:_unarchiver]) != nil) { self->qualifiers = [[_unarchiver decodeObjectForKey:@"qualifiers"] copy]; self->count = [self->qualifiers count]; } return self; } - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver { [super encodeWithKeyValueArchiver:_archiver]; [_archiver encodeObject:[self qualifiers] forKey:@"qualifiers"]; } /* description */ - (NSString *)description { NSMutableString *ms; NSArray *sd; unsigned i, len; sd = [self->qualifiers valueForKey:@"qualifierDescription"]; if ((len = [sd count]) == 0) return nil; if (len == 1) return [sd objectAtIndex:0]; ms = [NSMutableString stringWithCapacity:(len * 16)]; [ms appendString:@"("]; for (i = 0; i < len; i++) { if (i != 0) [ms appendString:@" AND "]; [ms appendString:[sd objectAtIndex:i]]; } [ms appendString:@")"]; return ms; } @end /* EOAndQualifier */ SOPE/sope-core/EOControl/EODataSource.h0000644000000000000000000000263515004363604016520 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOControl_EODataSource_H__ #define __EOControl_EODataSource_H__ #import @class NSArray, NSEnumerator; @class EOClassDescription; @interface EODataSource : NSObject /* reflection */ - (EOClassDescription *)classDescriptionForObjects; /* master-detail */ - (EODataSource *)dataSourceQualifiedByKey:(NSString *)_relKey; - (void)qualifyWithRelationshipKey:(NSString *)_relKey ofObject:(id)_object; /* operations */ - (NSArray *)fetchObjects; - (void)deleteObject:(id)_object; - (void)insertObject:(id)_object; - (id)createObject; - (NSEnumerator *)fetchEnumerator; @end #endif /* __EOControl_EODataSource_H__ */ SOPE/sope-core/EOControl/EOQualifier.h0000644000000000000000000001612015004363604016401 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOQualifier_h__ #define __EOQualifier_h__ #import #include /* EOQualifier EOQualifier is the superclass of all the concrete qualifier classes which are used to build up a qualification object hierarchy (aka a SQL where statement). Subclasses: EOAndQualifier EOOrQualifier EONotQualifier EOKeyValueQualifier EOKeyComparisonQualifier EOQualifierVariable EOQualifierVariable defers the evaluation of some qualification value to runtime. It's comparable to SQL late-binding variables (aka "a=$value"). Also provided are some categories on NSObject and NSArray to filter an in-memory object tree. */ @class NSDictionary, NSArray, NSSet, NSMutableSet; @protocol EOQualifierEvaluation - (BOOL)evaluateWithObject:(id)_object; @end @interface EOQualifier : NSObject < NSCopying, EOKeyValueArchiving > + (EOQualifier *)qualifierToMatchAnyValue:(NSDictionary *)_values; + (EOQualifier *)qualifierToMatchAllValues:(NSDictionary *)_values; + (SEL)operatorSelectorForString:(NSString *)_str; + (NSString *)stringForOperatorSelector:(SEL)_sel; /* bindings */ - (EOQualifier *)qualifierWithBindings:(NSDictionary *)_bindings requiresAllVariables:(BOOL)_reqAll; - (NSArray *)bindingKeys; /* keys (new in WO 4.5) */ - (NSSet *)allQualifierKeys; - (void)addQualifierKeysToSet:(NSMutableSet *)_keys; /* comparing */ - (BOOL)isEqual:(id)_obj; - (BOOL)isEqualToQualifier:(EOQualifier *)_qual; /* remapping keys */ - (EOQualifier *)qualifierByApplyingTransformer:(id)_t inContext:(id)_ctx; - (EOQualifier *)qualifierByApplyingKeyMap:(NSDictionary *)_map; /* BDControl additions */ - (NSUInteger)count; - (NSArray *)subqualifiers; /* debugging */ + (BOOL)isEvaluationDebuggingEnabled; @end /* EOQualifier */ @interface EOQualifier(Parsing) + (EOQualifier *)qualifierWithQualifierFormat:(NSString *)_qualifierFormat, ...; + (EOQualifier *)qualifierWithQualifierFormat:(NSString *)_qualifierFormat arguments:(NSArray *)_arguments; /* this is used in "cast (xxx as mytypename)" expressions */ + (void)registerValueClass:(Class)_valueClass forTypeName:(NSString *)_type; @end @interface EOAndQualifier : EOQualifier < EOQualifierEvaluation, NSCoding > { NSArray *qualifiers; unsigned count; } - (id)initWithQualifierArray:(NSArray *)_qualifiers; - (id)initWithQualifiers:(EOQualifier *)_qual1, ...; - (NSArray *)qualifiers; @end /* EOAndQualifier */ @interface EOOrQualifier : EOQualifier < EOQualifierEvaluation, NSCoding > { NSArray *qualifiers; unsigned count; } - (id)initWithQualifierArray:(NSArray *)_qualifiers; /* designated init */ - (id)initWithQualifiers:(EOQualifier *)_qual1, ...; - (NSArray *)qualifiers; @end /* EOOrQualifier */ @interface EONotQualifier : EOQualifier < EOQualifierEvaluation, NSCoding > { EOQualifier *qualifier; } - (id)initWithQualifier:(EOQualifier *)_qualifier; /* designated init */ - (EOQualifier *)qualifier; @end /* EONotQualifier */ extern SEL EOQualifierOperatorEqual; extern SEL EOQualifierOperatorNotEqual; extern SEL EOQualifierOperatorLessThan; extern SEL EOQualifierOperatorGreaterThan; extern SEL EOQualifierOperatorLessThanOrEqualTo; extern SEL EOQualifierOperatorGreaterThanOrEqualTo; extern SEL EOQualifierOperatorContains; extern SEL EOQualifierOperatorLike; extern SEL EOQualifierOperatorCaseInsensitiveLike; @interface EOKeyValueQualifier : EOQualifier < EOQualifierEvaluation, NSCoding > { /* this is a '%A selector %@' qualifier */ NSString *key; id value; SEL operator; BOOL formatted; } - (id)initWithKey:(NSString *)_key operatorSelector:(SEL)_selector value:(id)_value; - (NSString *)key; - (SEL)selector; - (id)value; - (void) setValue: (id) _value; - (BOOL) formatted; - (void) setFormatted: (BOOL) _formatted; @end @interface EOKeyComparisonQualifier : EOQualifier < EOQualifierEvaluation, NSCoding > { /* this is a '%A selector %A' qualifier */ NSString *leftKey; NSString *rightKey; SEL operator; } - (id)initWithLeftKey:(NSString *)_leftKey operatorSelector:(SEL)_selector rightKey:(NSString *)_rightKey; - (NSString *)leftKey; - (NSString *)rightKey; - (SEL)selector; @end /* operators */ #define EOQualifierOperatorEqual @selector(isEqualTo:) #define EOQualifierOperatorNotEqual @selector(isNotEqualTo:) #define EOQualifierOperatorLessThan @selector(isLessThan:) #define EOQualifierOperatorGreaterThan @selector(isGreaterThan:) #define EOQualifierOperatorLessThanOrEqualTo @selector(isLessThanOrEqualTo:) #define EOQualifierOperatorGreaterThanOrEqualTo @selector(isGreaterThanOrEqualTo:) #define EOQualifierOperatorContains @selector(doesContain:) #define EOQualifierOperatorLike @selector(isLike:) #define EOQualifierOperatorCaseInsensitiveLike @selector(isCaseInsensitiveLike:) /* variable qualifier content */ @interface EOQualifierVariable : NSObject < NSCoding, EOKeyValueArchiving > { NSString *varKey; } + (id)variableWithKey:(NSString *)_key; - (id)initWithKey:(NSString *)_key; - (NSString *)key; /* Comparing */ - (BOOL)isEqual:(id)_obj; - (BOOL)isEqualToQualifierVariable:(EOQualifierVariable *)_obj; @end /* define the appropriate selectors */ @interface NSObject(QualifierComparisions) - (BOOL)isEqualTo:(id)_object; - (BOOL)isNotEqualTo:(id)_object; - (BOOL)isLessThan:(id)_object; - (BOOL)isGreaterThan:(id)_object; - (BOOL)isLessThanOrEqualTo:(id)_object; - (BOOL)isGreaterThanOrEqualTo:(id)_object; - (BOOL)doesContain:(id)_object; - (BOOL)isLike:(NSString *)_object; - (BOOL)isCaseInsensitiveLike:(NSString *)_object; @end @interface NSObject(EOQualifierTransformer) - (EOQualifier *)transformQualifier:(EOQualifier *)_q inContext:(id)_ctx; - (EOQualifier *)transformAndQualifier:(EOAndQualifier *)_q inContext:(id)_ctx; - (EOQualifier *)transformOrQualifier:(EOOrQualifier *)_q inContext:(id)_ctx; - (EOQualifier *)transformNotQualifier:(EONotQualifier *)_q inContext:(id)_ctx; - (EOQualifier *)transformKeyValueQualifier:(EOKeyValueQualifier *)_q inContext:(id)_ctx; - (EOQualifier *)transformKeyComparisonQualifier:(EOKeyComparisonQualifier *)q inContext:(id)_ctx; @end /* array qualification */ #import @interface NSArray(Qualification) - (NSArray *)filteredArrayUsingQualifier:(EOQualifier *)_qualifier; @end #endif /* __EOQualifier_h__ */ SOPE/sope-core/EOControl/EOKeyGlobalID.h0000644000000000000000000000277015004363604016554 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOControl_EOKeyGlobalID_H__ #define __EOControl_EOKeyGlobalID_H__ #include @class NSArray; /* An immutable global id based on primary key values. The values must be passed in the alphabetical order of the attribute named. This class cannot be subclassed !!! */ @interface EOKeyGlobalID : EOGlobalID < NSCoding > { @protected NSString *entityName; unsigned int count; id values[1]; } + (id)globalIDWithEntityName:(NSString *)_name keys:(id *)_keyValues keyCount:(unsigned int)_count zone:(NSZone *)_zone; /* accessors */ - (NSString *)entityName; - (unsigned int)keyCount; - (id *)keyValues; - (NSArray *)keyValuesArray; @end #endif /* __EOControl_EOKeyGlobalID_H__ */ SOPE/sope-core/EOControl/EOOrQualifier.m0000644000000000000000000001646215004363604016720 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "common.h" @interface EOQualifier(EvalContext) - (BOOL)evaluateWithObject:(id)_object inEvalContext:(id)_ctx; @end @implementation EOOrQualifier //static BOOL debugEval = NO; static BOOL debugTransform = NO; - (id)initWithQualifierArray:(NSArray *)_qualifiers { self->count = [_qualifiers count]; self->qualifiers = [_qualifiers copyWithZone:[self zone]]; return self; } - (id)initWithQualifiers:(EOQualifier *)_qual1, ... { va_list va; EOQualifier *q; id *qs; unsigned c; NSArray *a; va_start(va, _qual1); for (c = 0, q = _qual1; q != nil; q = va_arg(va, id), c++) ; va_end(va); if (c == 0) return [self initWithQualifierArray:nil]; qs = calloc(c, sizeof(id)); va_start(va, _qual1); for (c = 0, q = _qual1; q != nil; q = va_arg(va, id), c++) { qs[c] = q; } va_end(va); a = [NSArray arrayWithObjects:qs count:c]; free(qs); return [self initWithQualifierArray:a]; } - (void)dealloc { [self->qualifiers release]; [super dealloc]; } /* accessors */ - (NSArray *)qualifiers { return self->qualifiers; } - (NSArray *)subqualifiers { return [self qualifiers]; } /* bindings */ - (EOQualifier *)qualifierWithBindings:(NSDictionary *)_bindings requiresAllVariables:(BOOL)_reqAll { NSArray *array; id objects[self->count + 1]; unsigned i; IMP objAtIdx; objAtIdx = [self->qualifiers methodForSelector:@selector(objectAtIndex:)]; for (i = 0; i < self->count; i++) { id q, newq; q = objAtIdx(self->qualifiers, @selector(objectAtIndex:), i); newq = [q qualifierWithBindings:_bindings requiresAllVariables:_reqAll]; if (newq == nil) newq = q; objects[i] = newq; } array = [NSArray arrayWithObjects:objects count:self->count]; return [[[[self class] alloc] initWithQualifierArray:array] autorelease]; } - (NSArray *)bindingKeys { NSMutableSet *keys = nil; unsigned i; IMP objAtIdx; objAtIdx = [self->qualifiers methodForSelector:@selector(objectAtIndex:)]; for (i = 0; i < self->count; i++) { NSArray *qb; id q; q = objAtIdx(self->qualifiers, @selector(objectAtIndex:), i); qb = [q bindingKeys]; if ([qb count] > 0) { if (keys == nil) keys = [NSMutableSet setWithCapacity:16]; [keys addObjectsFromArray:qb]; } } return keys ? [keys allObjects] : (NSArray *)[NSArray array]; } /* keys */ - (void)addQualifierKeysToSet:(NSMutableSet *)_keys { /* new in WO 4.5 */ [self->qualifiers makeObjectsPerformSelector:_cmd withObject:_keys]; } /* evaluation */ - (BOOL)evaluateWithObject:(id)_object inEvalContext:(id)_ctx { unsigned i; IMP objAtIdx; if ((_ctx == nil) && (self->count > 1)) _ctx = [NSMutableDictionary dictionaryWithCapacity:16]; objAtIdx = [self->qualifiers methodForSelector:@selector(objectAtIndex:)]; for (i = 0; i < self->count; i++) { id q; q = objAtIdx(self->qualifiers, @selector(objectAtIndex:), i); if ([q evaluateWithObject:_object inEvalContext:_ctx]) return YES; } return NO; } - (BOOL)evaluateWithObject:(id)_object { return [self evaluateWithObject:_object inEvalContext:nil]; } /* NSCoding */ - (void)encodeWithCoder:(NSCoder *)_coder { [_coder encodeObject:self->qualifiers]; } - (id)initWithCoder:(NSCoder *)_coder { self->qualifiers = [[_coder decodeObject] retain]; return self; } /* Comparing */ - (BOOL)isEqualToQualifier:(EOQualifier *)_qual { return [self->qualifiers isEqualToArray:[(EOOrQualifier *)_qual qualifiers]]; } /* remapping keys */ - (EOQualifier *)qualifierByApplyingTransformer:(id)_transformer inContext:(id)_ctx { if ([_transformer respondsToSelector: @selector(transformOrQualifier:inContext:)]) { if (debugTransform) NSLog(@"transformer: %@\n transform: %@", _transformer, self); return [_transformer transformOrQualifier:self inContext:_ctx]; } else { EOOrQualifier *aq; NSArray *a; id *qs; unsigned i; BOOL didTransform = NO; if (debugTransform) { NSLog(@"EOOrQualifier: transform %i using %@ ...", self->count, _transformer); } qs = calloc(self->count + 1, sizeof(id)); for (i = 0; i < self->count; i++) { EOQualifier *q; q = [self->qualifiers objectAtIndex:i]; qs[i] = [q qualifierByApplyingTransformer:_transformer inContext:_ctx]; if (qs[i] == nil) qs[i] = q; else if (qs[i] != q) { if (debugTransform) NSLog(@"EOOrQualifier: subqualifier %i did transform", i); didTransform = YES; } else if (debugTransform) NSLog(@"EOOrQualifier: subqualifier %i did not transform", i); } if (didTransform) { a = [[NSArray alloc] initWithObjects:qs count:self->count]; if (qs) free(qs); aq = [[EOOrQualifier alloc] initWithQualifierArray:a]; [a release]; return [aq autorelease]; } else { if (qs) free(qs); return [[self retain] autorelease]; } } } - (EOQualifier *)qualifierByApplyingKeyMap:(NSDictionary *)_map { EOOrQualifier *aq; NSArray *a; id *qs; unsigned i; qs = calloc(self->count + 1, sizeof(id)); for (i = 0; i < self->count; i++) { EOQualifier *q; q = [self->qualifiers objectAtIndex:i]; qs[i] = [q qualifierByApplyingKeyMap:_map]; if (qs[i] == nil) qs[i] = q; } a = [[NSArray alloc] initWithObjects:qs count:self->count]; if (qs) free(qs); aq = [[EOOrQualifier alloc] initWithQualifierArray:a]; [a release]; return [aq autorelease]; } /* key/value archiving */ - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { if ((self = [super initWithKeyValueUnarchiver:_unarchiver]) != nil) { self->qualifiers = [[_unarchiver decodeObjectForKey:@"qualifiers"] copy]; self->count = [self->qualifiers count]; } return self; } - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver { [super encodeWithKeyValueArchiver:_archiver]; [_archiver encodeObject:[self qualifiers] forKey:@"qualifiers"]; } /* description */ - (NSString *)description { NSMutableString *ms; NSArray *sd; unsigned i, len; sd = [self->qualifiers valueForKey:@"qualifierDescription"]; if ((len = [sd count]) == 0) return nil; if (len == 1) return [sd objectAtIndex:0]; ms = [NSMutableString stringWithCapacity:(len * 16)]; [ms appendString:@"("]; for (i = 0; i < len; i++) { if (i != 0) [ms appendString:@" OR "]; [ms appendString:[sd objectAtIndex:i]]; } [ms appendString:@")"]; return ms; } @end /* EOOrQualifier */ SOPE/sope-core/EOControl/EOSortOrdering.h0000644000000000000000000000430615004363604017104 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOControl_EOSortOrdering_H__ #define __EOControl_EOSortOrdering_H__ #import #include #include @class NSDictionary, NSString; #define EOCompareAscending @selector(compareAscending:) #define EOCompareDescending @selector(compareDescending:) #define EOCompareCaseInsensitiveAscending @selector(compareCaseInsensitiveAscending:) #define EOCompareCaseInsensitiveDescending @selector(compareCaseInsensitiveDescending:) @interface EOSortOrdering : NSObject < EOKeyValueArchiving > { NSString *key; SEL selector; } + (EOSortOrdering *)sortOrderingWithKey:(NSString *)_key selector:(SEL)_selector; - (id)initWithKey:(NSString *)_key selector:(SEL)_selector; /* accessors */ - (NSString *)key; - (SEL)selector; /* remapping keys */ - (EOSortOrdering *)sortOrderingByApplyingKeyMap:(NSDictionary *)_map; @end #import @interface NSArray(EOSortOrdering) - (NSArray *)sortedArrayUsingKeyOrderArray:(NSArray *)_orderings; @end @interface NSMutableArray(EOSortOrdering) - (void)sortUsingKeyOrderArray:(NSArray *)_orderings; @end #import @interface NSString(EOSortOrdering) - (int)compareAscending:(id)_object; - (int)compareDescending:(id)_object; - (int)compareCaseInsensitiveAscending:(id)_object; - (int)compareCaseInsensitiveDescending:(id)_object; @end #endif /* __EOControl_EOSortOrdering_H__ */ SOPE/sope-core/EOControl/EOArrayDataSource.h0000644000000000000000000000235615004363604017517 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOArrayDataSource_H__ #define __EOArrayDataSource_H__ #include @class NSArray, NSMutableArray; @class EOFetchSpecification; @interface EOArrayDataSource : EODataSource { NSMutableArray *objects; EOFetchSpecification *fetchSpecification; } - (void)setFetchSpecification:(EOFetchSpecification *)_fspec; - (EOFetchSpecification *)fetchSpecification; - (void)setArray:(NSArray *)_array; @end #endif /* __EOArrayDataSource_H__ */ SOPE/sope-core/EOControl/COPYING0000644000000000000000000006130315004363604015121 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-core/EOControl/EOArrayDataSource.m0000644000000000000000000000544515004363604017526 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include "common.h" @interface EODataSource(PostChange) - (void)postDataSourceChangedNotification; @end @implementation EOArrayDataSource - (id)init { if ((self = [super init])) { self->objects = [[NSMutableArray alloc] init]; } return self; } - (void)dealloc { [self->fetchSpecification release]; [self->objects release]; [super dealloc]; } /* accessors */ - (void)setFetchSpecification:(EOFetchSpecification *)_fspec { if ([self->fetchSpecification isEqual:_fspec]) return; [self->fetchSpecification autorelease]; self->fetchSpecification = [_fspec copy]; [self postDataSourceChangedNotification]; } - (EOFetchSpecification *)fetchSpecification { return self->fetchSpecification; } - (void)setArray:(NSArray *)_array { [self->objects removeAllObjects]; [self->objects addObjectsFromArray:_array]; } /* fetching */ - (NSArray *)fetchObjects { NSArray *result; if (self->fetchSpecification == nil) { result = [[self->objects copy] autorelease]; } else { EOQualifier *q; NSArray *sort; q = [self->fetchSpecification qualifier]; sort = [self->fetchSpecification sortOrderings]; if (q == nil) { if (sort) result = [self->objects sortedArrayUsingKeyOrderArray:sort]; else result = [[self->objects copy] autorelease]; } else { result = [self->objects filteredArrayUsingQualifier:q]; if (sort) result = [result sortedArrayUsingKeyOrderArray:sort]; } } return result; } /* operations */ - (void)deleteObject:(id)_object { [self->objects removeObjectIdenticalTo:_object]; [self postDataSourceChangedNotification]; } - (void)insertObject:(id)_object { [self->objects addObject:_object]; [self postDataSourceChangedNotification]; } - (id)createObject { return [NSMutableDictionary dictionaryWithCapacity:16]; } @end /* EOArrayDataSource */ SOPE/sope-core/EOControl/fhs.make0000644000000000000000000000201715004363604015502 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) FHS_INCLUDE_DIR=$(FHS_INSTALL_ROOT)/include/ FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib/ FHS_BIN_DIR=$(FHS_INSTALL_ROOT)/bin/ ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib64/ else FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib/ endif fhs-header-dirs :: $(MKDIRS) $(FHS_INCLUDE_DIR)$(libEOControl_HEADER_FILES_INSTALL_DIR) move-headers-to-fhs :: fhs-header-dirs @echo "moving headers to $(FHS_INCLUDE_DIR) .." mv -f $(GNUSTEP_HEADERS)$(libEOControl_HEADER_FILES_INSTALL_DIR)/*.h \ $(FHS_INCLUDE_DIR)$(libEOControl_HEADER_FILES_INSTALL_DIR)/ NONFHS_LIBDIR="$(GNUSTEP_LIBRARIES)/$(GNUSTEP_TARGET_LDIR)/" NONFHS_LIBNAME="$(LIBRARY_NAME)$(LIBRARY_NAME_SUFFIX)$(SHARED_LIBEXT)" move-libs-to-fhs :: @echo "moving libs to $(FHS_LIB_DIR) .." mv -f $(NONFHS_LIBDIR)/$(NONFHS_LIBNAME)* $(FHS_LIB_DIR)/ move-to-fhs :: move-headers-to-fhs move-libs-to-fhs after-install :: move-to-fhs endif SOPE/sope-core/EOControl/EONotQualifier.m0000644000000000000000000001023115004363604017064 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "common.h" @interface NSObject(QualifierDescription) - (NSString *)qualifierDescription; @end @interface EOQualifier(EvalContext) - (BOOL)evaluateWithObject:(id)_object inEvalContext:(id)_ctx; @end @implementation EONotQualifier - (id)initWithQualifier:(EOQualifier *)_qualifier { self->qualifier = [_qualifier retain]; return self; } - (void)dealloc { [self->qualifier release]; [super dealloc]; } /* accessors */ - (EOQualifier *)qualifier { return self->qualifier; } - (NSUInteger)count { return self->qualifier ? 1 : 0; } - (NSArray *)subqualifiers { return self->qualifier ? [NSArray arrayWithObject:self->qualifier] : nil; } /* bindings */ - (EOQualifier *)qualifierWithBindings:(NSDictionary *)_bindings requiresAllVariables:(BOOL)_reqAll { EOQualifier *nq; nq = [self->qualifier qualifierWithBindings:_bindings requiresAllVariables:_reqAll]; if (nq == nil) return self; if (nq == self->qualifier) return self; return [[[[self class] alloc] initWithQualifier:nq] autorelease]; } - (NSArray *)bindingKeys { return [self->qualifier bindingKeys]; } /* keys */ - (void)addQualifierKeysToSet:(NSMutableSet *)_keys { /* new in WO 4.5 */ [self->qualifier addQualifierKeysToSet:_keys]; } /* evaluation */ - (BOOL)evaluateWithObject:(id)_object inEvalContext:(id)_ctx { return [self->qualifier evaluateWithObject:_object inEvalContext:_ctx] ? NO : YES; } - (BOOL)evaluateWithObject:(id)_object { return [self evaluateWithObject:_object inEvalContext:nil]; } /* NSCoding */ - (void)encodeWithCoder:(NSCoder *)_coder { [_coder encodeObject:self->qualifier]; } - (id)initWithCoder:(NSCoder *)_coder { self->qualifier = [[_coder decodeObject] retain]; return self; } /* Comparing */ - (BOOL)isEqualToQualifier:(EOQualifier *)_qual { return [self->qualifier isEqual:[(EONotQualifier *)_qual qualifier]]; } /* remapping keys */ - (EOQualifier *)qualifierByApplyingTransformer:(id)_transformer inContext:(id)_ctx { if ([_transformer respondsToSelector: @selector(transformNotQualifier:inContext:)]) { return [_transformer transformNotQualifier:self inContext:_ctx]; } else { EONotQualifier *nq; EOQualifier *q; q = [self->qualifier qualifierByApplyingTransformer:_transformer inContext:_ctx]; nq = [[EONotQualifier alloc] initWithQualifier:(q ? q : self->qualifier)]; return [nq autorelease]; } } - (EOQualifier *)qualifierByApplyingKeyMap:(NSDictionary *)_map { EONotQualifier *nq; EOQualifier *q; q = [self->qualifier qualifierByApplyingKeyMap:_map]; nq = [[EONotQualifier alloc] initWithQualifier:(q ? q : self->qualifier)]; return [nq autorelease]; } /* key/value archiving */ - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { if ((self = [super initWithKeyValueUnarchiver:_unarchiver]) != nil) { self->qualifier = [[_unarchiver decodeObjectForKey:@"qualifier"] copy]; } return self; } - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver { [super encodeWithKeyValueArchiver:_archiver]; [_archiver encodeObject:[self qualifier] forKey:@"qualifier"]; } /* description */ - (NSString *)description { NSString *qd; qd = [self->qualifier qualifierDescription]; return [[@"NOT (" stringByAppendingString:qd] stringByAppendingString:@")"]; } @end /* EONotQualifier */ SOPE/sope-core/EOControl/README0000644000000000000000000000030715004363604014743 0ustar rootrootEOControl ========= TODO: Intro Qualifiers / Sorting / Fetch-Spec ================================= TODO: explain Datasources =========== TODO: explain Primary Keys ============ TODO: explain SOPE/sope-core/EOControl/EOFetchSpecification.m0000644000000000000000000002512515004363604020224 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOFetchSpecification.h" #include "EOQualifier.h" #include "EOSortOrdering.h" #include "common.h" @implementation EOFetchSpecification + (EOFetchSpecification *)fetchSpecificationWithEntityName:(NSString *)_ename qualifier:(EOQualifier *)_qualifier sortOrderings:(NSArray *)_sortOrderings { EOFetchSpecification *fs = nil; fs = [[self alloc] initWithEntityName:_ename qualifier:_qualifier sortOrderings:_sortOrderings usesDistinct:NO isDeep:NO hints:nil]; return [fs autorelease]; } - (id)initWithEntityName:(NSString *)_name qualifier:(EOQualifier *)_qualifier sortOrderings:(NSArray *)_sortOrderings usesDistinct:(BOOL)_dflag isDeep:(BOOL)_isDeep hints:(NSDictionary *)_hints { if ((self = [super init])) { self->entityName = [_name copyWithZone:[self zone]]; self->qualifier = [_qualifier retain]; self->sortOrderings = [_sortOrderings retain]; self->fetchLimit = 0; self->hints = [_hints retain]; self->fsFlags.usesDistinct = _dflag ? 1 : 0; self->fsFlags.deep = _isDeep ? 1 : 0; } return self; } - (id)initWithEntityName:(NSString *)_name qualifier:(EOQualifier *)_qualifier sortOrderings:(NSArray *)_sortOrderings usesDistinct:(BOOL)_dflag { // DEPRECATED // Note: this does not work with GDL2! (and probably not with EOF 4) return [self initWithEntityName:_name qualifier:_qualifier sortOrderings:_sortOrderings usesDistinct:_dflag isDeep:NO hints:nil]; } - (id)init { if ((self = [super init])) { } return self; } - (void)dealloc { [self->hints release]; [self->entityName release]; [self->qualifier release]; [self->sortOrderings release]; [super dealloc]; } /* accessors */ - (void)setEntityName:(NSString *)_name { id tmp; if (_name == self->entityName) return; tmp = self->entityName; self->entityName = [_name copyWithZone:[self zone]]; [tmp release]; } - (NSString *)entityName { return self->entityName; } - (void)setQualifier:(EOQualifier *)_qualifier { ASSIGN(self->qualifier, _qualifier); } - (EOQualifier *)qualifier { return self->qualifier; } - (void)setSortOrderings:(NSArray *)_orderings { ASSIGN(self->sortOrderings, _orderings); } - (NSArray *)sortOrderings { return self->sortOrderings; } - (void)setUsesDistinct:(BOOL)_flag { self->fsFlags.usesDistinct = _flag ? 1 : 0; } - (BOOL)usesDistinct { return self->fsFlags.usesDistinct ? YES : NO; } - (void)setLocksObjects:(BOOL)_flag { self->fsFlags.locksObjects = _flag ? 1 : 0; } - (BOOL)locksObjects { return self->fsFlags.locksObjects ? YES : NO; } - (void)setIsDeep:(BOOL)_flag { self->fsFlags.deep = _flag ? 1 : 0; } - (BOOL)isDeep { return self->fsFlags.deep ? YES : NO; } - (void)setFetchLimit:(unsigned)_limit { self->fetchLimit = _limit; } - (unsigned)fetchLimit { return self->fetchLimit; } - (void)setHints:(NSDictionary *)_hints { ASSIGN(self->hints, _hints); } - (NSDictionary *)hints { return self->hints; } /* bindings */ - (EOFetchSpecification *) fetchSpecificationWithQualifierBindings:(NSDictionary *)_bindings { EOQualifier *q = nil; EOFetchSpecification *newfs = nil; q = [[self qualifier] qualifierWithBindings:_bindings requiresAllVariables:NO]; newfs = [[[self class] alloc] initWithEntityName:[self entityName] qualifier:q sortOrderings:[self sortOrderings] usesDistinct:[self usesDistinct]]; [newfs setLocksObjects:[self locksObjects]]; [newfs setFetchLimit:[self fetchLimit]]; return [newfs autorelease]; } /* GDL2 compatibility */ - (EOFetchSpecification *) fetchSpecificationByApplyingBindings:(NSDictionary *)_bindings { return [self fetchSpecificationWithQualifierBindings:_bindings]; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { EOFetchSpecification *fspec; NSDictionary *hdict; hdict = [[self hints] copy]; fspec = [[[self class] alloc] initWithEntityName:[self entityName] qualifier:[self qualifier] sortOrderings:[self sortOrderings] usesDistinct:[self usesDistinct] isDeep:[self isDeep] hints:hdict]; [fspec setLocksObjects:[self locksObjects]]; [fspec setFetchLimit:[self fetchLimit]]; [hdict release]; return fspec; } /* Equality */ - (BOOL)isEqualToFetchSpecification:(EOFetchSpecification *)_fspec { id t1, t2; if (_fspec == self) return YES; t1 = [self entityName]; t2 = [_fspec entityName]; if (t1 != t2) { if (![t1 isEqualToString:t2]) return NO; } t1 = [self sortOrderings]; t2 = [_fspec sortOrderings]; if (t1 != t2) { if (![t1 isEqual:t2]) return NO; } t1 = [self qualifier]; t2 = [_fspec qualifier]; if (t1 != t2) { if (![t1 isEqual:t2]) return NO; } if ([self usesDistinct] != [_fspec usesDistinct]) return NO; if ([self locksObjects] != [_fspec locksObjects]) return NO; if ([self fetchLimit] != [_fspec fetchLimit]) return NO; t1 = [self hints]; t2 = [_fspec hints]; if (t1 != t2) { if (![t1 isEqual:t2]) return NO; } return YES; } - (BOOL)isEqual:(id)_other { if ([_other isKindOfClass:[EOFetchSpecification class]]) return [self isEqualToFetchSpecification:_other]; return NO; } /* remapping keys */ - (EOFetchSpecification *)fetchSpecificationByApplyingKeyMap:(NSDictionary *)_m { NSAutoreleasePool *pool; EOFetchSpecification *fs; NSMutableDictionary *lHints; EOQualifier *q = nil; NSMutableArray *o = nil; pool = [[NSAutoreleasePool alloc] init]; /* process qualifier */ q = [self->qualifier qualifierByApplyingKeyMap:_m]; /* process attributes */ if (self->hints) { NSArray *a; unsigned len; a = [self->hints objectForKey:@"attributes"]; if ((len = [a count]) > 0) { NSMutableArray *ma; unsigned i; ma = [[NSMutableArray alloc] initWithCapacity:(len + 1)]; for (i = 0; i < len; i++) { NSString *key, *tkey; key = [a objectAtIndex:i]; tkey = [_m objectForKey:key]; [ma addObject:(tkey ? tkey : key)]; } lHints = [self->hints mutableCopy]; [lHints setObject:ma forKey:@"attributes"]; [ma release]; } else lHints = (id)[self->hints retain]; } else lHints = nil; /* process orderings */ if (self->sortOrderings) { unsigned i, len; len = [self->sortOrderings count]; o = [[NSMutableArray alloc] initWithCapacity:len]; for (i = 0; i < len; i++) { EOSortOrdering *so, *tso; so = [self->sortOrderings objectAtIndex:i]; tso = [so sortOrderingByApplyingKeyMap:_m]; [o addObject:tso ? tso : so]; } } else o = nil; /* construct result */ fs = [[EOFetchSpecification alloc] initWithEntityName:self->entityName qualifier:q sortOrderings:o usesDistinct:[self usesDistinct] isDeep:[self isDeep] hints:[self hints]]; [fs setLocksObjects:[self locksObjects]]; [fs setFetchLimit:self->fetchLimit]; if (lHints) { [fs setHints:lHints]; [lHints release]; } [o release]; [pool release]; return [fs autorelease]; } /* key/value archiving */ - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { if ((self = [super init]) != nil) { self->entityName = [[_unarchiver decodeObjectForKey:@"entityName"] copy]; self->qualifier = [[_unarchiver decodeObjectForKey:@"qualifier"] retain]; self->hints = [[_unarchiver decodeObjectForKey:@"hints"] copy]; self->sortOrderings = [[_unarchiver decodeObjectForKey:@"sortOrderings"] retain]; self->fetchLimit = [_unarchiver decodeIntForKey:@"fetchLimit"]; self->fsFlags.usesDistinct = [_unarchiver decodeBoolForKey:@"usesDistinct"] ? 1 : 0; self->fsFlags.locksObjects = [_unarchiver decodeBoolForKey:@"locksObjects"] ? 1 : 0; self->fsFlags.deep = [_unarchiver decodeBoolForKey:@"deep"] ? 1 : 0; } return self; } - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver { [_archiver encodeObject:[self entityName] forKey:@"entityName"]; [_archiver encodeObject:[self qualifier] forKey:@"qualifier"]; [_archiver encodeObject:[self hints] forKey:@"hints"]; [_archiver encodeObject:[self sortOrderings] forKey:@"sortOrderings"]; [_archiver encodeInt:[self fetchLimit] forKey:@"fetchLimit"]; [_archiver encodeBool:self->fsFlags.usesDistinct forKey:@"usesDistinct"]; [_archiver encodeBool:self->fsFlags.locksObjects forKey:@"locksObjects"]; [_archiver encodeBool:self->fsFlags.deep forKey:@"deep"]; } /* description */ - (NSString *)description { NSMutableString *ms; id tmp; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<%@[0x%p]:", NSStringFromClass([self class]), self]; if ((tmp = [self entityName])) [ms appendFormat:@" entity=%@", tmp]; if ((tmp = [self qualifier])) [ms appendFormat:@" qualifier=%@", tmp]; if ((tmp = [self sortOrderings])) [ms appendFormat:@" orderings=%@", tmp]; if ([self locksObjects]) [ms appendString:@" locks"]; if ([self usesDistinct]) [ms appendString:@" distinct"]; if ([self fetchLimit] > 0) [ms appendFormat:@" limit=%i", [self fetchLimit]]; if ((tmp = [self hints])) { NSEnumerator *e; NSString *hint; BOOL isFirst = YES; [ms appendString:@" hints:"]; e = [tmp keyEnumerator]; while ((hint = [e nextObject])) { if (isFirst) isFirst = NO; else [ms appendString:@","]; [ms appendString:hint]; [ms appendString:@"="]; [ms appendString:[[(NSDictionary *)tmp objectForKey:hint] stringValue]]; } } [ms appendString:@">"]; return ms; } @end /* EOFetchSpecification */ SOPE/sope-core/EOControl/EOQualifierVariable.m0000644000000000000000000000461315004363604020060 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOQualifier.h" #include "common.h" @implementation EOQualifierVariable + (id)variableWithKey:(NSString *)_key { return [[[self alloc] initWithKey:_key] autorelease]; } - (id)initWithKey:(NSString *)_key { self->varKey = [_key copyWithZone:[self zone]]; return self; } - (id)init { return [self initWithKey:nil]; } - (void)dealloc { [self->varKey release]; [super dealloc]; } /* accessors */ - (NSString *)key { return self->varKey; } /* NSCoding */ - (void)encodeWithCoder:(NSCoder *)_coder { [_coder encodeObject:self->varKey]; } - (id)initWithCoder:(NSCoder *)_coder { self->varKey = [[_coder decodeObject] copyWithZone:[self zone]]; return self; } /* Comparing */ - (BOOL)isEqual:(id)_obj { if ([_obj isKindOfClass:[self class]]) return [self isEqualToQualifierVariable:(EOQualifierVariable *)_obj]; return NO; } - (BOOL)isEqualToQualifierVariable:(EOQualifierVariable *)_obj { return [self->varKey isEqual:[_obj key]]; } /* key/value archiving */ - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { if ((self = [super init]) != nil) { self->varKey = [[_unarchiver decodeObjectForKey:@"key"] copy]; } return self; } - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver { [_archiver encodeObject:[self key] forKey:@"key"]; } /* description */ - (NSString *)qualifierDescription { return [@"$" stringByAppendingString:[self key]]; } - (NSString *)description { return [NSString stringWithFormat:@"<%@[0x%p]: variable=%@>", NSStringFromClass([self class]), self, [self key]]; } @end /* EOQualifierVariable */ SOPE/sope-core/EOControl/EOGlobalID.h0000644000000000000000000000235015004363604016075 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOControl_EOGlobalID_H__ #define __EOControl_EOGlobalID_H__ #import @class NSArray; @class EOFetchSpecification; #define EOUniqueBinaryKeyLength 12 @interface EOGlobalID : NSObject < NSCopying > { } - (BOOL)isTemporary; @end @interface EOTemporaryGlobalID : EOGlobalID { unsigned char idbuffer[EOUniqueBinaryKeyLength]; } + (void)assignGloballyUniqueBytes:(unsigned char *)_buffer; @end #endif /* __EOControl_EOGlobalID_H__ */ SOPE/sope-core/EOControl/EODataSource.m0000644000000000000000000000433215004363604016521 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "common.h" @implementation EODataSource /* reflection */ - (EOClassDescription *)classDescriptionForObjects { return nil; } /* master-detail */ - (EODataSource *)dataSourceQualifiedByKey:(NSString *)_relKey { [NSException raise:@"NSInvalidArgumentException" format:@"datasource %@ can't return a ds qualified by key '%@'", self, _relKey]; return nil; } - (void)qualifyWithRelationshipKey:(NSString *)_relKey ofObject:(id)_object { [NSException raise:@"NSInvalidArgumentException" format:@"datasource %@ can't qualify by key '%@' of object %@", self, _relKey, _object]; } /* operations */ - (NSArray *)fetchObjects { return nil; } - (NSEnumerator *)fetchEnumerator { return [[self fetchObjects] objectEnumerator]; } - (void)deleteObject:(id)_object { [NSException raise:@"NSInvalidArgumentException" format:@"datasource %@ can't delete object %@", self, _object]; } - (void)insertObject:(id)_object { [NSException raise:@"NSInvalidArgumentException" format:@"datasource %@ can't insert object %@", self, _object]; } - (id)createObject { EOClassDescription *cd; if ((cd = [self classDescriptionForObjects]) == nil) return nil; return [cd createInstanceWithEditingContext:nil globalID:nil zone:NULL]; } @end /* EODataSource */ SOPE/sope-core/EOControl/EOGenericRecord.m0000644000000000000000000002732615004363604017212 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOGenericRecord.h" #include "EONull.h" #include "EOClassDescription.h" #include "EOObserver.h" #include "EOKeyValueCoding.h" #include "common.h" #include @interface NSObject(MappedArray) - (NSArray *)mappedArrayUsingSelector:(SEL)_selector; @end @interface _EOConcreteEOGenericRecordKeyEnumerator : NSEnumerator { EOGenericRecord *dict; struct _NSMapNode *node; int bucket; } + (id)enumWithEO:(EOGenericRecord *)_eo; @end #if !LIB_FOUNDATION_LIBRARY struct _NSMapNode { void *key; void *value; struct _NSMapNode *next; }; #endif @implementation EOGenericRecord /* final methods */ static __inline__ unsigned _getHashSize(EOGenericRecord *self); static __inline__ struct _NSMapNode *_getNodeAt(EOGenericRecord *self, int idx); static BOOL is_prime(unsigned n); static unsigned nextPrime(unsigned old_value); static void eoMapGrow(EOGenericRecord *table, unsigned newSize); static void eoCheckMapTableFull(EOGenericRecord *table); static __inline__ void eoInsert(EOGenericRecord *table, id key, id value); static __inline__ id eoGet(EOGenericRecord *table, id key); static __inline__ void eoRemove(EOGenericRecord *table, id key); static EONull *null = nil; + (NSInteger)version { return 2; } + (void)initialize { if (null == nil) null = [[EONull null] retain]; } - (id)initWithEditingContext:(id)_ec classDescription:(EOClassDescription *)_classDesc globalID:(EOGlobalID *)_oid { unsigned capacity; #if DEBUG NSAssert(_classDesc, @"did not find class description for EOGenericRecord !"); #endif capacity = 16 * 4 / 3; capacity = capacity ? capacity : 13; if (!is_prime(capacity)) capacity = nextPrime(capacity); self->hashSize = capacity; self->nodes = NSZoneCalloc([self zone], capacity, sizeof(void *)); self->itemsCount = 0; self->classDescription = [_classDesc retain]; self->willChange = [self methodForSelector:@selector(willChange)]; return self; } - (id)init { EOClassDescription *c; c = (EOClassDescription *) [EOClassDescription classDescriptionForClass:[self class]]; return [self initWithEditingContext:nil classDescription:c globalID:nil]; } - (void)dealloc { if ([self respondsToSelector:@selector(_letDatabasesForget)]) [self performSelector:@selector(_letDatabasesForget)]; if (self->itemsCount > 0) { NSZone *z = [self zone]; unsigned i; for (i = 0; i < self->hashSize; i++) { struct _NSMapNode *next, *node; node = self->nodes[i]; self->nodes[i] = NULL; while (node) { [(id)node->key release]; [(id)node->value release]; next = node->next; NSZoneFree(z, node); node = next; } } self->itemsCount = 0; } if (self->nodes) NSZoneFree([self zone], self->nodes); [self->classDescription release]; [super dealloc]; } /* class description */ - (NSClassDescription *)classDescription { return self->classDescription; } static inline void _willChange(EOGenericRecord *self) { if (self->willChange) self->willChange(self, @selector(willChange:)); else [self willChange]; } #if GNUSTEP_BASE_LIBRARY - (void)setValue:(id)_value forKey:(NSString *)_key { [self takeValue:_value forKey:_key]; } #endif - (void)takeValue:(id)_value forKey:(NSString *)_key { id value; if (_value == nil) _value = null; #if DEBUG NSAssert1(_key, @"called -takeValue:0x%p forKey:nil !", _value); #endif value = eoGet(self, _key); if (value != _value) { _willChange(self); if (_value == nil) eoRemove(self, _key); else eoInsert(self, _key, _value); } } - (id)valueForKey:(NSString *)_key { id v; if ((v = eoGet(self, _key)) == nil) { #if DEBUG && 0 if ([_key isEqualToString:@"description"]) { NSLog(@"WARNING(%s): -valueForKey:%@ is nil, calling super", __PRETTY_FUNCTION__, _key); } #endif return [super valueForKey:_key]; } #if DEBUG NSAssert(null != nil, @"missing null .."); #endif return v == null ? nil : v; } - (void)takeValuesFromDictionary:(NSDictionary *)dictionary { _willChange(self); { NSEnumerator *e = [dictionary keyEnumerator]; NSString *key; while ((key = [e nextObject])) { id value = [dictionary objectForKey:key]; NSAssert(value, @"tried to set value .."); eoInsert(self, key, value); } } } - (NSDictionary *)valuesForKeys:(NSArray *)keys { // OPT - cache IMP for objectAtIndex, objectForKey, setObject:forKey: NSMutableDictionary *dict; IMP objAtIdx, setObjForKey; unsigned int i, n; if (keys == nil) return nil; n = [keys count]; dict = [NSMutableDictionary dictionaryWithCapacity:n]; objAtIdx = [keys methodForSelector:@selector(objectAtIndex:)]; setObjForKey = [dict methodForSelector:@selector(setObject:forKey:)]; for (i = 0; i < n; i++) { NSString *key; id value; key = objAtIdx(keys, @selector(objectAtIndex:), i); NSAssert(key, @"invalid key "); value = [self valueForKey:key]; if (value == nil) value = null; #if DEBUG NSAssert2(value, @"eo of type %@, missing value for attribute %@", self->classDescription, key); #endif setObjForKey(dict, @selector(setObject:forKey:), value, key); } return dict; } - (void)takeStoredValue:(id)_value forKey:(NSString *)_key { if (_value == nil) _value = null; [self takeValue:_value forKey:_key]; } - (id)storedValueForKey:(NSString *)_key { id v; v = [self valueForKey:_key]; #if DEBUG && 0 NSAssert(v != null, @"valueForKey: return NSNull !"); #endif //if (v == nil) return [super storedValueForKey:_key]; return v; } - (void)setObject:(id)object forKey:(id)key { if (object == nil) object = null; _willChange(self); eoInsert(self, key, object); } - (id)objectForKey:(id)key { return eoGet(self, key); } - (void)removeObjectForKey:(id)key { _willChange(self); eoRemove(self, key); } - (BOOL)kvcIsPreferredInKeyPath { return YES; } - (NSEnumerator *)keyEnumerator { return [_EOConcreteEOGenericRecordKeyEnumerator enumWithEO:self]; } /* copying */ - (id)copyWithZone:(NSZone *)_zone { return [self retain]; } /* description */ - (NSString *)description { return [NSString stringWithFormat: @"", [self entityName], [self valuesForKeys:[self attributeKeys]]]; } /* final methods */ static __inline__ unsigned _getHashSize(EOGenericRecord *self) { return self->hashSize; } static __inline__ struct _NSMapNode * _getNodeAt(EOGenericRecord *self, int idx) { return self->nodes[idx]; } static BOOL is_prime(unsigned n) { int i, n2 = sqrt(n); for (i = 2; i <= n2; i++) { if (n % i == 0) return NO; } return YES; } static unsigned nextPrime(unsigned old_value) { unsigned i, new_value = old_value | 1; for (i = new_value; i >= new_value; i += 2) { if (is_prime(i)) return i; } return old_value; } static void eoMapGrow(EOGenericRecord *table, unsigned newSize) { unsigned i; struct _NSMapNode **newNodeTable; newNodeTable = NSZoneCalloc([table zone], newSize, sizeof(struct _NSMapNode*)); for (i = 0; i < table->hashSize; i++) { struct _NSMapNode *next, *node; unsigned int h; node = table->nodes[i]; while (node) { next = node->next; h = [(id)node->key hash] % newSize; node->next = newNodeTable[h]; newNodeTable[h] = node; node = next; } } NSZoneFree([table zone], table->nodes); table->nodes = newNodeTable; table->hashSize = newSize; } static void eoCheckMapTableFull(EOGenericRecord *table) { if( ++(table->itemsCount) >= ((table->hashSize * 3) / 4)) { unsigned newSize; newSize = nextPrime((table->hashSize * 4) / 3); if(newSize != table->hashSize) eoMapGrow(table, newSize); } } static __inline__ void eoInsert(EOGenericRecord *table, id key, id value) { unsigned int h; struct _NSMapNode *node; h = [key hash] % table->hashSize; for (node = table->nodes[h]; node; node = node->next) { /* might cache the selector .. */ if ([key isEqual:node->key]) break; } /* Check if an entry for key exist in nodeTable. */ if (node) { /* key exist. Set for it new value and return the old value of it. */ if (key != node->key) { key = [key retain]; [(id)node->key release]; } if (value != node->value) { value = [value retain]; [(id)node->value release]; } node->key = key; node->value = value; return; } /* key not found. Allocate a new bucket and initialize it. */ node = NSZoneMalloc([table zone], sizeof(struct _NSMapNode)); key = [key retain]; value = [value retain]; node->key = (void*)key; node->value = (void*)value; node->next = table->nodes[h]; table->nodes[h] = node; eoCheckMapTableFull(table); } static __inline__ id eoGet(EOGenericRecord *table, id key) { struct _NSMapNode *node; node = table->nodes[[key hash] % table->hashSize]; for (; node; node = node->next) { /* could cache method .. */ if ([key isEqual:node->key]) return node->value; } return nil; } static __inline__ void eoRemove(EOGenericRecord *table, id key) { unsigned int h; struct _NSMapNode *node, *node1 = NULL; if (key == nil) return; h = [key hash] % table->hashSize; // node point to current bucket, and node1 to previous bucket or to NULL // if current node is the first node in the list for (node = table->nodes[h]; node; node1 = node, node = node->next) { /* could cache method .. */ if ([key isEqual:node->key]) { [(id)node->key release]; [(id)node->value release]; if (!node1) table->nodes[h] = node->next; else node1->next = node->next; NSZoneFree([table zone], node); (table->itemsCount)--; return; } } } @end /* EOGenericRecord */ @implementation _EOConcreteEOGenericRecordKeyEnumerator - (id)initWithEO:(EOGenericRecord *)_eo { self->dict = [_eo retain]; self->node = NULL; self->bucket = -1; return self; } - (void)dealloc { [self->dict release]; [super dealloc]; } + (id)enumWithEO:(EOGenericRecord *)_eo { return [[[self alloc] initWithEO:_eo] autorelease]; } - (id)nextObject { if (self->node) self->node = self->node->next; if (self->node == NULL) { for(self->bucket++; ((unsigned)self->bucket) < _getHashSize(self->dict); self->bucket++) { if (_getNodeAt(self->dict, self->bucket)) { self->node = _getNodeAt(self->dict, self->bucket); break; } } if (((unsigned)self->bucket) >= _getHashSize(self->dict)) { self->node = NULL; self->bucket = (_getHashSize(self->dict) - 1); return nil; } } return self->node->key; } @end /* _EOConcreteEOGenericRecordKeyEnumerator */ SOPE/sope-core/EOControl/EOFetchSpecification.h0000644000000000000000000000456215004363604020221 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOFetchSpecification_h__ #define __EOFetchSpecification_h__ #import @class NSArray, NSString, NSDictionary; @class EOQualifier; @interface EOFetchSpecification : NSObject < NSCopying > { NSString *entityName; EOQualifier *qualifier; NSArray *sortOrderings; unsigned fetchLimit; NSDictionary *hints; struct { int usesDistinct:1; int locksObjects:1; int deep:1; int reserved:29; } fsFlags; } + (EOFetchSpecification *)fetchSpecificationWithEntityName:(NSString *)_ename qualifier:(EOQualifier *)_qualifier sortOrderings:(NSArray *)sortOrderings; - (id)initWithEntityName:(NSString *)_name qualifier:(EOQualifier *)_qualifier sortOrderings:(NSArray *)_sortOrderings usesDistinct:(BOOL)_dflag isDeep:(BOOL)_isDeep hints:(NSDictionary *)_hints; /* accessors */ - (void)setEntityName:(NSString *)_name; - (NSString *)entityName; - (void)setQualifier:(EOQualifier *)_qualifier; - (EOQualifier *)qualifier; - (void)setSortOrderings:(NSArray *)_orderings; - (NSArray *)sortOrderings; - (void)setUsesDistinct:(BOOL)_flag; - (BOOL)usesDistinct; - (void)setIsDeep:(BOOL)_flag; - (BOOL)isDeep; - (void)setLocksObjects:(BOOL)_flag; - (BOOL)locksObjects; - (void)setFetchLimit:(unsigned)_limit; - (unsigned)fetchLimit; - (void)setHints:(NSDictionary *)_hints; - (NSDictionary *)hints; /* bindings */ - (EOFetchSpecification *)fetchSpecificationWithQualifierBindings:(NSDictionary *)_bindings; /* remapping keys */ - (EOFetchSpecification *)fetchSpecificationByApplyingKeyMap:(NSDictionary *)_m; @end #endif /* __EOFetchSpecification_h__ */ SOPE/sope-core/EOControl/EOGenericRecord.h0000644000000000000000000000371215004363604017176 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOControl_EOGenericRecord_h__ #define __EOControl_EOGenericRecord_h__ #import #import #include @class NSDictionary, NSArray, NSString, NSEnumerator; @class EOClassDescription; /* * EOGeneric record class, used for enterprise objects * that do not have special data handling */ @interface EOGenericRecord : NSObject < NSCopying > { EOClassDescription *classDescription; IMP willChange; /* hash-table */ struct _NSMapNode **nodes; unsigned int hashSize; unsigned int itemsCount; } - (id)initWithEditingContext:(id)_ec classDescription:(EOClassDescription *)_classDesc globalID:(EOGlobalID *)_oid; // Key-value coding methods - (void)takeValuesFromDictionary:(NSDictionary *)dictionary; - (NSDictionary *)valuesForKeys:(NSArray *)keys; // Shortcuts to key-value coding methods - (void)setObject:(id)anObject forKey:(id)aKey; - (id)objectForKey:(id)aKey; - (void)removeObjectForKey:(id)aKey; @end /* EOGenericRecord */ @class NSEnumerator; @interface EOGenericRecord(EOMOF2Extensions) - (NSEnumerator *)keyEnumerator; @end #endif /* __EOControl_EOGenericRecord_h__ */ SOPE/sope-core/EOControl/EOQualifier.m0000644000000000000000000001736715004363604016424 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "EOQualifier.h" #include "EOKeyValueCoding.h" #include "common.h" #include "EONull.h" #import @interface NSObject(QualifierDescription) - (NSString *)qualifierDescription; @end @implementation EOQualifier static NSMapTable *operatorToSelector = NULL; static NSMapTable *selectorToOperator = NULL; static EONull *null = nil; + (void)initialize { if (null == nil) null = [EONull null]; if (operatorToSelector == NULL) { operatorToSelector = NSCreateMapTable(NSObjectMapKeyCallBacks, NSIntMapValueCallBacks, 10); NSMapInsert(operatorToSelector, @"=", EOQualifierOperatorEqual); NSMapInsert(operatorToSelector, @"==", EOQualifierOperatorEqual); NSMapInsert(operatorToSelector, @"!=", EOQualifierOperatorNotEqual); NSMapInsert(operatorToSelector, @"<>", EOQualifierOperatorNotEqual); NSMapInsert(operatorToSelector, @"<", EOQualifierOperatorLessThan); NSMapInsert(operatorToSelector, @">", EOQualifierOperatorGreaterThan); NSMapInsert(operatorToSelector, @"<=", EOQualifierOperatorLessThanOrEqualTo); NSMapInsert(operatorToSelector, @"like",EOQualifierOperatorLike); NSMapInsert(operatorToSelector, @"LIKE",EOQualifierOperatorLike); NSMapInsert(operatorToSelector, @">=", EOQualifierOperatorGreaterThanOrEqualTo); NSMapInsert(operatorToSelector, @"caseInsensitiveLike", EOQualifierOperatorCaseInsensitiveLike); } if (selectorToOperator == NULL) { selectorToOperator = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 10); NSMapInsert(selectorToOperator, NSStringFromSelector(EOQualifierOperatorEqual), @"="); NSMapInsert(selectorToOperator, NSStringFromSelector(EOQualifierOperatorNotEqual), @"<>"); NSMapInsert(selectorToOperator, NSStringFromSelector(EOQualifierOperatorLessThan), @"<"); NSMapInsert(selectorToOperator, NSStringFromSelector(EOQualifierOperatorGreaterThan), @">"); NSMapInsert(selectorToOperator, NSStringFromSelector(EOQualifierOperatorLessThanOrEqualTo), @"<="); NSMapInsert(selectorToOperator, NSStringFromSelector(EOQualifierOperatorLike), @"like"); NSMapInsert(selectorToOperator, NSStringFromSelector(EOQualifierOperatorGreaterThanOrEqualTo), @">="); NSMapInsert(selectorToOperator, NSStringFromSelector(EOQualifierOperatorCaseInsensitiveLike), @"caseInsensitiveLike"); } } + (EOQualifier *)qualifierToMatchAnyValue:(NSDictionary *)_values { /* OR qualifier */ NSEnumerator *keys; NSString *key; NSArray *array; unsigned i; id qualifiers[[_values count] + 1]; keys = [_values keyEnumerator]; for (i = 0; (key = [keys nextObject]); i++) { id value; value = [_values objectForKey:key]; qualifiers[i] = [[EOKeyValueQualifier alloc] initWithKey:key operatorSelector:EOQualifierOperatorEqual value:value]; qualifiers[i] = [qualifiers[i] autorelease]; } array = [NSArray arrayWithObjects:qualifiers count:i]; return [[[EOOrQualifier alloc] initWithQualifierArray:array] autorelease]; } + (EOQualifier *)qualifierToMatchAllValues:(NSDictionary *)_values { /* AND qualifier */ NSEnumerator *keys; NSString *key; NSArray *array; unsigned i; id qualifiers[[_values count] + 1]; keys = [_values keyEnumerator]; for (i = 0; (key = [keys nextObject]); i++) { id value; value = [_values objectForKey:key]; qualifiers[i] = [[EOKeyValueQualifier alloc] initWithKey:key operatorSelector:EOQualifierOperatorEqual value:value]; qualifiers[i] = [qualifiers[i] autorelease]; } array = [NSArray arrayWithObjects:qualifiers count:i]; return [[[EOAndQualifier alloc] initWithQualifierArray:array] autorelease]; } + (SEL)operatorSelectorForString:(NSString *)_str { SEL s; if ((s = NSMapGet(operatorToSelector, _str))) return s; else return NSSelectorFromString(_str); } + (NSString *)stringForOperatorSelector:(SEL)_sel { NSString *s, *ss; if ((s = NSStringFromSelector(_sel)) == nil) return nil; if ((ss = NSMapGet(selectorToOperator, s))) return ss; return s; } /* bindings */ - (EOQualifier *)qualifierWithBindings:(NSDictionary *)_bindings requiresAllVariables:(BOOL)_reqAll { return self; } - (NSArray *)bindingKeys { return nil; } - (BOOL)requiresAllQualifierBindingVariables { return YES; } /* keys */ - (NSSet *)allQualifierKeys { /* new in WO 4.5 */ id set; set = [NSMutableSet setWithCapacity:64]; [self addQualifierKeysToSet:set]; return [[set copy] autorelease]; } - (void)addQualifierKeysToSet:(NSMutableSet *)_keys { /* new in WO 4.5 */ } /* Comparing */ - (BOOL)isEqual:(id)_obj { if ([_obj isKindOfClass:[self class]]) return [self isEqualToQualifier:(EOQualifier *)_obj]; return NO; } - (BOOL)isEqualToQualifier:(EOQualifier *)_qual { [self doesNotRecognizeSelector:_cmd]; return NO; } /* remapping keys */ - (EOQualifier *)qualifierByApplyingTransformer:(id)_t inContext:(id)_ctx { if ([_t respondsToSelector:@selector(transformQualifier:inContext:)]) return [_t transformQualifier:self inContext:_ctx]; else return [[self retain] autorelease]; } - (EOQualifier *)qualifierByApplyingKeyMap:(NSDictionary *)_key { return [[self copy] autorelease]; } /* GDL2 compatibility */ - (EOQualifier *)qualifierByApplyingBindings:(NSDictionary *)_bindings { return [self qualifierWithBindings:_bindings requiresAllVariables: [self requiresAllQualifierBindingVariables]]; } /* BDControl additions */ - (NSUInteger)count { return [[self subqualifiers] count]; } - (NSArray *)subqualifiers { return nil; } /* debugging */ + (BOOL)isEvaluationDebuggingEnabled { static int evalDebug = -1; if (evalDebug == -1) { evalDebug = [[NSUserDefaults standardUserDefaults] boolForKey:@"EOQualifierDebugEvaluation"] ? 1 : 0; if (evalDebug) NSLog(@"WARNING: qualifier evaluation debugging is enabled !"); } return evalDebug ? YES : NO; } /* QuickEval */ - (BOOL)evaluateWithObject:(id)_object inEvalContext:(id)_ctx { return [(id)self evaluateWithObject:_object]; } /* key/value archiving */ - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { return [super init]; } - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver { } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { /* EOQualifiers are supposed to be immutable */ return [self retain]; } @end /* EOQualifier */ SOPE/sope-core/EOControl/NSArray+EOQualifier.m0000644000000000000000000000271015004363604017721 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "common.h" @implementation NSArray(EOQualifier) - (NSArray *)filteredArrayUsingQualifier:(EOQualifier *)_qualifier { NSAutoreleasePool *pool; NSMutableArray *array = nil; NSArray *result; NSUInteger i, count; pool = [[NSAutoreleasePool alloc] init]; result = nil; count = [self count]; array = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) { id o; o = [self objectAtIndex:i]; if ([(id)_qualifier evaluateWithObject:o]) [array addObject:o]; } result = [array copy]; [pool release]; return [result autorelease]; } @end /* NSArray(EOQualifier) */ SOPE/sope-core/EOControl/libEOControl.def0000644000000000000000000000017415004363604017100 0ustar rootrootEXPORTS EOCompareAscending; EOCompareDescending; EOCompareCaseInsensitiveAscending; EOCompareCaseInsensitiveDescending; SOPE/sope-core/EOControl/EOValidation.m0000644000000000000000000001060315004363604016557 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOClassDescription.h" #include "EOKeyValueCoding.h" #include "EONull.h" #include "common.h" #if !LIB_FOUNDATION_LIBRARY @interface NSException(UsedSetUI) /* does Jaguar allow -setUserInfo: ? */ - (void)setUserInfo:(NSDictionary *)_ui; @end #endif @implementation NSClassDescription(EOValidation) - (NSException *)validateObjectForDelete:(id)_object { return nil; } - (NSException *)validateObjectForSave:(id)_object { return nil; } - (NSException *)validateValue:(id *)_value forKey:(NSString *)_key { return nil; } @end /* NSClassDescription(EOValidation) */ @implementation NSObject(EOValidation) - (NSException *)validateForDelete { return [[self classDescription] validateObjectForDelete:self]; } - (NSException *)validateForInsert { return [self validateForSave]; } - (NSException *)validateForUpdate { return [self validateForSave]; } - (NSException *)validateForSave { NSException *e; NSMutableArray *exceptions; NSArray *properties; unsigned int i, count; id (*validate)(id, SEL, id *, NSString *); id (*objAtIdx)(id, SEL, unsigned int idx); id (*valForKey)(id, SEL, NSString *); exceptions = nil; /* first ask class description to validate object */ if ((e = [[self classDescription] validateObjectForSave:self])) { if (exceptions == nil) exceptions = [NSMutableArray array]; [exceptions addObject:e]; } /* then process all properties */ if ((properties = [self allPropertyKeys]) == nil) properties = [NSArray array]; validate = (void *)[self methodForSelector:@selector(validateValue:forKey:)]; valForKey = (void *)[self methodForSelector:@selector(valueForKey:)]; objAtIdx = (void *)[properties methodForSelector:@selector(objectAtIndex:)]; for (i = 0, count = [properties count]; i < count; i++) { NSString *key; id value, orgValue; key = objAtIdx(properties, @selector(objectAtIndex:), i); orgValue = value = valForKey(self, @selector(valueForKey:), key); if ((e = validate(self, @selector(validateValue:forKey:), &value, key))) { /* validation of property failed */ if (exceptions == nil) exceptions = [NSMutableArray array]; [exceptions addObject:e]; } else if (orgValue != value) { /* the value was changed during validation */ [self takeValue:value forKey:key]; } } if ((count = [exceptions count]) == 0) { return nil; } else if (count == 1) { return [exceptions objectAtIndex:0]; } else { NSException *master; NSMutableDictionary *ui; master = [exceptions objectAtIndex:0]; [exceptions removeObjectAtIndex:0]; ui = [[master userInfo] mutableCopy]; if (ui == nil) ui = [[NSMutableDictionary alloc] init]; [ui setObject:exceptions forKey:@"EOAdditionalExceptions"]; [master setUserInfo:ui]; [ui release]; ui = nil; return master; } } - (NSException *)validateValue:(id *)_value forKey:(NSString *)_key { NSException *e; if ((e = [[self classDescription] validateValue:_value forKey:_key])) return e; /* should invoke key-specific methods, eg -validateBlah: */ { /* construct 'validate'(8) + key + ':'(1) */ unsigned len; char *buf; SEL sel; len = [_key cStringLength]; buf = malloc(len + 14); strcpy(buf, "validate"); [_key getCString:&buf[8]]; strcat(buf, ":"); buf[8] = toupper(buf[8]); sel = sel_registerName(buf); if (sel) { if ([self respondsToSelector:sel]) { if (buf) free(buf); return [self performSelector:sel withObject:*_value]; } } if (buf) free(buf); } return nil; } @end /* NSObject(EOValidation) */ SOPE/sope-core/EOControl/EOControlDecls.h0000644000000000000000000000234215004363604017054 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOControl_EOControlDecls_H__ #define __EOControl_EOControlDecls_H__ #if BUILD_libEOControl_DLL # define EOControl_EXPORT __declspec(dllexport) # define EOControl_DECLARE __declspec(dllexport) #elif libEOControl_ISDLL # define EOControl_EXPORT extern __declspec(dllimport) # define EOControl_DECLARE extern __declspec(dllimport) #else # define EOControl_EXPORT extern # define EOControl_DECLARE #endif #endif /* __EOControl_EOControlDecls_H__ */ SOPE/sope-core/EOControl/NSObject+EOQualifierOps.m0000644000000000000000000001272515004363604020542 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOQualifier.h" #include "EONull.h" #include "common.h" static EONull *null = nil; /* values */ @interface NSObject(CompareIFace) - (NSComparisonResult)compare:(id)_object; @end @implementation NSObject(ImplementedQualifierComparisons) - (BOOL)isEqualTo:(id)_object { return [self isEqual:_object]; } - (BOOL)isNotEqualTo:(id)_object { return ![self isEqualTo:_object]; } - (BOOL)isLessThan:(id)_object { return [self compare:_object] < 0 ? YES : NO; } - (BOOL)isGreaterThan:(id)_object { return [self compare:_object] > 0 ? YES : NO; } - (BOOL)isLessThanOrEqualTo:(id)_object { return [self compare:_object] <= 0 ? YES : NO; } - (BOOL)isGreaterThanOrEqualTo:(id)_object { return [self compare:_object] >= 0 ? YES : NO; } - (BOOL)doesContain:(id)_object { return NO; } - (BOOL)isLike:(NSString *)_object { return NO; } - (BOOL)isCaseInsensitiveLike:(NSString *)_object { return NO; } @end /* NSObject(ImplementedQualifierComparisons) */ @implementation NSArray(ImplementedQualifierComparisons) - (BOOL)doesContain:(id)_object { return [self containsObject:_object]; } @end /* NSArray(ImplementedQualifierComparisons) */ @implementation NSString(ImplementedQualifierComparisons) - (BOOL)isLike:(NSString *)_pattern { NSArray *cs; unsigned count; #if 0 NSString *first, *last; #endif if (null == nil) null = [[EONull null] retain]; if ((id)_pattern == (id)null) return NO; if ([_pattern isEqual:@"*"]) /* all match */ return YES; cs = [_pattern componentsSeparatedByString:@"*"]; count = [cs count]; if (count == 0) return [self isEqual:_pattern]; if (count == 1) return [self isEqual:_pattern]; if (count == 2) { if ([_pattern hasPrefix:@"*"]) return [self hasSuffix:[cs objectAtIndex:1]]; if ([_pattern hasSuffix:@"*"]) return [self hasPrefix:[cs objectAtIndex:0]]; } if (count == 3) { if ([_pattern hasPrefix:@"*"] && [_pattern hasSuffix:@"*"]) return [self rangeOfString:[cs objectAtIndex:1]].length == 0 ? NO : YES; } #if 1 { NSEnumerator *enumerator; int idx; int len; NSString *str; idx = 0; len = [self length]; enumerator = [cs objectEnumerator]; while ((str = [enumerator nextObject]) && idx < len) { NSRange r; if ([str length] == 0) continue; r = NSMakeRange(idx, ([self length] - idx)); r = [self rangeOfString:str options:0 range:r]; if (r.length == 0) return NO; idx += r.length; } return [enumerator nextObject] ? NO : YES; } #else first = [cs objectAtIndex:0]; last = [cs lastObject]; if (![self hasPrefix:first]) return NO; if (![self hasSuffix:last]) return NO; /* to be completed (match interior stuff, match '?') */ return YES; #endif return NO; } - (BOOL)isCaseInsensitiveLike:(NSString *)_pattern { return [[self lowercaseString] isLike:[_pattern lowercaseString]]; } @end /* NSString(ImplementedQualifierComparisons) */ @implementation NSNumber(ImplementedQualifierComparisons) - (BOOL)isEqualTo:(id)_object { if (_object == nil) return NO; if (_object == self) return YES; return [self isEqual:_object]; } - (BOOL)isNotEqualTo:(id)_object { if (_object == nil) return YES; return ![self isEqualTo:_object]; } - (BOOL)isLessThan:(id)_object { if (_object == nil) return YES; if (_object == self) return NO; return [self compare:_object] < 0 ? YES : NO; } - (BOOL)isGreaterThan:(id)_object { if (_object == nil) return NO; if (_object == self) return NO; return [self compare:_object] > 0 ? YES : NO; } - (BOOL)isLessThanOrEqualTo:(id)_object { if (_object == nil) return YES; if (_object == self) return YES; return [self compare:_object] <= 0 ? YES : NO; } - (BOOL)isGreaterThanOrEqualTo:(id)_object { if (_object == nil) return NO; if (_object == self) return YES; return [self compare:_object] >= 0 ? YES : NO; } @end /* NSNumber(ImplementedQualifierComparisons) */ @implementation NSDate(ImplementedQualifierComparisons) #define CHECK_NULL(__VAL__, __RES__) \ {if (null == nil) null = [[EONull null] retain];} \ if (__VAL__ == nil || __VAL__ == null) return __RES__ - (BOOL)isLessThan:(id)_object { CHECK_NULL(_object, NO); return [self compare:_object] < 0 ? YES : NO; } - (BOOL)isGreaterThan:(id)_object { CHECK_NULL(_object, YES); return [self compare:_object] > 0 ? YES : NO; } - (BOOL)isLessThanOrEqualTo:(id)_object { CHECK_NULL(_object, NO); return [self compare:_object] <= 0 ? YES : NO; } - (BOOL)isGreaterThanOrEqualTo:(id)_object { CHECK_NULL(_object, YES); return [self compare:_object] >= 0 ? YES : NO; } @end /* NSDate(ImplementedQualifierComparisons) */ SOPE/sope-core/EOControl/EODetailDataSource.m0000644000000000000000000001164015004363604017644 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "common.h" @implementation EODetailDataSource - (id)initWithMasterClassDescription:(EOClassDescription *)_cd detailKey:(NSString *)_relKey { if ((self = [super init])) { self->masterClassDescription = [_cd retain]; [self qualifyWithRelationshipKey:_relKey ofObject:nil]; } return self; } - (id)initWithMasterDataSource:(EODataSource *)_ds detailKey:(NSString *)_relKey { if ((self = [self initWithMasterClassDescription:nil detailKey:_relKey])) { self->masterDataSource = [_ds retain]; } return self; } - (id)init { return [self initWithMasterClassDescription:nil detailKey:nil]; } - (void)dealloc { [self->detailKey release]; [self->masterObject release]; [self->masterClassDescription release]; [self->masterDataSource release]; [super dealloc]; } /* reflection */ - (void)setMasterClassDescription:(EOClassDescription *)_cd { ASSIGN(self->masterClassDescription, _cd); } - (EOClassDescription *)masterClassDescription { return self->masterClassDescription; } - (EODataSource *)masterDataSource { return self->masterDataSource; } /* editing context */ - (id)editingContext { return [[self masterObject] editingContext]; } /* master-detail */ - (id)masterObject { return self->masterObject; } - (NSString *)detailKey { return self->detailKey; } - (void)qualifyWithRelationshipKey:(NSString *)_relKey ofObject:(id)_object { id tmp; tmp = self->detailKey; self->detailKey = [_relKey copy]; [tmp release]; ASSIGN(self->masterObject, _object); } /* operations */ - (NSArray *)fetchObjects { id eo; NSString *dk; if ((eo = [self masterObject]) == nil) return [NSArray array]; if ((dk = [self detailKey]) == nil) return [NSArray arrayWithObject:eo]; return [eo valueForKey:dk]; } - (void)insertObject:(id)_object { id eo; NSString *dk; if ((eo = [self masterObject]) == nil) { [NSException raise:@"NSInternalInconsistencyException" format: @"detail datasource %@ has no master object set " @"for insertion of object %@", self, _object]; } if ((dk = [self detailKey]) == nil) { [NSException raise:@"NSInternalInconsistencyException" format: @"detail datasource %@ has no detail key set " @"for insertion of object %@ into master %@", self, _object, eo]; } [eo addObject:_object toBothSidesOfRelationshipWithKey:dk]; } - (void)deleteObject:(id)_object { id eo; NSString *dk; if ((eo = [self masterObject]) == nil) { [NSException raise:@"NSInternalInconsistencyException" format: @"detail datasource %@ has no master object set " @"for deletion of object %@", self, _object]; } if ((dk = [self detailKey]) == nil) { [NSException raise:@"NSInternalInconsistencyException" format: @"detail datasource %@ has no detail key set " @"for deletion of object %@ from master %@", self, _object, eo]; } [eo removeObject:_object fromPropertyWithKey:dk]; } /* key/value archiving */ - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { /* dataSource = { class = EODetailDataSource; detailKey = roles; masterClassDescription = Movie; }; */ if ((self = [super init])) { NSString *ename; self->detailKey = [[_unarchiver decodeObjectForKey:@"detailKey"] copy]; ename = [_unarchiver decodeObjectForKey:@"masterClassDescription"]; NSLog(@"TODO(%s): set class description: %@", __PRETTY_FUNCTION__, ename); } return self; } - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver { [_archiver encodeObject:[self detailKey] forKey:@"detailKey"]; [_archiver encodeObject:[[self masterClassDescription] entityName] forKey:@"masterClassDescription"]; } @end /* EODetailDataSource */ SOPE/sope-core/EOControl/Version0000644000000000000000000000004515004363604015432 0ustar rootroot# version file SUBMINOR_VERSION:=74 SOPE/sope-core/EOControl/EOQualifierParser.m0000644000000000000000000010452715004363604017574 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "EOQualifier.h" #include "EONull.h" #include "common.h" //#define USE_DESCRIPTION_FOR_AT 1 static int qDebug = 0; static NSMutableDictionary *EOQualifierParserTypeMappings = nil; /* The literals understood by the value parser. NOTE: Any literal used here can never be used as a key ! So add as little as possible. */ typedef struct { const unsigned char *token; id value; int scase; } EOQPTokEntry; static EOQPTokEntry toks[] = { { (const unsigned char *)"NULL", nil, 0 }, { (const unsigned char *)"nil", nil, 1 }, { (const unsigned char *)"YES", nil, 0 }, { (const unsigned char *)"NO", nil, 0 }, { (const unsigned char *)"TRUE", nil, 0 }, { (const unsigned char *)"FALSE", nil, 0 }, { (const unsigned char *)NULL, nil, 0 } }; static inline void _setupLiterals(void) { static BOOL didSetup = NO; if (didSetup) return; didSetup = YES; toks[0].value = [[NSNull null] retain]; toks[1].value = toks[0].value; toks[2].value = [[NSNumber numberWithBool:YES] retain]; toks[3].value = [[NSNumber numberWithBool:NO] retain]; toks[4].value = toks[2].value; toks[5].value = toks[3].value; } /* cache */ static Class StringClass = Nil; static Class NumberClass = Nil; static EONull *null = nil; /* parsing functions */ static EOQualifier *_parseCompoundQualifier(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_qualLen); static EOQualifier *_testOperator(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_opLen, BOOL *_testAnd); static EOQualifier *_parseQualifiers(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_qualLen); static EOQualifier *_parseParenthesisQualifier(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_qualLen); static EOQualifier *_parseNotQualifier(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_qualLen); static EOQualifier *_parseKeyCompQualifier(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_qualLen); static NSString *_parseKey(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_keyLen); static id _parseValue(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_keyLen); static inline unsigned _countWhiteSpaces(const char *_buf, unsigned _bufLen); static NSString *_parseOp(const char *_buf, unsigned _bufLen, unsigned *_opLen); @interface EOQualifierParserContext : NSObject { NSMapTable *qualifierCache; } - (NSDictionary *)resultForFunction:(NSString *)_fct atPos:(unsigned)_pos; - (void)setResult:(NSDictionary *)_dict forFunction:(NSString *)_fct atPos:(unsigned)_pos; - (id)getObjectFromStackFor:(char)_c; /* factory */ - (EOQualifier *)keyComparisonQualifierWithLeftKey:(NSString *)_leftKey operatorSelector:(SEL)_sel rightKey:(NSString *)_rightKey; - (EOQualifier *)keyValueQualifierWithKey:(NSString *)_key operatorSelector:(SEL)_sel value:(id)_value; - (EOQualifier *)andQualifierWithArray:(NSArray *)_qualifiers; - (EOQualifier *)orQualifierWithArray:(NSArray *)_qualifiers; - (EOQualifier *)notQualifierWithQualifier:(EOQualifier *)_qualifier; @end @interface EOQualifierVAParserContext : EOQualifierParserContext { va_list *va; } + (id)contextWithVaList:(va_list *)_va; - (id)initWithVaList:(va_list *)_va; @end @interface EOQualifierEnumeratorParserContext : EOQualifierParserContext { NSEnumerator *enumerator; } + (id)contextWithEnumerator:(NSEnumerator *)_enumerator; - (id)initWithEnumerator:(NSEnumerator *)_enumerator; @end @implementation EOQualifierVAParserContext + (id)contextWithVaList:(va_list *)_va { return [[[EOQualifierVAParserContext alloc] initWithVaList:_va] autorelease]; } - (id)initWithVaList:(va_list *)_va { if ((self = [super init])) { self->va = _va; } return self; } - (id)getObjectFromStackFor:(char)_c { id obj = nil; if (StringClass == Nil) StringClass = [NSString class]; if (NumberClass == Nil) NumberClass = [NSNumber class]; if (null == nil) null = [EONull null]; if (_c == 's') { char *str = va_arg(*self->va, char*); obj = [StringClass stringWithCString:str]; } else if (_c == 'd') { int i= va_arg(*self->va, int); obj = [NumberClass numberWithInt:i]; } else if (_c == 'f') { double d = va_arg(*self->va, double); obj = [NumberClass numberWithDouble:d]; } else if (_c == '@') { id o = va_arg(*self->va, id); #if USE_DESCRIPTION_FOR_AT obj = (o == nil) ? (id)null : (id)[o description]; #else obj = (o == nil) ? (id)null : (id)o; #endif } else { [NSException raise:@"NSInvalidArgumentException" format:@"unknown conversation char %c", _c]; } return obj; } @end /* EOQualifierVAParserContext */ @implementation EOQualifierEnumeratorParserContext + (id)contextWithEnumerator:(NSEnumerator *)_enumerator { return [[[EOQualifierEnumeratorParserContext alloc] initWithEnumerator:_enumerator] autorelease]; } - (id)initWithEnumerator:(NSEnumerator *)_enumerator { if ((self = [super init])) { ASSIGN(self->enumerator, _enumerator); } return self; } - (void)dealloc { [self->enumerator release]; [super dealloc];; } - (id)getObjectFromStackFor:(char)_c { static Class NumberClass = Nil; id o; if (NumberClass == Nil) NumberClass = [NSNumber class]; o = [self->enumerator nextObject]; switch (_c) { case '@': #if USE_DESCRIPTION_FOR_AT return [o description]; #else return o; #endif case 'f': return [NumberClass numberWithDouble:[o doubleValue]]; case 'd': return [NumberClass numberWithInt:[o intValue]]; case 's': // return [NSString stringWithCString:[o cString]]; return [[o copy] autorelease]; default: [NSException raise:@"NSInvalidArgumentException" format:@"unknown or not allowed conversation char %c", _c]; } return nil; } @end /* EOQualifierEnumeratorParserContext */ @implementation EOQualifierParserContext - (id)init { if (StringClass == Nil) StringClass = [NSString class]; if ((self = [super init])) { self->qualifierCache = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 200); } return self; } - (void)dealloc { if (self->qualifierCache) NSFreeMapTable(self->qualifierCache); [super dealloc]; } - (NSDictionary *)resultForFunction:(NSString *)_fct atPos:(unsigned)_pos { return NSMapGet(self->qualifierCache, [StringClass stringWithFormat:@"%@_%d", _fct, _pos]); } - (void)setResult:(NSDictionary *)_dict forFunction:(NSString *)_fct atPos:(unsigned)_pos { NSMapInsert(self->qualifierCache, [StringClass stringWithFormat:@"%@_%d", _fct, _pos], _dict); } - (id)getObjectFromStackFor:(char)_c { [self doesNotRecognizeSelector:_cmd]; return nil; } /* factory */ - (EOQualifier *)keyComparisonQualifierWithLeftKey:(NSString *)_leftKey operatorSelector:(SEL)_sel rightKey:(NSString *)_rightKey { static Class clazz = Nil; if (clazz == Nil) clazz = [EOKeyComparisonQualifier class]; return [[[clazz alloc] initWithLeftKey:_leftKey operatorSelector:_sel rightKey:_rightKey] autorelease]; } - (EOQualifier *)keyValueQualifierWithKey:(NSString *)_key operatorSelector:(SEL)_sel value:(id)_value { static Class clazz = Nil; if (clazz == Nil) clazz = [EOKeyValueQualifier class]; return [[[clazz alloc] initWithKey:_key operatorSelector:_sel value:_value] autorelease]; } - (EOQualifier *)andQualifierWithArray:(NSArray *)_qualifiers { static Class clazz = Nil; if (clazz == Nil) clazz = [EOAndQualifier class]; return [[[clazz alloc] initWithQualifierArray:_qualifiers] autorelease]; } - (EOQualifier *)orQualifierWithArray:(NSArray *)_qualifiers { static Class clazz = Nil; if (clazz == Nil) clazz = [EOOrQualifier class]; return [[[clazz alloc] initWithQualifierArray:_qualifiers] autorelease]; } - (EOQualifier *)notQualifierWithQualifier:(EOQualifier *)_qualifier { static Class clazz = Nil; if (clazz == Nil) clazz = [EONotQualifier class]; return [[[clazz alloc] initWithQualifier:_qualifier] autorelease]; } - (EOQualifierVariable *)variableWithKey:(NSString *)_key { static Class clazz = Nil; if (clazz == Nil) clazz = [EOQualifierVariable class]; return [clazz variableWithKey:_key]; } @end /* EOQualifierParserContext */ @implementation EOQualifier(Parsing) + (void)registerValueClass:(Class)_valueClass forTypeName:(NSString *)_type { if (EOQualifierParserTypeMappings == nil) EOQualifierParserTypeMappings = [[NSMutableDictionary alloc] init]; if (_type == nil) { NSLog(@"ERROR(%s): got passed no type name!", __PRETTY_FUNCTION__); return; } if (_valueClass == nil) { NSLog(@"ERROR(%s): got passed no value-class for type '%@'!", __PRETTY_FUNCTION__, _type); return; } [EOQualifierParserTypeMappings setObject:_valueClass forKey:_type]; } + (EOQualifier *)qualifierWithQualifierFormat:(NSString *)_qualifierFormat,... { va_list va; EOQualifier *qualifier; unsigned length = 0; const char *buf; unsigned bufLen; _setupLiterals(); if (StringClass == Nil) StringClass = [NSString class]; buf = [_qualifierFormat cStringUsingEncoding: NSUTF8StringEncoding]; bufLen = strlen(buf); va_start(va, _qualifierFormat); qualifier = _parseQualifiers([EOQualifierVAParserContext contextWithVaList:&va], buf, bufLen, &length); va_end(va); if (qualifier != nil) { /* check whether the rest of the string is OK */ if (length < bufLen) length += _countWhiteSpaces(buf + length, bufLen - length); if (length < bufLen) { NSLog(@"WARNING(%s): unexpected chars at the end of the " @"string(class=%@,len=%"PRIuPTR") '%@'", __PRETTY_FUNCTION__, [_qualifierFormat class], [_qualifierFormat length], _qualifierFormat); NSLog(@" buf-length: %i", bufLen); NSLog(@" length: %i", length); NSLog(@" char[length]: '%c' (%i) '%s'", buf[length], buf[length], (buf+length)); qualifier = nil; } else if (length > bufLen) { NSLog(@"WARNING(%s): length should never be longer than bufLen ?, " @"internal parsing error !", __PRETTY_FUNCTION__); } } return qualifier; } + (EOQualifier *)qualifierWithQualifierFormat:(NSString *)_qualifierFormat arguments:(NSArray *)_arguments { EOQualifier *qual = nil; unsigned length = 0; const char *buf = NULL; unsigned bufLen = 0; EOQualifierEnumeratorParserContext *ctx; _setupLiterals(); if (StringClass == Nil) StringClass = [NSString class]; ctx = [EOQualifierEnumeratorParserContext contextWithEnumerator: [_arguments objectEnumerator]]; //NSLog(@"qclass: %@", [_qualifierFormat class]); buf = [_qualifierFormat cString]; bufLen = [_qualifierFormat cStringLength]; qual = _parseQualifiers(ctx, buf, bufLen, &length); if (qual != nil) { /* check whether the rest of the string is OK */ if (length < bufLen) { length += _countWhiteSpaces(buf + length, bufLen - length); } if (length != bufLen) { NSLog(@"WARNING(%s): unexpected chars at the end of the string '%@'", __PRETTY_FUNCTION__, _qualifierFormat); qual = nil; } } return qual; } @end /* EOQualifier(Parsing) */ static EOQualifier *_parseSingleQualifier(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_qualLen) { EOQualifier *res = nil; if ((res = _parseParenthesisQualifier(_ctx, _buf, _bufLen, _qualLen)) != nil) { if (qDebug) NSLog(@"_parseSingleQualifier return <%@> for <%s> ", res, _buf); return res; } if ((res = _parseNotQualifier(_ctx, _buf, _bufLen, _qualLen)) != nil) { if (qDebug) NSLog(@"_parseSingleQualifier return <%@> for <%s> ", res, _buf); return res; } if ((res = _parseKeyCompQualifier(_ctx, _buf, _bufLen, _qualLen)) != nil) { if (qDebug) { NSLog(@"_parseSingleQualifier return <%@> for <%s> length %d", res, _buf, *_qualLen); } return res; } return nil; } static EOQualifier *_parseQualifiers(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_qualLen) { EOQualifier *res = nil; if ((res = _parseCompoundQualifier(_ctx, _buf, _bufLen, _qualLen))) { if (qDebug) NSLog(@"_parseQualifiers return <%@> for <%s> ", res, _buf); return res; } if ((res = _parseSingleQualifier(_ctx, _buf, _bufLen, _qualLen))) { if (qDebug) NSLog(@"_parseQualifiers return <%@> for <%s> ", res, _buf); return res; } if (qDebug) NSLog(@"_parseQualifiers return nil for <%s> ", _buf); return nil; } static EOQualifier *_parseParenthesisQualifier(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_qualLen) { unsigned pos = 0; unsigned qualLen = 0; EOQualifier *qual = nil; pos = _countWhiteSpaces(_buf, _bufLen); if (_bufLen <= pos + 2) /* at least open and close parenthesis */ { if (qDebug) NSLog(@"1_parseParenthesisQualifier return nil for <%s> ", _buf); return nil; } if (_buf[pos] != '(') { if (qDebug) NSLog(@"2_parseParenthesisQualifier return nil for <%s> ", _buf); return nil; } pos++; if (!(qual = _parseQualifiers(_ctx, _buf + pos, _bufLen - pos, &qualLen))) { if (qDebug) NSLog(@"3_parseParenthesisQualifier return nil for <%s> ", _buf); return nil; } pos += qualLen; if (_bufLen <= pos) { if (qDebug) NSLog(@"4_parseParenthesisQualifier return nil for <%s> qual[%@] %@ bufLen %d " @"pos %d", _buf, [qual class], qual, _bufLen, pos); return nil; } pos += _countWhiteSpaces(_buf + pos, _bufLen - pos); if (_buf[pos] != ')') { if (qDebug) NSLog(@"5_parseParenthesisQualifier return nil for <%s> [%s] ", _buf, _buf+pos); return nil; } if (qDebug) NSLog(@"6_parseParenthesisQualifier return <%@> for <%s> ", qual, _buf); *_qualLen = pos + 1; /* one step after the parenthesis */ return qual; } static EOQualifier *_parseNotQualifier(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_qualLen) { unsigned pos, len = 0; char c0, c1, c2 = 0; EOQualifier *qual = nil; pos = _countWhiteSpaces(_buf, _bufLen); if (_bufLen - pos < 4) { /* at least 3 chars for 'NOT' */ if (qDebug) NSLog(@"_parseNotQualifier return nil for <%s> ", _buf); return nil; } c0 = _buf[pos]; c1 = _buf[pos + 1]; c2 = _buf[pos + 2]; if (!(((c0 == 'n') || (c0 == 'N')) && ((c1 == 'o') || (c1 == 'O')) && ((c2 == 't') || (c2 == 'T')))) { if (qDebug) NSLog(@"_parseNotQualifier return nil for <%s> ", _buf); return nil; } pos += 3; qual = _parseSingleQualifier(_ctx, _buf + pos, _bufLen - pos, &len); if (qual == nil) { if (qDebug) NSLog(@"_parseNotQualifier return nil for <%s> ", _buf); return nil; } *_qualLen = pos +len; if (qDebug) NSLog(@"_parseNotQualifier return %@ for <%s> ", qual, _buf); return [_ctx notQualifierWithQualifier:qual]; } static EOQualifier *_parseKeyCompQualifier(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_qualLen) { NSString *key = nil; NSString *op = nil; id value = nil; EOQualifier *qual = nil; NSDictionary *dict = nil; SEL sel = NULL; unsigned length = 0; unsigned pos = 0; BOOL valueIsKey = NO; dict = [_ctx resultForFunction:@"parseKeyCompQualifier" atPos:(unsigned long)_buf]; if (dict != nil) { if (qDebug) NSLog(@"_parseKeyCompQual return <%@> [cached] for <%s> ", dict, _buf); *_qualLen = [[dict objectForKey:@"length"] unsignedIntValue]; return [dict objectForKey:@"object"]; } pos = _countWhiteSpaces(_buf, _bufLen); if ((key = _parseKey(_ctx , _buf + pos, _bufLen - pos, &length)) == nil) { if (qDebug) NSLog(@"_parseKeyCompQualifier return nil for <%s> ", _buf); return nil; } pos += length; pos += _countWhiteSpaces(_buf + pos, _bufLen - pos); if (!(op = _parseOp(_buf + pos, _bufLen - pos, &length))) { if (qDebug) NSLog(@"_parseKeyCompQualifier return nil for <%s> ", _buf); return nil; } sel = [EOQualifier operatorSelectorForString:op]; if (sel == NULL) { NSLog(@"WARNING(%s): possible unknown operator <%@>", __PRETTY_FUNCTION__, op); if (qDebug) NSLog(@"_parseKeyCompQualifier return nil for <%s> ", _buf); return nil; } pos +=length; pos += _countWhiteSpaces(_buf + pos, _bufLen - pos); valueIsKey = NO; value = _parseValue(_ctx, _buf + pos, _bufLen - pos, &length); if (value == nil) { value = _parseKey(_ctx, _buf + pos, _bufLen - pos, &length); if (value == nil) { if (qDebug) NSLog(@"_parseKeyCompQualifier return nil for <%s> ", _buf); return nil; } else valueIsKey = YES; } pos +=length; *_qualLen = pos; qual = (valueIsKey) ? [_ctx keyComparisonQualifierWithLeftKey:key operatorSelector:sel rightKey:value] : [_ctx keyValueQualifierWithKey:key operatorSelector:sel value:value]; if (qDebug) NSLog(@"_parseKeyCompQualifier return <%@> for <%s> ", qual, _buf); if (qual != nil) { id keys[2], values[2]; keys[0] = @"length"; values[0] = [NSNumber numberWithUnsignedInt:pos]; keys[1] = @"object"; values[1] = qual; [_ctx setResult: [NSDictionary dictionaryWithObjects:values forKeys:keys count:2] forFunction:@"parseKeyCompQualifier" atPos:(unsigned long)_buf]; *_qualLen = pos; } return qual; } static NSString *_parseOp(const char *_buf, unsigned _bufLen, unsigned *_opLen) { unsigned pos = 0; char c0 = 0; char c1 = 0; if (_bufLen == 0) { if (qDebug) NSLog(@"_parseOp _bufLen == 0 --> return nil"); return nil; } pos = _countWhiteSpaces(_buf, _bufLen); if (_bufLen - pos > 1) {/* at least an operation and a value */ c0 = _buf[pos]; c1 = _buf[pos+1]; if (((c0 >= '<') && (c0 <= '>')) || (c0 == '!')) { NSString *result; if ((c1 >= '<') && (c1 <= '>')) { *_opLen = 2; result = [StringClass stringWithCString:_buf + pos length:2]; if (qDebug) NSLog(@"_parseOp return <%@> for <%s> ", result, _buf); } else { *_opLen = 1; result = [StringClass stringWithCString:&c0 length:1]; if (qDebug) NSLog(@"_parseOp return <%@> for <%s> ", result, _buf); } return result; } else { /* string designator operator */ unsigned opStart = pos; while (pos < _bufLen) { if (_buf[pos] == ' ') break; pos++; } if (pos >= _bufLen) { NSLog(@"WARNING(%s): found end of string during operator parsing", __PRETTY_FUNCTION__); } if (qDebug) { NSLog(@"%s: _parseOp return <%@> for <%s> ", __PRETTY_FUNCTION__, [StringClass stringWithCString:_buf + opStart length:pos - opStart], _buf); } *_opLen = pos; return [StringClass stringWithCString:_buf + opStart length:pos - opStart]; } } if (qDebug) NSLog(@"_parseOp return nil for <%s> ", _buf); return nil; } static NSString *_parseKey(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_keyLen) { id result = nil; NSDictionary *dict = nil; unsigned pos = 0; unsigned startKey = 0; char c = 0; if (_bufLen == 0) { if (qDebug) NSLog(@"%s: _bufLen == 0 --> return nil", __PRETTY_FUNCTION__); return nil; } dict = [_ctx resultForFunction:@"parseKey" atPos:(unsigned long)_buf]; if (dict != nil) { if (qDebug) { NSLog(@"%s: return <%@> [cached] for <%s> ", __PRETTY_FUNCTION__, dict, _buf); } *_keyLen = [[dict objectForKey:@"length"] unsignedIntValue]; return [dict objectForKey:@"object"]; } pos = _countWhiteSpaces(_buf, _bufLen); startKey = pos; c = _buf[pos]; if (c == '%') { if (_bufLen - pos < 2) { if (qDebug) { NSLog(@"%s: [c==%%,bufLen-pos<2]: _parseValue return nil for <%s> ", __PRETTY_FUNCTION__, _buf); } return nil; } pos++; result = [_ctx getObjectFromStackFor:_buf[pos]]; pos++; } else { /* '{' for namspaces */ register BOOL isQuotedKey = NO; if (c == '"') isQuotedKey = YES; else if (!(((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || c == '{')) { if (qDebug) { NSLog(@"%s: [c!=AZaz{]: _parseKey return nil for <%s> ", __PRETTY_FUNCTION__, _buf); } return nil; } pos++; while (pos < _bufLen) { c = _buf[pos]; if (isQuotedKey && c == '"') break; else if ((c == ' ') || (c == '<') || (c == '>') || (c == '=') || (c == '!') || c == ')' || c == '(') break; pos++; } if (isQuotedKey) { pos++; // skip quote result = [StringClass stringWithCString:(_buf + startKey + 1) length:(pos - startKey - 2)]; } else { result = [StringClass stringWithCString:(_buf + startKey) length:(pos - startKey)]; } } *_keyLen = pos; if (qDebug) NSLog(@"%s: return <%@> for <%s> ", __PRETTY_FUNCTION__, result, _buf); if (result != nil) { id keys[2], values[2]; keys[0] = @"length"; values[0] = [NSNumber numberWithUnsignedInt:pos]; keys[1] = @"object"; values[1] = result; [_ctx setResult: [NSDictionary dictionaryWithObjects:values forKeys:keys count:2] forFunction:@"parseKey" atPos:(unsigned long)_buf]; *_keyLen = pos; } return result; } static id _parseValue(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_keyLen) { NSString *cast = nil; NSDictionary *dict = nil; id obj = nil; unsigned pos = 0; char c = 0; if (NumberClass == Nil) NumberClass = [NSNumber class]; if (null == nil) null = [[NSNull null] retain]; if (_bufLen == 0) { if (qDebug) NSLog(@"_parseValue _bufLen == 0 --> return nil"); return nil; } dict = [_ctx resultForFunction:@"parseValue" atPos:(unsigned long)_buf]; if (dict != nil) { if (qDebug) { NSLog(@"_parseKeyCompQualifier return <%@> [cached] for <%s> ", dict, _buf); } *_keyLen = [[dict objectForKey:@"length"] unsignedIntValue]; return [dict objectForKey:@"object"]; } pos = _countWhiteSpaces(_buf, _bufLen); c = _buf[pos]; if (c == '$') { /* found EOQualifierVariable */ unsigned startVar = 0; NSString *varKey; pos++; startVar = pos; while (pos < _bufLen) { if ((_buf[pos] == ' ') || (_buf[pos] == ')')) break; pos++; } varKey = [StringClass stringWithCString:(_buf + startVar) length:pos - startVar]; obj = [_ctx variableWithKey:varKey]; } else { /* first, check for CAST */ BOOL parseComplexCast = NO; if (c == 'c' && _bufLen > 14) { if (strstr(_buf, "cast") == _buf && (isspace(_buf[4]) || _buf[4]=='(')) { /* for example: cast("1970-01-01T00:00:00Z" as 'dateTime') [min 15 #]*/ pos += 4; /* skip 'cast' */ while (isspace(_buf[pos])) /* skip spaces */ pos++; if (_buf[pos] != '(') { NSLog(@"WARNING(%s): got unexpected cast string: '%s'", __PRETTY_FUNCTION__, _buf); } else pos++; /* skip opening bracket '(' */ parseComplexCast = YES; c = _buf[pos]; } } else if (c == '(') { /* starting with a cast */ /* for example: (NSCalendarDate)"1999-12-12" [min 5 chars] */ unsigned startCast = 0; pos++; startCast = pos; while (pos < _bufLen) { if (_buf[pos] == ')') break; pos++; } pos++; if (pos >= _bufLen) { NSLog(@"WARNING(%s): found end of string while reading a cast", __PRETTY_FUNCTION__); return nil; } c = _buf[pos]; cast = [StringClass stringWithCString:(_buf + startCast) length:(pos - 1 - startCast)]; if (qDebug) NSLog(@"%s: got cast %@", __PRETTY_FUNCTION__, cast); } /* next, check for FORMAT SPECIFIER */ if (c == '%') { if (_bufLen - pos < 2) { if (qDebug) NSLog(@"_parseValue return nil for <%s> ", _buf); return nil; } pos++; obj = [_ctx getObjectFromStackFor:_buf[pos]]; pos++; } /* next, check for A NUMBER */ else if (((c >= '0') && (c <= '9')) || (c == '-')) { /* got a number */ unsigned startNumber; startNumber = pos; pos++; while (pos < _bufLen) { c = _buf[pos]; if (!((c >= '0') && (c <= '9'))) break; pos++; } obj = [NumberClass numberWithInt:atoi(_buf + startNumber)]; } /* check for some text literals */ if ((obj == nil) && ((_bufLen - pos) > 1)) { unsigned char i; for (i = 0; i < 20 && (toks[i].token != NULL) && (obj == nil); i++) { const unsigned char *tok; unsigned char toklen; int rc; tok = toks[i].token; toklen = strlen((const char *)tok); if ((_bufLen - pos) < toklen) /* remaining string not long enough */ continue; rc = toks[i].scase ? strncmp(&(_buf[pos]), (const char *)tok, toklen) : strncasecmp(&(_buf[pos]), (const char *)tok, toklen); if (rc != 0) /* does not match */ continue; if (!(_buf[pos + toklen] == '\0' || isspace(_buf[pos + toklen]) || _buf[pos + toklen] == ')')) { /* Not at the string end or followed by a space or a right parenthesis. The latter is required to correctly parse this: (not (attribute = nil) and attribute.className = 'com.webobjects.foundation.NSTimestamp') */ continue; } /* wow, found the token */ pos += toklen; /* skip it */ obj = toks[i].value; } } /* next, check for STRING */ if (obj == nil) { if ((c == '\'') || (c == '"')) { NSString *res = nil; char string[_bufLen - pos]; unsigned cnt = 0; pos++; while (pos < _bufLen) { char ch = _buf[pos]; if (ch == c) break; if ((ch == '\\') && (_bufLen > (pos + 1))) { if (_buf[pos + 1] == c) { pos += 1; ch = c; } } string[cnt++] = ch; pos++; } if (pos >= _bufLen) { NSLog(@"WARNING(%s): found end of string before end of quoted text", __PRETTY_FUNCTION__); return nil; } res = [StringClass stringWithCString:string length:cnt]; pos++; /* don`t forget quotations */ if (qDebug) NSLog(@"_parseValue return <%@> for <%s> ", res, _buf); obj = res; } } /* complete parsing of cast */ if (parseComplexCast && (pos + 6) < _bufLen) { /* now we need " as 'dateTime'" [min 7 #] */ /* skip spaces */ while (isspace(_buf[pos]) && pos < _bufLen) pos++; //printf("POS: '%s'\n", &(_buf[pos])); /* parse 'as' */ if (_buf[pos] != 'a' && _buf[pos] != 'A') NSLog(@"%s: expecting 'AS' of complex cast ...", __PRETTY_FUNCTION__); else if (_buf[pos + 1] != 's' && _buf[pos + 1] != 'S') NSLog(@"%s: expecting 'AS' of complex cast ...", __PRETTY_FUNCTION__); else { /* skip AS */ pos += 2; /* skip spaces */ while (isspace(_buf[pos]) && pos < _bufLen) pos++; /* read cast type */ if (_buf[pos] != '\'') { NSLog(@"%s: expected type of complex cast ...", __PRETTY_FUNCTION__); } else { const unsigned char *cs, *ce; //printf("POS: '%s'\n", &(_buf[pos])); pos++; cs = (const unsigned char *)&(_buf[pos]); ce = (const unsigned char *)index((const char *)cs, '\''); cast = [NSString stringWithCString:(const char*)cs length:(ce - cs)]; if (qDebug) { NSLog(@"%s: parsed complex cast: '%@' to '%@'", __PRETTY_FUNCTION__, obj, cast); } pos += (ce - cs); pos++; // skip ' pos++; // skip ) //printf("POS: '%s'\n", &(_buf[pos])); } } } } if (cast != nil && obj != nil) { Class class = Nil; id orig = obj; if ((class = [EOQualifierParserTypeMappings objectForKey:cast]) == nil) { /* no value explicitly mapped to class, try to construct class name... */ NSString *className; className = cast; if ((class = NSClassFromString(className)) == Nil) { /* check some default cast types ... */ className = [cast lowercaseString]; if ([className isEqualToString:@"datetime"]) class = [NSCalendarDate class]; else if ([className isEqualToString:@"datetime.tz"]) class = [NSCalendarDate class]; } } if (class) { obj = [[[class alloc] initWithString:[orig description]] autorelease]; if (obj == nil && [NSCalendarDate class] == class && 10 == [[orig description] length]) { NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"yyyy-MM-dd"]; NSDate *date = [dateFormatter dateFromString: [orig description]]; obj = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:[date timeIntervalSinceReferenceDate]]; } if (obj == nil) { NSLog(@"%s: could not init object '%@' of cast class %@(%@) !", __PRETTY_FUNCTION__, orig, class, cast); obj = null; } } else { NSLog(@"WARNING(%s): could not map cast '%@' to a class " @"(returning null) !", __PRETTY_FUNCTION__, cast); obj = null; } } if (qDebug) { NSLog(@"%s: return <%@> for <%s> ", __PRETTY_FUNCTION__, obj != nil ? obj : (id)@"", _buf); } if (obj != nil) { NSDictionary *d; id keys[2], values[2]; keys[0] = @"length"; values[0] = [NSNumber numberWithUnsignedInt:pos]; keys[1] = @"object"; values[1] = obj; d = [[NSDictionary alloc] initWithObjects:values forKeys:keys count:2]; [_ctx setResult:d forFunction:@"parseValue" atPos:(unsigned long)_buf]; [d release]; *_keyLen = pos; } return obj; } static EOQualifier *_testOperator(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_opLen, BOOL *isAnd) { EOQualifier *qual = nil; char c0, c1, c2 = 0; unsigned pos, len = 0; pos = _countWhiteSpaces(_buf, _bufLen); if (_bufLen < 4) {/* at least OR or AND and somethink more */ if (qDebug) NSLog(@"_testOperator return nil for <%s> ", _buf); return nil; } c0 = _buf[pos + 0]; c1 = _buf[pos + 1]; c2 = _buf[pos + 2]; if (((c0 == 'a') || (c0 == 'A')) && ((c1 == 'n') || (c1 == 'N')) && ((c2 == 'd') || (c2 == 'D'))) { pos += 3; *isAnd = YES; } else if (((c0 == 'o') || (c0 == 'O')) && ((c1 == 'r') || (c1 == 'R'))) { pos += 2; *isAnd = NO; } pos += _countWhiteSpaces(_buf + pos, _bufLen - pos); qual = _parseSingleQualifier(_ctx, _buf + pos, _bufLen - pos, &len); *_opLen = pos + len; if (qDebug) NSLog(@"_testOperator return %@ for <%s> ", qual, _buf); return qual; } static EOQualifier *_parseCompoundQualifier(id _ctx, const char *_buf, unsigned _bufLen, unsigned *_qualLen) { EOQualifier *q0, *q1 = nil; NSMutableArray *array = nil; unsigned pos, len = 0; EOQualifier *result; BOOL isAnd; isAnd = YES; if ((q0 = _parseSingleQualifier(_ctx, _buf, _bufLen, &len)) == nil) { if (qDebug) NSLog(@"_parseAndOrQualifier return nil for <%s> ", _buf); return nil; } pos = len; if (!(q1 = _testOperator(_ctx, _buf + pos, _bufLen - pos, &len, &isAnd))) { if (qDebug) NSLog(@"_parseAndOrQualifier return nil for <%s> ", _buf); return nil; } pos += len; array = [NSMutableArray arrayWithObjects:q0, q1, nil]; while (YES) { BOOL newIsAnd; newIsAnd = YES; q0 = _testOperator(_ctx, _buf + pos, _bufLen - pos, &len, &newIsAnd); if (!q0) break; if (newIsAnd != isAnd) { NSArray *a; a = [[array copy] autorelease]; q1 = (isAnd) ? [_ctx andQualifierWithArray:a] : [_ctx orQualifierWithArray:a]; [array removeAllObjects]; [array addObject:q1]; isAnd = newIsAnd; } [array addObject:q0]; pos += len; } *_qualLen = pos; result = (isAnd) ? [_ctx andQualifierWithArray:array] : [_ctx orQualifierWithArray:array]; if (qDebug) NSLog(@"_parseAndOrQualifier return <%@> for <%s> ", result, _buf); return result; } static inline unsigned _countWhiteSpaces(const char *_buf, unsigned _bufLen) { unsigned cnt = 0; if (_bufLen == 0) { if (qDebug) NSLog(@"_parseString _bufLen == 0 --> return nil"); return 0; } while (_buf[cnt] == ' ' || _buf[cnt] == '\t' || _buf[cnt] == '\n' || _buf[cnt] == '\r') { cnt++; if (cnt == _bufLen) break; } return cnt; } SOPE/sope-core/EOControl/EONull.h0000644000000000000000000000230215004363604015367 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOControl_EONull_h__ #define __EOControl_EONull_h__ #import #ifndef HAVE_NSNull # define HAVE_NSNull 1 #endif #if HAVE_NSNull #import #define EONull NSNull #else /* !HAVE_NSNull | NeXT Foundation */ #import @interface EONull : NSObject + (id)null; @end /* EONull */ #endif /* !HAVE_NSNull */ #endif /* __EOControl_EONull_h__ */ SOPE/sope-core/EOControl/EOControl-Info.plist0000644000000000000000000000134415004363604017677 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable EOControl CFBundleGetInfoString CFBundleIdentifier org.OpenGroupware.SOPE.core.EOControl CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType FMWK CFBundleShortVersionString CFBundleSignature ???? CFBundleVersion 4.5 SOPE/sope-core/EOControl/EOKeyGlobalID.m0000644000000000000000000001006715004363604016557 0ustar rootroot/* Copyright (C) 2000-2006 SKYRIX Software AG Copyright (C) 2006 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOKeyGlobalID.h" #include "common.h" @implementation EOKeyGlobalID + (id)globalIDWithEntityName:(NSString *)_name keys:(id *)_keyValues keyCount:(unsigned int)_count zone:(NSZone *)_zone { EOKeyGlobalID *kid; NSAssert1(_count > 0, @"missing key-values (count is 0, entity is %@", _name); if ((kid = (id)NSAllocateObject(self, sizeof(id) * _count, _zone))) { unsigned int i; kid->entityName = [_name copyWithZone:_zone]; kid->count = _count; for (i = 0; i < _count; i++) { #if DEBUG if (_keyValues[i] == nil) { NSLog(@"WARN(%s): got 'nil' as a EOKeyGlobalID value (entity=%@)!", __PRETTY_FUNCTION__, _name); } #endif kid->values[i] = [_keyValues[i] retain]; } return [kid autorelease]; } return nil; } - (void)dealloc { unsigned int i; for (i = 0; i < self->count; i++) { [self->values[i] release]; self->values[i] = nil; } [self->entityName release]; [super dealloc]; } /* accessors */ - (NSString *)entityName { return self->entityName; } - (unsigned int)keyCount { return self->count; } - (id *)keyValues { return &(self->values[0]); } - (NSArray *)keyValuesArray { return [NSArray arrayWithObjects:&(self->values[0]) count:self->count]; } /* Equality */ - (NSUInteger)hash { return [self->entityName hash] - [self->values[0] hash]; } - (BOOL)isEqual:(id)_other { EOKeyGlobalID *otherKey; unsigned int i; if (_other == nil) return NO; if (_other == self) return YES; otherKey = _other; if (object_getClass(otherKey) != object_getClass(self)) return NO; if (otherKey->count != self->count) return NO; if (![otherKey->entityName isEqualToString:self->entityName]) return NO; for (i = 0; i < self->count; i++) { if (self->values[i] != otherKey->values[i]) { if (![self->values[i] isEqual:otherKey->values[i]]) return NO; } } return YES; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { return [self retain]; } /* NSCoding */ - (void)encodeWithCoder:(NSCoder *)_coder { [self doesNotRecognizeSelector:_cmd]; } - (id)initWithCoder:(NSCoder *)_coder { [self doesNotRecognizeSelector:_cmd]; return nil; #if 0 NSString *entityName; NSZone *z; unsigned int count; z = [self zone]; [self release]; entityName = [_coder decodeObject]; self = [EOKeyGlobalID globalIDWithEntityName:entityName keys:NULL keyCount:0 zone:z]; return [self retain]; #endif } /* description */ - (NSString *)description { NSMutableString *s; NSString *d; unsigned int i; s = [[NSMutableString alloc] init]; [s appendFormat:@"<0x%p[%@]: %@", self, NSStringFromClass([self class]), [self entityName]]; if (self->count == 0) { [s appendString:@" no-key-values"]; } else { for (i = 0; i < self->count; i++) { if (i == 0) [s appendString:@" "]; else [s appendString:@"/"]; if (self->values[i] == nil) [s appendString:@""]; else if (self->values[i] == nil) [s appendString:@""]; else [s appendString:[self->values[i] stringValue]]; } } [s appendString:@">"]; d = [s copy]; [s release]; return [d autorelease]; } @end /* EOKeyGlobalID */ SOPE/sope-core/EOControl/EOObserver.h0000644000000000000000000000617215004363604016255 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOControl_EOObserver_H__ #define __EOControl_EOObserver_H__ #import @class NSArray; @protocol EOObserving < NSObject > - (void)objectWillChange:(id)_object; @end @interface NSObject(EOObserver) - (void)willChange; @end /* Note that -addObserver/-removeObserver methods do *not* nest ! Suppression methods do nest. */ @interface EOObserverCenter : NSObject + (void)notifyObserversObjectWillChange:(id)_object; + (void)addObserver:(id)_observer forObject:(id)_object; + (void)removeObserver:(id)_observer forObject:(id)_object; + (void)addOmniscientObserver:(id)_observer; + (void)removeOmniscientObserver:(id)_observer; + (NSArray *)observersForObject:(id)_object; + (id)observerForObject:(id)_object ofClass:(Class)_targetClass; /* suppressing notifications */ + (void)suppressObserverNotification; + (void)enableObserverNotification; + (unsigned)observerNotificationSuppressCount; @end /* asynchronous observing */ typedef enum { EOObserverPriorityImmediate, EOObserverPriorityFirst, EOObserverPrioritySecond, EOObserverPriorityThird, EOObserverPriorityFourth, EOObserverPriorityFifth, EOObserverPrioritySixth, EOObserverPriorityLater } EOObserverPriority; @class EODelayedObserver; @interface EODelayedObserverQueue : NSObject { @protected EODelayedObserver *queues[8]; NSArray *runLoopModes; BOOL hasObservers; } + (EODelayedObserverQueue *)defaultObserverQueue; /* accessors */ - (void)setRunLoopModes:(NSArray *)_modes; - (NSArray *)runLoopModes; /* managing queue */ - (void)enqueueObserver:(EODelayedObserver *)_observer; - (void)dequeueObserver:(EODelayedObserver *)_observer; /* notification */ - (void)notifyObserversUpToPriority:(EOObserverPriority)_lastPriority; @end @interface EODelayedObserver : NSObject < EOObserving > { @public EODelayedObserver *next; /* for access by queue */ } /* accessors */ - (EOObserverPriority)priority; - (EODelayedObserverQueue *)observerQueue; /* notifications */ - (void)subjectChanged; - (void)discardPendingNotification; @end @interface EOObserverProxy : EODelayedObserver { @protected EOObserverPriority priority; id target; SEL action; } - (id)initWithTarget:(id)_target action:(SEL)_action priority:(EOObserverPriority)_priority; @end #endif /* __EOControl_EOObserver_H__ */ SOPE/sope-core/EOControl/EODetailDataSource.h0000644000000000000000000000324115004363604017635 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOControl_EODetailDataSource_H__ #define __EOControl_EODetailDataSource_H__ #include #include @class EOClassDescription; @interface EODetailDataSource : EODataSource < EOKeyValueArchiving > { EOClassDescription *masterClassDescription; EODataSource *masterDataSource; id masterObject; NSString *detailKey; } - (id)initWithMasterClassDescription:(EOClassDescription *)_cd detailKey:(NSString *)_relKey; // designated initializer - (id)initWithMasterDataSource:(EODataSource *)_ds detailKey:(NSString *)_relKey; /* reflection */ - (void)setMasterClassDescription:(EOClassDescription *)_cd; - (EOClassDescription *)masterClassDescription; - (EODataSource *)masterDataSource; /* master-detail */ - (id)masterObject; - (NSString *)detailKey; @end #endif /* __EOControl_EODetailDataSource_H__ */ SOPE/sope-core/EOControl/NSObject+QualDesc.m0000644000000000000000000000243615004363604017412 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EONull.h" #include "common.h" @implementation NSObject(QualifierDescription) - (NSString *)qualifierDescription { return [self description]; } @end /* NSObject(QualifierDescription) */ @implementation NSString(QualifierDescription) - (NSString *)qualifierDescription { return [NSString stringWithFormat:@"'%@'", self]; } @end /* NSString(QualifierDescription) */ @implementation EONull(QualifierDescription) - (NSString *)qualifierDescription { return @"nil"; } @end /* EONull(QualifierDescription) */ SOPE/sope-core/EOControl/COPYRIGHT0000644000000000000000000000010615004363604015353 0ustar rootrootCopyright (C) 2000-2005 SKYRIX Software AG Contact: info@skyrix.com SOPE/sope-core/EOControl/EOSortOrdering.m0000644000000000000000000002346115004363604017114 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOSortOrdering.h" #include "EOKeyValueCoding.h" #include #include "common.h" #if GNU_RUNTIME # include #endif @implementation EOSortOrdering /*" This class specifies a sort-ordering as used with EOFetchSpecification. It takes a key and a sort selector which is used for comparision. "*/ /*" Create a sort-ordering object with the specified key and sort selector "*/ + (EOSortOrdering *)sortOrderingWithKey:(NSString *)_key selector:(SEL)_sel { return [[[self alloc] initWithKey:_key selector:_sel] autorelease]; } /*" Initialize a sort-ordering object with the specified key and sort selector "*/ - (id)initWithKey:(NSString *)_key selector:(SEL)_selector { if ((self = [super init])) { self->key = [_key copyWithZone:[self zone]]; self->selector = _selector; } return self; } - (void)dealloc { [self->key release]; [super dealloc]; } /* accessors */ /*" Returns the key the ordering sorts with. "*/ - (NSString *)key { return self->key; } /*" Returns the selector the ordering sorts with. "*/ - (SEL)selector { return self->selector; } /* equality */ - (BOOL)isEqualToSortOrdering:(EOSortOrdering *)_sortOrdering { if (!sel_isEqual([_sortOrdering selector], [self selector])) return NO; if (![[_sortOrdering key] isEqualToString:[self key]]) return NO; return YES; } - (BOOL)isEqual:(id)_other { if ([_other isKindOfClass:[EOSortOrdering class]]) return [self isEqualToSortOrdering:_other]; return NO; } /* remapping keys */ - (EOSortOrdering *)sortOrderingByApplyingKeyMap:(NSDictionary *)_map { NSString *k; k = [_map objectForKey:self->key]; return [EOSortOrdering sortOrderingWithKey:(k ? k : self->key) selector:self->selector]; } /* key/value archiving */ - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { if ((self = [super init]) != nil) { NSString *s; self->key = [[_unarchiver decodeObjectForKey:@"key"] copy]; if ((s = [_unarchiver decodeObjectForKey:@"selector"]) != nil) self->selector = NSSelectorFromString(s); else if ((s = [_unarchiver decodeObjectForKey:@"selectorName"]) != nil) { if (![s hasSuffix:@":"]) s = [s stringByAppendingString:@":"]; self->selector = NSSelectorFromString(s); } } return self; } - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver { [_archiver encodeObject:[self key] forKey:@"key"]; [_archiver encodeObject:NSStringFromSelector([self selector]) forKey:@"selectorName"]; } /* description */ - (NSString *)description { return [NSString stringWithFormat: @"<0x%p[%@]: key=%@ selector=%@>", self, NSStringFromClass([self class]), [self key], NSStringFromSelector([self selector])]; } @end /* EOSortOrdering */ @implementation NSArray(EOSortOrdering) /*" Sort the array using the sort-orderings contained in the argument. If no orderings are given, a copy of self is returned. "*/ - (NSArray *)sortedArrayUsingKeyOrderArray:(NSArray *)_orderings { NSMutableArray *m = nil; NSArray *result = nil; if ([_orderings count] == 0) return [[self copy] autorelease]; m = [self mutableCopy]; [m sortUsingKeyOrderArray:_orderings]; result = [m copy]; [m release]; m = nil; return [result autorelease]; } @end /* NSArray(EOSortOrdering) */ @implementation NSMutableArray(EOSortOrdering) typedef struct { EOSortOrdering *orderings[10]; /* max depth 10 */ short count; } EOSortOrderingContext; static EONull *null = nil; static int keyOrderComparator(id o1, id o2, EOSortOrderingContext *context) { short i; for (i = 0; i < context->count; i++) { NSString *key; SEL sel; id v1, v2; int (*ccmp)(id, SEL, id); NSComparisonResult result; key = [context->orderings[i] key]; sel = [context->orderings[i] selector]; v1 = [o1 valueForKeyPath:key]; v2 = [o2 valueForKeyPath:key]; if (v1 == v2) result = NSOrderedSame; else if ((v1 == nil) || (v1 == null)) result = (sel == EOCompareAscending) ? NSOrderedAscending : NSOrderedDescending; else if ((v2 == nil) || (v2 == null)) result = (sel == EOCompareAscending) ? NSOrderedDescending : NSOrderedAscending; else if ((ccmp = (void *)[v1 methodForSelector:sel])) result = ccmp(v1, sel, v2); else result = (NSComparisonResult)[v1 performSelector:sel withObject:v2]; if (result != NSOrderedSame) return result; } return NSOrderedSame; } /*" Sort the array using the sort-orderings contained in the argument. "*/ - (void)sortUsingKeyOrderArray:(NSArray *)_orderings { NSEnumerator *e = nil; EOSortOrdering *ordering = nil; EOSortOrderingContext ctx; int i; NSAssert([_orderings count] < 10, @"max sort descriptor count is 10!"); e = [_orderings objectEnumerator]; for (i = 0; (ordering = [e nextObject]) && (i < 10); i++) ctx.orderings[i] = ordering; ctx.count = i; if (null == nil) null = [EONull null]; [self sortUsingFunction:(void *)keyOrderComparator context:&ctx]; } /*" Limit the comparison the first object of the compared arrays "*/ static Class ArrayClass = Nil; - (int)compareCaseInsensitiveDescending:(id)_object { int result; if (ArrayClass == Nil) ArrayClass = [NSArray class]; if (_object == self) return NSOrderedSame; if ([_object isKindOfClass: ArrayClass]) { if ([_object count] && [_object objectAtIndex: 0]) result = [[self objectAtIndex: 0] compareCaseInsensitiveAscending: [_object objectAtIndex: 0]]; else result = NSOrderedDescending; } else result = [[self objectAtIndex: 0] compareCaseInsensitiveAscending: _object]; if (result == NSOrderedAscending) return NSOrderedDescending; else if (result == NSOrderedDescending) return NSOrderedAscending; else return NSOrderedSame; } @end /* NSMutableArray(EOSortOrdering) */ @implementation EONull(EOSortOrdering) /*" Compares the null object, "nil" and "self" are considered of the same order, otherwise null is considered of lower order. "*/ - (int)compareAscending:(id)_object { if (_object == self) return NSOrderedSame; if (_object == nil) return NSOrderedSame; return NSOrderedDescending; } /*" Compares the null object, "nil" and "self" are considered of the same order, otherwise null is considered of higher order. "*/ - (int)compareDescending:(id)_object { if (_object == self) return NSOrderedSame; if (_object == nil) return NSOrderedSame; return NSOrderedAscending; } @end /* EONull(EOSortOrdering) */ @implementation NSNumber(EOSortOrdering) static Class NumClass = Nil; - (int)compareAscending:(id)_object { if (_object == self) return NSOrderedSame; if (NumClass == Nil) NumClass = [NSNumber class]; if ([_object isKindOfClass:NumClass]) return [self compare:_object]; else return [_object compareDescending:self]; } - (int)compareDescending:(id)_object { int result; result = [self compareAscending:_object]; if (result == NSOrderedAscending) return NSOrderedDescending; else if (result == NSOrderedDescending) return NSOrderedAscending; else return NSOrderedSame; } @end /* NSNumber(EOSortOrdering) */ @implementation NSString(EOSortOrdering) - (int)compareAscending:(id)_object { if (_object == self) return NSOrderedSame; return [self compare:[_object stringValue]]; } - (int)compareCaseInsensitiveAscending:(id)_object { if (_object == self) return NSOrderedSame; return [self caseInsensitiveCompare:[_object stringValue]]; } - (int)compareDescending:(id)_object { int result; if (_object == self) return NSOrderedSame; result = [self compareAscending:_object]; if (result == NSOrderedAscending) return NSOrderedDescending; else if (result == NSOrderedDescending) return NSOrderedAscending; else return NSOrderedSame; } - (int)compareCaseInsensitiveDescending:(id)_object { int result; if (_object == self) return NSOrderedSame; result = [self compareCaseInsensitiveAscending:_object]; if (result == NSOrderedAscending) return NSOrderedDescending; else if (result == NSOrderedDescending) return NSOrderedAscending; else return NSOrderedSame; } @end /* NSString(EOSortOrdering) */ @implementation NSDate(EOSortOrdering) static Class DateClass = Nil; - (int)compareAscending:(id)_object { if (_object == self) return NSOrderedSame; if (DateClass == Nil) DateClass = [NSDate class]; if (![_object isKindOfClass:DateClass]) return NSOrderedAscending; return [self compare:_object]; } - (int)compareDescending:(id)_object { int result; if (_object == self) return NSOrderedSame; if (DateClass == Nil) DateClass = [NSDate class]; if (![_object isKindOfClass:DateClass]) return NSOrderedDescending; result = [self compare:_object]; if (result == NSOrderedAscending) return NSOrderedDescending; else if (result == NSOrderedDescending) return NSOrderedAscending; else return NSOrderedSame; } @end /* NSDate(EOSortOrdering) */ SOPE/sope-core/EOControl/EOKeyValueCoding.h0000644000000000000000000000505315004363604017334 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOControl_EOKeyValueCoding_H__ #define __EOControl_EOKeyValueCoding_H__ #import #import #if NeXT_Foundation_LIBRARY #import #else @interface NSObject(EOKeyValueCoding) + (BOOL)accessInstanceVariablesDirectly; + (void)flushAllKeyBindings; - (void)handleTakeValue:(id)_value forUnboundKey:(NSString *)_key; - (id)handleQueryWithUnboundKey:(NSString *)_key; - (void)unableToSetNullForKey:(NSString *)_key; - (void)takeValuesFromDictionary:(NSDictionary *)_dictionary; - (NSDictionary *)valuesForKeys:(NSArray *)_keys; - (void)takeValue:(id)_value forKey:(NSString *)_key; - (id)valueForKey:(NSString *)_key; /* stored values */ + (BOOL)useStoredAccessor; - (void)takeStoredValue:(id)_value forKey:(NSString *)_key; - (id)storedValueForKey:(NSString *)_key; @end /* key-path stuff */ @interface NSObject(EOKeyPathValueCoding) - (void)takeValue:(id)_value forKeyPath:(NSString *)_keyPath; - (id)valueForKeyPath:(NSString *)_keyPath; @end /* array stuff */ @interface NSArray(EOKeyValueCoding) /* Special functions for computed values. Computed keys start with '@', seg '@sum'. Yoy can define own computed keys by following the method naming 'compute' + Func + 'ForKey:'. */ - (id)computeSumForKey:(NSString *)_key; - (id)computeAvgForKey:(NSString *)_key; - (id)computeCountForKey:(NSString *)_key; - (id)computeMaxForKey:(NSString *)_key; - (id)computeMinForKey:(NSString *)_key; /* Attention: NSArray's 'valueForKey:' is special in that it does not return properties of the array but an array of the properties of it's elements. That is, it is similar to a map function. */ - (id)valueForKey:(NSString *)_key; @end #endif /* !NeXT_Foundation_LIBRARY */ #endif /* __EOControl_EOKeyValueCoding_H__ */ SOPE/sope-core/EOControl/EOKeyValueArchiver.h0000644000000000000000000000557515004363604017705 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOControl_EOKeyValueArchiver_H__ #define __EOControl_EOKeyValueArchiver_H__ #import @class NSString, NSDictionary, NSMutableArray, NSMutableDictionary; @class NSMutableSet; @interface EOKeyValueArchiver : NSObject { NSMutableDictionary *plist; id delegate; // non-retained } /* coding */ - (void)encodeObject:(id)_obj forKey:(NSString *)_key; - (void)encodeReferenceToObject:(id)_obj forKey:(NSString *)_key; - (void)encodeBool:(BOOL)_flag forKey:(NSString *)_key; - (void)encodeInt:(int)_value forKey:(NSString *)_key; - (NSDictionary *)dictionary; /* delegate */ - (void)setDelegate:(id)_delegate; - (id)delegate; @end @interface EOKeyValueUnarchiver : NSObject { NSDictionary *plist; NSMutableArray *unarchivedObjects; NSMutableSet *awakeObjects; id parent; id delegate; // non-retained (eg a WOComponent) } - (id)initWithDictionary:(NSDictionary *)_dict; /* decoding */ - (id)decodeObjectForKey:(NSString *)_key; - (id)decodeObjectReferenceForKey:(NSString *)_key; /* ask delegate for obj */ - (BOOL)decodeBoolForKey:(NSString *)_key; - (int)decodeIntForKey:(NSString *)_key; - (id)decodeObjectAtIndex:(unsigned)_idx; /* operations */ - (void)ensureObjectAwake:(id)_object; - (void)finishInitializationOfObjects; - (void)awakeObjects; - (id)parent; /* delegate */ - (void)setDelegate:(id)_delegate; - (id)delegate; @end @protocol EOKeyValueArchiving - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver; - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver; @end @interface NSObject(EOKeyValueArchivingAwakeMethods) - (void)finishInitializationWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_un; - (void)awakeFromKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver; @end /* delegates */ @interface NSObject(KVCArchiverDelegates) - (id)archiver:(EOKeyValueArchiver *)_archiver referenceToEncodeForObject:(id)_obj; @end @interface NSObject(KVCUnarchiverDelegates) - (id)unarchiver:(EOKeyValueUnarchiver *)_unarchiver objectForReference:(id)_obj; @end #endif /* __EOControl_EOKeyValueArchiver_H__ */ SOPE/sope-core/EOControl/EOClassDescription.h0000644000000000000000000000734515004363604017742 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOControl_EOClassDescription_H__ #define __EOControl_EOClassDescription_H__ #import #include @class NSException, NSString, NSFormatter; @interface EOClassDescription : NSClassDescription @end @interface NSClassDescription(EOClassDescription) /* model */ - (NSString *)entityName; - (NSString *)inverseForRelationshipKey:(NSString *)_key; - (NSClassDescription *)classDescriptionForDestinationKey:(NSString *)_key; /* object initialization */ - (id)createInstanceWithEditingContext:(id)_ec globalID:(EOGlobalID *)_oid zone:(NSZone *)_zone; - (void)awakeObject:(id)_object fromFetchInEditingContext:(id)_ec; - (void)awakeObject:(id)_object fromInsertionInEditingContext:(id)_ec; /* delete */ - (void)propagateDeleteForObject:(id)_object editingContext:(id)_ec; /* entity names */ #if 0 // used by: EOGenericRecord.m + (NSClassDescription *)classDescriptionForEntityName:(NSString *)_entityName; #endif /* formatting */ - (NSFormatter *)defaultFormatterForKey:(NSString *)_key; - (NSFormatter *)defaultFormatterForKeyPath:(NSString *)_keyPath; @end @interface NSClassDescription(EOValidation) - (NSException *)validateObjectForDelete:(id)_object; - (NSException *)validateObjectForSave:(id)_object; - (NSException *)validateValue:(id *)_value forKey:(NSString *)_key; @end @interface NSObject(EOClassDescriptionInit) /* object initialization */ - (id)initWithEditingContext:(id)_ec classDescription:(NSClassDescription *)_classDesc globalID:(EOGlobalID *)_oid; - (void)awakeFromFetchInEditingContext:(id)_ec; - (void)awakeFromInsertionInEditingContext:(id)_ec; /* model */ - (NSString *)entityName; - (NSString *)inverseForRelationshipKey:(NSString *)_key; - (NSArray *)attributeKeys; - (NSArray *)toManyRelationshipKeys; - (NSArray *)toOneRelationshipKeys; - (BOOL)isToManyKey:(NSString *)_key; - (NSArray *)allPropertyKeys; /* delete */ - (void)propagateDeleteWithEditingContext:(id)_ec; @end /* validation */ @interface NSObject(EOValidation) - (NSException *)validateForDelete; - (NSException *)validateForInsert; - (NSException *)validateForUpdate; - (NSException *)validateForSave; @end @interface NSException(EOValidation) + (NSException *)aggregateExceptionWithExceptions:(NSArray *)_exceptions; @end /* snapshots */ @interface NSObject(EOSnapshots) - (NSDictionary *)snapshot; - (void)updateFromSnapshot:(NSDictionary *)_snapshot; - (NSDictionary *)changesFromSnapshot:(NSDictionary *)_snapshot; @end /* relationships */ @interface NSObject(EORelationshipManipulation) - (void)addObject:(id)_o toBothSidesOfRelationshipWithKey:(NSString *)_key; - (void)removeObject:(id)_o fromBothSidesOfRelationshipWithKey:(NSString *)_key; - (void)addObject:(id)_object toPropertyWithKey:(NSString *)_key; - (void)removeObject:(id)_object fromPropertyWithKey:(NSString *)_key; @end /* shallow array copying */ @interface NSArray(ShallowCopy) - (id)shallowCopy; @end #endif /* __EOControl_EOClassDescription_H__ */ SOPE/sope-core/EOControl/SxCore-EOControl.graffle0000644000000000000000000011232115004363604020460 0ustar rootroot CanvasColor w 1.000000e+00 ColumnAlign 0 ColumnSpacing 5.400000e+01 GraphDocumentVersion 2 GraphicsList Bounds {{45, 414}, {162, 18}} Class ShapedGraphic ID 2788 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOQualifier.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOQualifierVariable} Bounds {{45, 351}, {162, 18}} Class ShapedGraphic ID 2787 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOGenericRecord.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOGenericRecord} Class Group Graphics Bounds {{243, 270}, {135, 18}} Class ShapedGraphic ID 2782 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOKeyGlobalID.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOKeyGlobalID} Bounds {{387, 270}, {135, 18}} Class ShapedGraphic ID 2783 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOGlobalID.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOTemporaryGlobalID} Bounds {{315, 234}, {135, 18}} Class ShapedGraphic ID 2784 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOGlobalID.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOGlobalID} Class LineGraphic Head ID 2782 ID 2785 Points {364.5, 252} {328.5, 270} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 2784 Class LineGraphic Head ID 2783 ID 2786 Points {400.5, 252} {436.5, 270} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 2784 ID 2781 Bounds {{45, 315}, {162, 18}} Class ShapedGraphic ID 2780 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOSortOrdering.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOSortOrdering} Bounds {{45, 162}, {162, 18}} Class ShapedGraphic ID 2779 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOObserver.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOObserverCenter} Class Group Graphics Bounds {{99, 585}, {126, 18}} Class ShapedGraphic ID 2762 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOQualifier.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EONotQualifier} Bounds {{297, 630}, {126, 18}} Class ShapedGraphic ID 2763 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOQualifier.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOAndQualifier} Bounds {{315, 594}, {126, 18}} Class ShapedGraphic ID 2764 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOQualifier.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOKeyValueQualifier} Bounds {{333, 558}, {126, 18}} Class ShapedGraphic ID 2765 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOQualifier.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOOrQualifier} Bounds {{99, 504}, {135, 18}} Class ShapedGraphic ID 2766 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOQualifier.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 EOQualifierEvaluation} Bounds {{279, 504}, {126, 18}} Class ShapedGraphic ID 2767 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOQualifier.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOQualifier} Bounds {{99, 630}, {171, 18}} Class ShapedGraphic ID 2768 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOQualifier.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOKeyComparisonQualifier} Class LineGraphic Head ID 2762 ID 2769 Points {166, 522} {162.5, 585} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 2766 Class LineGraphic Head ID 2762 ID 2770 Points {322, 522} {182, 585} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 2767 Class LineGraphic Head ID 2763 ID 2771 Points {180.321, 522} {346.179, 630} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 2766 Class LineGraphic Head ID 2763 ID 2772 Points {343.286, 522} {358.714, 630} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 2767 Class LineGraphic Head ID 2764 ID 2773 Points {187.65, 522} {356.85, 594} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 2766 Class LineGraphic Head ID 2764 ID 2774 Points {345.6, 522} {374.4, 594} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 2767 Class LineGraphic Head ID 2765 ID 2775 Points {204.75, 522} {357.75, 558} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 2766 Class LineGraphic Head ID 2765 ID 2776 Points {351, 522} {387, 558} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 2767 Class LineGraphic Head ID 2768 ID 2777 Points {167.786, 522} {183.214, 630} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 2766 Class LineGraphic Head ID 2768 ID 2778 Points {330.75, 522} {195.75, 630} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 2767 ID 2761 Class Group Graphics Bounds {{243, 342}, {126, 18}} Class ShapedGraphic ID 2759 Shape RoundedRectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NSClassDescription} Bounds {{243, 378}, {126, 18}} Class ShapedGraphic ID 2760 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOClassDescription.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOClassDescription} ID 2758 Class Group Graphics Bounds {{387, 342}, {126, 18}} Class ShapedGraphic ID 2755 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOObserver.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 EOObserving} Bounds {{387, 378}, {126, 18}} Class ShapedGraphic ID 2756 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOObserver.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EODelayedObserver} Bounds {{387, 414}, {126, 18}} Class ShapedGraphic ID 2757 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOObserver.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOObserverProxy} ID 2754 Class Group Graphics Bounds {{252, 153}, {126, 18}} Class ShapedGraphic ID 2749 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EODetailDataSource.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EODetailDataSource} Bounds {{387, 153}, {126, 18}} Class ShapedGraphic ID 2750 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOArrayDataSource.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOArrayDataSource} Bounds {{324, 117}, {126, 18}} Class ShapedGraphic ID 2751 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EODataSource.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EODataSource} Class LineGraphic Head ID 2749 ID 2752 Points {369, 135} {333, 153} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 2751 Class LineGraphic Head ID 2750 ID 2753 Points {402.75, 135} {434.25, 153} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 2751 ID 2748 Bounds {{45, 126}, {162, 18}} Class ShapedGraphic ID 2747 Link Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 } Bounds {{45, 99}, {162, 18}} Class ShapedGraphic ID 2746 Link Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 } Bounds {{45, 288}, {162, 18}} Class ShapedGraphic ID 2745 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOFetchSpecification.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOFetchSpecification} Bounds {{45, 189}, {162, 18}} Class ShapedGraphic ID 2744 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOObserver.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EODelayedObserverQueue} Bounds {{45, 378}, {162, 18}} Class ShapedGraphic ID 2743 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EONull.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EONull} Bounds {{45, 252}, {162, 18}} Class ShapedGraphic ID 2742 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOKeyValueArchiver.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOKeyValueUnarchiver} Bounds {{45, 225}, {162, 18}} Class ShapedGraphic ID 2741 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EOKeyValueArchiver.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EOKeyValueArchiver} Class LineGraphic Head ID 2760 ID 2740 Points {306, 360} {306, 378} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 2759 Class LineGraphic Head ID 2756 ID 2739 Points {450, 360} {450, 378} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 2755 Class LineGraphic Head ID 2757 ID 2738 Points {450, 396} {450, 414} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 2756 GridInfo HPages 1 ImageCounter 1 IsPalette NO Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo AutoAdjust YES HierarchicalOrientation 0 MagneticFieldCenter {0, 0} MagnetsEnabled YES PageBreakColor w 3.333333e-01 PageBreaks YES PageSetup BAt0eXBlZHN0cmVhbYED6IQBQISEhAtOU1ByaW50SW5mbwGEhAhOU09iamVjdACFkoSE hBNOU011dGFibGVEaWN0aW9uYXJ5AISEDE5TRGljdGlvbmFyeQCUhAFpEpKEhIQITlNT dHJpbmcBlIQBKxBOU0pvYkRpc3Bvc2l0aW9uhpKEmZkPTlNQcmludFNwb29sSm9ihpKE mZkOTlNCb3R0b21NYXJnaW6GkoSEhAhOU051bWJlcgCEhAdOU1ZhbHVlAJSEASqEhAFm nSSGkoSZmQtOU1BhcGVyTmFtZYaShJmZBkxldHRlcoaShJmZD05TUHJpbnRBbGxQYWdl c4aShJ2chIQBc54AhpKEmZkNTlNSaWdodE1hcmdpboaShJ2cn50khpKEmZkITlNDb3Bp ZXOGkoSdnISEAVOfAYaShJmZD05TU2NhbGluZ0ZhY3RvcoaShJ2chIQBZKABhpKEmZkL TlNGaXJzdFBhZ2WGkoSdnKmfAYaShJmZFE5TVmVydGljYWxQYWdpbmF0aW9uhpKEnZyk ngCGkoSZmRVOU0hvcml6b25hbFBhZ2luYXRpb26GkoSdnKSeAIaShJmZFk5TSG9yaXpv bnRhbGx5Q2VudGVyZWSGkoSdnKSeAYaShJmZDE5TTGVmdE1hcmdpboaShJ2cn50khpKE mZkNTlNPcmllbnRhdGlvboaShJ2cpJ4AhpKEmZkZTlNQcmludFJldmVyc2VPcmllbnRh dGlvboaSo5KEmZkKTlNMYXN0UGFnZYaShJ2chJeXgn////+GkoSZmQtOU1RvcE1hcmdp boaShJ2cn50khpKEmZkUTlNWZXJ0aWNhbGx5Q2VudGVyZWSGkrSShJmZC05TUGFwZXJT aXplhpKEnpyEhAx7X05TU2l6ZT1mZn2hgQJkgQMYhoaG RowAlign 0 RowSpacing 8.999991e+00 VPages 1 WindowInfo Frame {{67, 21}, {821, 897}} VisibleRegion {{-133, -50}, {806, 820}} Zoom 1 SOPE/sope-core/EOControl/TODO0000644000000000000000000000014215004363604014550 0ustar rootrootTODOs: EOSQLParser.m - remove usage of stringByReplacingString: which is not available on MacOSX SOPE/sope-core/EOControl/EOClassDescription.m0000644000000000000000000003130415004363604017737 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOClassDescription.h" #include "EOKeyValueCoding.h" #include "EONull.h" #include "common.h" @implementation NSClassDescription(EOClassDescription) /* model */ - (NSString *)entityName { return nil; } - (NSString *)inverseForRelationshipKey:(NSString *)_key { return nil; } - (NSClassDescription *)classDescriptionForDestinationKey:(NSString *)_key { return nil; } /* object initialization */ - (id)createInstanceWithEditingContext:(id)_ec globalID:(EOGlobalID *)_oid zone:(NSZone *)_zone { return nil; } - (void)awakeObject:(id)_object fromFetchInEditingContext:(id)_ec { } - (void)awakeObject:(id)_object fromInsertionInEditingContext:(id)_ec { } /* formatting */ - (NSFormatter *)defaultFormatterForKey:(NSString *)_key { return nil; } - (NSFormatter *)defaultFormatterForKeyPath:(NSString *)_keyPath { return nil; } /* delete */ - (void)propagateDeleteForObject:(id)_object editingContext:(id)_ec { } @end /* NSClassDescription(EOClassDescription) */ @implementation EOClassDescription // THREAD static NSMapTable *entityToDesc = NULL; static NSMapTable *classToDesc = NULL; + (void)initialize { if (entityToDesc == NULL) { entityToDesc = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 32); } if (classToDesc == NULL) { classToDesc = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 32); } } + (NSClassDescription *)classDescriptionForClass:(Class)_class { EOClassDescription *d; #if DEBUG NSAssert(_class != [EOGlobalID class], @"classDescriptionForClass:EOGlobalID ???"); #endif if ((d = NSMapGet(classToDesc, _class))) return d; [[NSNotificationCenter defaultCenter] postNotificationName: @"EOClassDescriptionNeededForClass" object:_class]; return NSMapGet(classToDesc, _class); } + (NSClassDescription *)classDescriptionForEntityName:(NSString *)_entityName { NSClassDescription *d; if ((d = NSMapGet(entityToDesc, _entityName))) return d; [[NSNotificationCenter defaultCenter] postNotificationName: @"EOClassDescriptionNeededForEntityName" object:_entityName]; return NSMapGet(entityToDesc, _entityName); } + (void)invalidateClassDescriptionCache { NSResetMapTable(entityToDesc); NSResetMapTable(classToDesc); } + (void)registerClassDescription:(NSClassDescription *)_clazzDesc forClass:(Class)_class { NSString *entityName; if (_clazzDesc == nil) return; if (_class) NSMapInsert(classToDesc, _class, _clazzDesc); if ((entityName = [_clazzDesc entityName])) NSMapInsert(entityToDesc, entityName, _clazzDesc); } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"<%@[0x%p]: entity=%@>", NSStringFromClass([self class]), self, [self entityName]]; } @end /* EOClassDescription */ @implementation NSObject(EOClassDescription) - (NSClassDescription *)classDescriptionForDestinationKey:(NSString *)_key { return [[self classDescription] classDescriptionForDestinationKey:_key]; } /* object initialization */ - (id)initWithEditingContext:(id)_ec classDescription:(NSClassDescription *)_classDesc globalID:(EOGlobalID *)_oid { return [self init]; } - (void)awakeFromFetchInEditingContext:(id)_ec { [[self classDescription] awakeObject:self fromFetchInEditingContext:_ec]; } - (void)awakeFromInsertionInEditingContext:(id)_ec { [[self classDescription] awakeObject:self fromInsertionInEditingContext:_ec]; } /* model */ - (NSString *)entityName { return [[self classDescription] entityName]; } - (NSString *)inverseForRelationshipKey:(NSString *)_key { return [[self classDescription] inverseForRelationshipKey:_key]; } - (NSArray *)attributeKeys { return [[self classDescription] attributeKeys]; } - (BOOL)isToManyKey:(NSString *)_key { return [[self toManyRelationshipKeys] containsObject:_key]; } - (NSArray *)allPropertyKeys { NSArray *attrs; attrs = [self attributeKeys]; attrs = attrs ? [attrs arrayByAddingObjectsFromArray:[self toOneRelationshipKeys]] : [self toOneRelationshipKeys]; attrs = attrs ? [attrs arrayByAddingObjectsFromArray:[self toManyRelationshipKeys]] : [self toManyRelationshipKeys]; return attrs; } /* delete */ - (void)propagateDeleteWithEditingContext:(id)_ec { [[self classDescription] propagateDeleteForObject:self editingContext:_ec]; } @end /* NSObject(EOClassDescription) */ @implementation NSException(EOValidation) + (NSException *)aggregateExceptionWithExceptions:(NSArray *)_exceptions { NSException *e; e = [[self alloc] initWithName:@"EOAggregateException" reason:@"several exceptions occured" userInfo: [NSDictionary dictionaryWithObject:_exceptions forKey:@"exceptions"]]; return [e autorelease]; } @end /* NSException(EOValidation) */ /* snapshots */ @implementation NSObject(EOSnapshots) - (NSDictionary *)snapshot { static NSNull *null = nil; NSMutableDictionary *d; NSDictionary *r; NSEnumerator *e; NSString *key; if (null == nil) null = [NSNull null]; d = [[NSMutableDictionary alloc] initWithCapacity:64]; e = [[self attributeKeys] objectEnumerator]; while ((key = [e nextObject])) { id value; value = [self valueForKey:key]; value = (value == nil) ? (id)[null retain] : (id)[value copy]; [d setObject:value forKey:key]; [value release]; value = nil; } e = [[self toOneRelationshipKeys] objectEnumerator]; while ((key = [e nextObject])) { id value; value = [self valueForKey:key]; if (value == nil) value = [NSNull null]; [d setObject:value forKey:key]; } e = [[self toManyRelationshipKeys] objectEnumerator]; while ((key = [e nextObject])) { id value; value = [self valueForKey:key]; if (value == nil) { value = [[NSNull null] retain]; } else { value = [value shallowCopy]; } [d setObject:value forKey:key]; [value release]; value = nil; } r = [d copy]; [d release]; d = nil; return [r autorelease]; } - (void)updateFromSnapshot:(NSDictionary *)_snapshot { [self takeValuesFromDictionary:_snapshot]; } - (NSDictionary *)changesFromSnapshot:(NSDictionary *)_snapshot { /* not really correct, need to work on relationships */ static NSNull *null = nil; NSMutableDictionary *diff; NSEnumerator *props; NSString *key; if (null == nil) null = [NSNull null]; diff = [NSMutableDictionary dictionaryWithCapacity:32]; props = [[self allPropertyKeys] objectEnumerator]; while ((key = [props nextObject])) { id value; id svalue; value = [self valueForKey:key]; svalue = [_snapshot objectForKey:key]; if (value == nil) value = null; if (svalue == nil) svalue = null; if (svalue != value) { /* difference */ if ([self isToManyKey:key]) { id adiff[2]; adiff[0] = [NSArray array]; adiff[1] = [NSArray array]; /* to be completed: calc real diff */ [diff setObject:[NSArray arrayWithObjects:adiff count:2] forKey:key]; } else [diff setObject:value forKey:key]; } } return diff; } - (void)reapplyChangesFromDictionary:(NSDictionary *)_changes { /* not really correct, need to work on relationships */ NSEnumerator *keys; NSString *key; keys = [_changes keyEnumerator]; while ((key = [keys nextObject])) { id value; value = [_changes objectForKey:key]; if ([self isToManyKey:key]) { NSArray *added; NSArray *deleted; NSMutableArray *current; added = [value objectAtIndex:0]; deleted = [value objectAtIndex:1]; current = [[self valueForKey:key] mutableCopy]; if (added) [current addObjectsFromArray:added]; if (deleted) [current removeObjectsInArray:deleted]; [current release]; current = nil; } else [self takeValue:value forKey:key]; [self takeValuesFromDictionary:_changes]; } } @end /* NSObject(EOSnapshots) */ /* relationships */ @implementation NSObject(EORelationshipManipulation) - (void)addObject:(id)_o toBothSidesOfRelationshipWithKey:(NSString *)_key { NSString *revKey; BOOL isToMany; revKey = [self inverseForRelationshipKey:_key]; isToMany = [self isToManyKey:_key]; self = [[self retain] autorelease]; _o = [[_o retain] autorelease]; if (isToMany) { /* watch out, likely to be buggy ! */ [self addObject:_o toPropertyWithKey:_key]; } else [self takeValue:_o forKey:_key]; if (revKey) { /* add to the reverse object */ BOOL revIsToMany; revIsToMany = [_o isToManyKey:revKey]; if (revIsToMany) [_o addObject:self toPropertyWithKey:revKey]; else [_o takeValue:self forKey:revKey]; } } - (void)removeObject:(id)_o fromBothSidesOfRelationshipWithKey:(NSString *)_key { NSString *revKey; BOOL isToMany; revKey = [self inverseForRelationshipKey:_key]; isToMany = [self isToManyKey:_key]; self = [[self retain] autorelease]; _o = [[_o retain] autorelease]; /* remove from this object */ if (isToMany) [self removeObject:_o fromPropertyWithKey:_key]; else [self takeValue:nil forKey:_key]; if (revKey) { /* remove from reverse object */ BOOL revIsToMany; revIsToMany = [_o isToManyKey:revKey]; if (revIsToMany) [_o removeObject:self fromPropertyWithKey:revKey]; else [_o takeValue:nil forKey:revKey]; } } - (void)addObject:(id)_object toPropertyWithKey:(NSString *)_key { NSString *selname; SEL sel; selname = [@"addTo" stringByAppendingString:[_key capitalizedString]]; sel = NSSelectorFromString(selname); if ([self respondsToSelector:sel]) [self performSelector:sel withObject:_object]; else { id v; v = [self valueForKey:_key]; if ([self isToManyKey:_key]) { /* to-many relationship */ if (v == nil) { [self takeValue:[NSArray arrayWithObject:_object] forKey:_key]; } else if (![v containsObject:_object]) { if ([v respondsToSelector:@selector(addObject:)]) [v addObject:_object]; else { v = [v arrayByAddingObject:_object]; [self takeValue:v forKey:_key]; } } } else { /* to-one relationship */ if (v != _object) [self takeValue:v forKey:_key]; } } } - (void)removeObject:(id)_object fromPropertyWithKey:(NSString *)_key { NSString *selname; SEL sel; selname = [@"removeFrom" stringByAppendingString:[_key capitalizedString]]; sel = NSSelectorFromString(selname); if ([self respondsToSelector:sel]) [self performSelector:sel withObject:_object]; else { id v; v = [self valueForKey:_key]; if ([self isToManyKey:_key]) { /* to-many relationship */ if (v == nil) { /* do nothing */ } else if (![v containsObject:_object]) { if ([v respondsToSelector:@selector(addObject:)]) [v removeObject:_object]; else { v = [v mutableCopy]; [v removeObject:_object]; [self takeValue:v forKey:_key]; [v release]; v = nil; } } } else { /* to-one relationship */ [self takeValue:nil forKey:_key]; } } } @end /* NSObject(EORelationshipManipulation) */ /* shallow array copying */ @implementation NSArray(ShallowCopy) - (id)shallowCopy { NSArray *a; unsigned i, cc; id *objects; cc = [self count]; objects = calloc(cc + 1, sizeof(id)); for (i = 0; i < cc; i++) objects[i] = [self objectAtIndex:i]; a = [[NSArray alloc] initWithObjects:objects count:cc]; if (objects) free(objects); return a; } @end /* NSArray(ShallowCopy) */ SOPE/sope-core/EOControl/GNUmakefile.preamble0000644000000000000000000000114415004363604017723 0ustar rootroot# GNUstep Makefile libEOControl_INCLUDE_DIRS += -I.. ADDITIONAL_CPPFLAGS += -Wall -funsigned-char ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) SYSTEM_LIB_DIR += -L/usr/local/lib64 -L/usr/lib64 else SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib endif # libFoundation, gstep-base ifeq ($(FOUNDATION_LIB),fd) libEOControl_LIBRARIES_DEPEND_UPON += -lFoundation endif ifeq ($(FOUNDATION_LIB),gnu) libEOControl_LIBRARIES_DEPEND_UPON += $(BASE_LIBS) endif # Apple ifeq ($(FOUNDATION_LIB),apple) libEOControl_PREBIND_ADDR="0xC1000000" libEOControl_LDFLAGS += -seg1addr $(libEOControl_PREBIND_ADDR) endif SOPE/sope-core/EOControl/EOKeyValueArchiver.m0000644000000000000000000002136115004363604017701 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOKeyValueArchiver.h" #include "common.h" @implementation EOKeyValueArchiver - (id)init { if ((self = [super init])) { self->plist = [[NSMutableDictionary alloc] init]; } return self; } - (void)dealloc { [self->plist release]; [super dealloc]; } /* coding */ static BOOL isPListObject(id _obj) { if ([_obj isKindOfClass:[NSString class]]) return YES; if ([_obj isKindOfClass:[NSData class]]) return YES; if ([_obj isKindOfClass:[NSArray class]]) return YES; return NO; } - (void)encodeObject:(id)_obj forKey:(NSString *)_key { NSMutableDictionary *oldPlist; if (isPListObject(_obj)) { id c; c = [_obj copy]; [self->plist setObject:c forKey:_key]; [c release]; return; } oldPlist = self->plist; self->plist = [[NSMutableDictionary alloc] init]; if (_obj) { /* store class name */ [self->plist setObject:NSStringFromClass([_obj class]) forKey:@"class"]; /* let object store itself */ [_obj encodeWithKeyValueArchiver:self]; } else { /* nil ??? */ } [oldPlist setObject:self->plist forKey:_key]; [self->plist release]; self->plist = oldPlist; } - (void)encodeReferenceToObject:(id)_obj forKey:(NSString *)_key { if ([self->delegate respondsToSelector: @selector(archiver:referenceToEncodeForObject:)]) _obj = [self->delegate archiver:self referenceToEncodeForObject:_obj]; /* if _obj wasn't replaced by the delegate, encode the object in place .. */ [self encodeObject:_obj forKey:_key]; } - (void)encodeBool:(BOOL)_flag forKey:(NSString *)_key { /* NO values are not archived .. */ if (_flag) { [self->plist setObject:@"YES" forKey:_key]; } } - (void)encodeInt:(int)_value forKey:(NSString *)_key { [self->plist setObject:[NSString stringWithFormat:@"%i", _value] forKey:_key]; } - (NSDictionary *)dictionary { return [[self->plist copy] autorelease]; } /* delegate */ - (void)setDelegate:(id)_delegate { self->delegate = _delegate; } - (id)delegate { return self->delegate; } @end /* EOKeyValueArchiver */ @implementation EOKeyValueUnarchiver - (id)initWithDictionary:(NSDictionary *)_dict { self->plist = [_dict copy]; self->unarchivedObjects = [[NSMutableArray alloc] initWithCapacity:16]; // should be a hashtable self->awakeObjects = [[NSMutableSet alloc] initWithCapacity:16]; return self; } - (id)init { [self release]; return nil; } - (void)dealloc { [self->awakeObjects release]; [self->unarchivedObjects release]; [self->plist release]; [super dealloc]; } /* class handling */ - (Class)classForName:(NSString *)_name { /* This method maps class names. It is intended for archives which are written by the Java bridge and therefore use fully qualified Java package names. The mapping is hardcoded for now, this could be extended to use a dictionary if considered necessary. */ NSString *lastComponent = nil; Class clazz; NSRange r; if (_name == nil) return nil; if ((clazz = NSClassFromString(_name)) != Nil) return clazz; /* check for Java like . names (eg com.webobjects.directtoweb.Assignment) */ r = [_name rangeOfString:@"." options:NSBackwardsSearch]; if (r.length > 0) { lastComponent = [_name substringFromIndex:(r.location + r.length)]; /* first check whether the last name directly matches a class */ if ((clazz = NSClassFromString(lastComponent)) != Nil) return clazz; /* then check some hardcoded prefixes */ if ([_name hasPrefix:@"com.webobjects.directtoweb"]) { if ((clazz = NSClassFromString(lastComponent)) != Nil) return clazz; } NSLog(@"WARNING(%s): could not map Java class in unarchiver: '%@'", __PRETTY_FUNCTION__, _name); } return Nil; } /* decoding */ - (id)_decodeCurrentPlist { NSString *className; Class clazz; id obj; if ([self->plist isKindOfClass:[NSArray class]]) { unsigned count; if ((count = [self->plist count]) == 0) obj = [[self->plist copy] autorelease]; else { unsigned i; id *objs; objs = calloc(count + 1, sizeof(id)); for (i = 0; i < count; i++) objs[i] = [self decodeObjectAtIndex:i]; obj = [NSArray arrayWithObjects:objs count:count]; if (objs != NULL) free(objs); } return obj; } if (![self->plist isKindOfClass:[NSDictionary class]]) return [[self->plist copy] autorelease]; /* handle dictionary */ if ((className = [self->plist objectForKey:@"class"]) == nil) return [[self->plist copy] autorelease]; /* treat as plain dictionary */ if ((clazz = [self classForName:className]) == nil) { NSLog(@"WARNING(%s): did not find class specified in archive '%@': %@", __PRETTY_FUNCTION__, className, self->plist); return nil; } /* create custom object */ obj = [clazz alloc]; obj = [obj initWithKeyValueUnarchiver:self]; if (obj != nil) [self->unarchivedObjects addObject:obj]; else { NSLog(@"WARNING(%s): could not unarchive object %@", __PRETTY_FUNCTION__, self->plist); } if (self->unarchivedObjects != nil) [obj release]; else [obj autorelease]; return obj; } - (id)decodeObjectAtIndex:(unsigned)_idx { NSDictionary *lastParent; id obj; /* push */ lastParent = self->parent; self->parent = self->plist; self->plist = [(NSArray *)self->parent objectAtIndex:_idx]; obj = [self _decodeCurrentPlist]; /* pop */ self->plist = self->parent; self->parent = lastParent; return obj != nil ? obj : (id)[NSNull null]; } - (id)decodeObjectForKey:(NSString *)_key { NSDictionary *lastParent; id obj; /* push */ lastParent = self->parent; self->parent = self->plist; self->plist = [(NSDictionary *)self->parent objectForKey:_key]; obj = [self _decodeCurrentPlist]; /* pop */ self->plist = self->parent; self->parent = lastParent; return obj; } - (id)decodeObjectReferenceForKey:(NSString *)_key { id refObj, obj; refObj = [self decodeObjectForKey:_key]; if ([self->delegate respondsToSelector: @selector(unarchiver:objectForReference:)]) { obj = [self->delegate unarchiver:self objectForReference:refObj]; if (obj != nil) [self->unarchivedObjects addObject:obj]; } else { /* if delegate does not dereference, pass back the reference object */ obj = refObj; } return obj; } - (BOOL)decodeBoolForKey:(NSString *)_key { id v; if ((v = [self->plist objectForKey:_key]) == nil) return NO; if ([v isKindOfClass:[NSString class]]) { unsigned l = [v length]; if (l == 4 && [v isEqualToString:@"true"]) return YES; if (l == 5 && [v isEqualToString:@"false"]) return NO; if (l == 3 && [v isEqualToString:@"YES"]) return YES; if (l == 2 && [v isEqualToString:@"NO"]) return NO; if (l == 1 && [v characterAtIndex:0] == '1') return YES; if (l == 1 && [v characterAtIndex:0] == '0') return NO; } return [v boolValue]; } - (int)decodeIntForKey:(NSString *)_key { return [[self->plist objectForKey:_key] intValue]; } /* operations */ - (void)ensureObjectAwake:(id)_object { if (![self->awakeObjects containsObject:_object]) { if ([_object respondsToSelector:@selector(awakeFromKeyValueUnarchiver:)]) { [_object awakeFromKeyValueUnarchiver:self]; } [self->awakeObjects addObject:_object]; } } - (void)awakeObjects { NSEnumerator *e; id obj; e = [self->unarchivedObjects objectEnumerator]; while ((obj = [e nextObject]) != nil) [self ensureObjectAwake:obj]; } - (void)finishInitializationOfObjects { NSEnumerator *e; id obj; e = [self->unarchivedObjects objectEnumerator]; while ((obj = [e nextObject]) != nil) { if ([obj respondsToSelector: @selector(finishInitializationWithKeyValueUnarchiver:)]) [obj finishInitializationWithKeyValueUnarchiver:self]; } } - (id)parent { return self->parent; } /* delegate */ - (void)setDelegate:(id)_delegate { self->delegate = _delegate; } - (id)delegate { return self->delegate; } @end /* EOKeyValueUnarchiver */ SOPE/sope-core/EOCoreData/0000755000000000000000000000000015004363604014125 5ustar rootrootSOPE/sope-core/EOCoreData/EOCoreData-Info.plist0000644000000000000000000000134615004363604020005 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable EOCoreData CFBundleGetInfoString CFBundleIdentifier org.OpenGroupware.SOPE.core.EOCoreData CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType FMWK CFBundleShortVersionString CFBundleSignature ???? CFBundleVersion 4.5 SOPE/sope-core/EOCoreData/NSRelationshipDescription+EO.h0000644000000000000000000000260415004363604021705 0ustar rootroot/* Copyright (C) 2005-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NSRelationshipDescription_EO_H__ #define __NSRelationshipDescription_EO_H__ // the next two are here to please the Leopard #import @class NSData; #import /* NSRelationshipDescription(EO) Make an NSRelationshipDescription behave like an EORelationship. This is mostly to make the CoreData model objects work with DirectToWeb and EO at the same time. */ @class NSArray; @interface NSRelationshipDescription(EO) - (NSArray *)sourceAttributes; @end #endif /* __NSRelationshipDescription_EO_H__ */ SOPE/sope-core/EOCoreData/NSPredicate+EO.h0000644000000000000000000000244015004363604016736 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NSPredicate_EO_H__ #define __NSPredicate_EO_H__ #import #import #include /* NSPredicate(EO) Convert an NSPredicate to an EOQualifier. */ @class NSExpression; @class EOQualifier; @interface NSPredicate(EO) - (NSPredicate *)asPredicate; - (NSExpression *)asExpression; - (EOQualifier *)asQualifier; @end @interface NSComparisonPredicate(EOCoreData) < EOKeyValueArchiving > @end #endif /* __NSPredicate_EO_H__ */ SOPE/sope-core/EOCoreData/NSAttributeDescription+EO.m0000644000000000000000000000367115004363604021221 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSAttributeDescription+EO.h" #import #include "common.h" @implementation NSAttributeDescription(EO) - (unsigned)width { /* This scans for a validation predicate checking for the maximum length. The code looks for: - an NSComparisonPredicate - which has the operator <= - and a keypath LHS with the keypath 'length' Note: only scans one level, does not walk NSCompoundPredicates */ NSArray *preds; unsigned i, count; if ((preds = [self validationPredicates]) == nil) return 0; if ((count = [preds count]) == 0) return 0; for (i = 0; i < count; i++) { NSComparisonPredicate *p; p = [preds objectAtIndex:i]; if (![p isKindOfClass:[NSComparisonPredicate class]]) continue; if ([p predicateOperatorType] != NSLessThanOrEqualToPredicateOperatorType) continue; if (![[[p leftExpression] keyPath] isEqualToString:@"length"]) continue; /* found it! */ return [[[p rightExpression] constantValue] unsignedIntValue]; } return 0; } - (BOOL)allowsNull { return [self isOptional]; } @end /* NSAttributeDescription(EO) */ SOPE/sope-core/EOCoreData/EOSortOrdering+CoreData.m0000644000000000000000000000526315004363604020634 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOSortOrdering+CoreData.h" #include "common.h" @implementation EOSortOrdering(CoreData) - (id)initWithSortDescriptor:(NSSortDescriptor *)_descriptor { SEL sel; if (_descriptor == nil) { [self release]; return nil; } sel = [_descriptor selector]; if (sel_isEqual(sel, @selector(compare:))) { sel = [_descriptor ascending] ? EOCompareAscending : EOCompareDescending; } else if (sel_isEqual(sel, @selector(caseInsensitiveCompare:))) { sel = [_descriptor ascending] ? EOCompareCaseInsensitiveAscending : EOCompareCaseInsensitiveDescending; } else { if (![_descriptor ascending]) { NSLog(@"WARNING(%s): cannot representing descending selector in " @"NSSortDescriptor: %@", __PRETTY_FUNCTION__, _descriptor); } } return [self initWithKey:[_descriptor key] selector:sel]; } - (BOOL)isAscendingEOSortSelector:(SEL)_sel { if (sel_isEqual(_sel, EOCompareDescending)) return NO; if (sel_isEqual(_sel, EOCompareCaseInsensitiveAscending)) return NO; return YES; } - (SEL)cdSortSelectorFromEOSortSelector:(SEL)_sel { if (sel_isEqual(_sel, EOCompareAscending)) return @selector(compare:); if (sel_isEqual(_sel, EOCompareDescending)) return @selector(compare:); if (sel_isEqual(_sel, EOCompareCaseInsensitiveAscending)) return @selector(caseInsensitiveCompare:); if (sel_isEqual(_sel, EOCompareCaseInsensitiveDescending)) return @selector(caseInsensitiveCompare:); return _sel; } - (NSSortDescriptor *)asSortDescriptor { SEL sel; sel = [self selector]; return [[[NSSortDescriptor alloc] initWithKey:[self key] ascending:[self isAscendingEOSortSelector:sel] selector:[self cdSortSelectorFromEOSortSelector:sel]] autorelease]; } @end /* EOSortOrdering(CoreData) */ @implementation NSSortDescriptor(EOCoreData) - (NSSortDescriptor *)asSortDescriptor { return self; } @end /* NSSortDescriptor(EOCoreData) */ SOPE/sope-core/EOCoreData/GNUmakefile0000644000000000000000000000344015004363604016200 0ustar rootroot# GNUstep makefile include ../../config.make include ../common.make ifneq ($(frameworks),yes) LIBRARY_NAME = libEOCoreData else FRAMEWORK_NAME = EOCoreData endif libEOCoreData_PCH_FILE = common.h libEOCoreData_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION) libEOCoreData_INSTALL_DIR=$(SOPE_SYSLIBDIR) libEOCoreData_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION) libEOCoreData_HEADER_FILES_DIR = . libEOCoreData_HEADER_FILES_INSTALL_DIR = /EOCoreData # headers libEOCoreData_HEADER_FILES += \ EOCoreData.h \ EOCoreDataSource.h \ \ EOFetchSpecification+CoreData.h \ EOQualifier+CoreData.h \ EOSortOrdering+CoreData.h \ libEOCoreData_HEADER_FILES += \ NSExpression+EO.h \ NSPredicate+EO.h \ NSEntityDescription+EO.h \ NSAttributeDescription+EO.h \ NSRelationshipDescription+EO.h \ # implementations libEOCoreData_OBJC_FILES += \ EOCoreDataSource.m \ \ EOFetchSpecification+CoreData.m \ EOQualifier+CoreData.m \ EOSortOrdering+CoreData.m \ EOKeyValueQualifier+CoreData.m \ EOKeyComparisonQualifier+CoreData.m \ EOCompoundQualifiers.m \ libEOCoreData_OBJC_FILES += \ NSExpression+EO.m \ NSPredicate+EO.m \ NSEntityDescription+EO.m \ NSAttributeDescription+EO.m \ NSRelationshipDescription+EO.m \ NSManagedObject+KVC.m \ libEOCoreData_OBJC_FILES += \ NSString+CoreData.m # framework support EOCoreData_PCH_FILE = $(libEOCoreData_PCH_FILE) EOCoreData_HEADER_FILES = $(libEOCoreData_HEADER_FILES) EOCoreData_OBJC_FILES = $(libEOCoreData_OBJC_FILES) # building -include GNUmakefile.preamble ifneq ($(FHS_INSTALL_ROOT),) GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include endif ifneq ($(frameworks),yes) include $(GNUSTEP_MAKEFILES)/library.make else include $(GNUSTEP_MAKEFILES)/framework.make endif -include GNUmakefile.postamble SOPE/sope-core/EOCoreData/NSEntityDescription+EO.h0000644000000000000000000000304015004363604020513 0ustar rootroot/* Copyright (C) 2005-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NSEntityDescription_EO_H__ #define __NSEntityDescription_EO_H__ // the next two are here to please the Leopard #import @class NSData; #import /* NSEntityDescription(EO) Make an NSEntityDescription behave like an EOEntity. This is mostly to make the CoreData model objects work with DirectToWeb and EO at the same time. */ @class NSString, NSArray; @interface NSEntityDescription(EO) - (id)relationshipNamed:(NSString *)_name; - (id)attributeNamed:(NSString *)_name; - (NSArray *)relationships; - (NSArray *)attributes; - (BOOL)isReadOnly; - (NSArray *)classPropertyNames; - (NSArray *)primaryKeyAttributeNames; @end #endif /* __NSEntityDescription_EO_H__ */ SOPE/sope-core/EOCoreData/EOSortOrdering+CoreData.h0000644000000000000000000000252515004363604020625 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOSortOrdering_CoreData_H__ #define __EOSortOrdering_CoreData_H__ #include /* EOSortOrdering(CoreData) Convert an libEOControl EOSortOrdering to a CoreData compliant NSSortDescriptor object. */ @class NSSortDescriptor; @interface EOSortOrdering(CoreData) - (id)initWithSortDescriptor:(NSSortDescriptor *)_descriptor; - (NSSortDescriptor *)asSortDescriptor; /* converting selectors */ - (BOOL)isAscendingEOSortSelector:(SEL)_sel; - (SEL)cdSortSelectorFromEOSortSelector:(SEL)_sel; @end #endif /* __EOSortOrdering_CoreData_H__ */ SOPE/sope-core/EOCoreData/NSExpression+EO.h0000644000000000000000000000220715004363604017176 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NSExpression_EO_H__ #define __NSExpression_EO_H__ #import /* NSExpression(EO) Convert an NSExpression to an EOQualifier. */ @class NSExpression; @class EOQualifier; @interface NSExpression(EOCoreData) < EOKeyValueArchiving > - (NSPredicate *)asPredicate; - (NSExpression *)asExpression; @end #endif /* __NSExpression_EO_H__ */ SOPE/sope-core/EOCoreData/ChangeLog0000644000000000000000000000457515004363604015712 0ustar rootroot2007-12-03 Helge Hess * fixed Leopard compilation issues (v4.5.12) 2005-10-03 Helge Hess * v4.5.11 * EOFetchSpecification+CoreData.m: only transfer limit to NSFetchRequest if its != 0 * EOCompoundQualifiers.m: added support for qualifier=>predicate conversion * improved qualifier=>predicate conversion support (v4.5.10) 2005-08-23 Helge Hess * v4.5.9 * added NSString+CoreData.m: for string related CD methods * EOCoreDataSource.m: added 'EOCoreDataSourceDebugEnabled' default to enable debugging 2005-08-06 Marcus Mueller * EOCoreData-Info.plist: new Xcode Info.plist file * EOCoreData.xcodeproj: new Xcode 2.1 project * README.txt: fixed a typo 2005-08-06 Helge Hess * v4.5.8 * NSEntityDescription+EO.m: added -isReadOnly, -classPropertyNames, -primaryKeyAttributeNames, -relationships, -attributes * added NSAttributeDescription+EO category containing the -width and -allowsNull methods * added NSRelationshipDescription+EO category containing the -sourceAttributes method 2005-08-04 Helge Hess * EOCoreDataSource.m: print a warning if no object-context was decoded from an archive, improved decoding of 'isFetchEnabled' (set to yes in case no value was set) (v4.5.7) * NSEntityDescription+EO.m: added EO compatible attribute/relship lookup methods (v4.5.6) 2005-08-04 Helge Hess * NSPredicate+EO.m: also check 'selectorName' key during unarchiving (v4.5.5) 2005-08-04 Helge Hess * NSExpression+EO.m: added EOKeyValueArchiving (v4.5.4) * NSPredicate+EO.m: added EOKeyValueArchiving to NSComparisonPredicate (v4.5.3) 2005-08-03 Helge Hess * v4.5.2 * EOFetchSpecification+CoreData.m: implemented -initWithFetchRequest: * EOCoreDataSource.m: added key/value archiving, added ability to retrieve the entity from the fetch specification, added support for qualifier bindings (v4.5.2) * EOSortOrdering+CoreData.m: implemented conversion methods * EOQualifier+CoreData.m: implemented conversion methods * moved NS* categories to own files * v4.5.1 * moved in implementation prototypes from CoreDataBlog * started EOCoreData library SOPE/sope-core/EOCoreData/common.h0000644000000000000000000000343515004363604015573 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOCoreData_COMMON_H__ #define __EOCoreData_COMMON_H__ #import #import #include #import #import #import #import #import #ifndef ASSIGN # define ASSIGN(object, value) \ ({id __object = (id)object; \ id __value = (id)value; \ if (__value != __object) { if (__value) [__value retain]; \ if (__object) [__object release]; \ object = __value;}}) #endif #ifndef ASSIGNCOPY # define ASSIGNCOPY(object, value) \ ({id __object = (id)object; \ id __value = (id)value; \ if (__value != __object) { if (__value) __value = [__value copy]; \ if (__object) [__object release]; \ object = __value;}}) #endif #if GNU_RUNTIME # include #endif #endif /* __EOCoreData_COMMON_H__ */ SOPE/sope-core/EOCoreData/EOFetchSpecification+CoreData.m0000644000000000000000000000712215004363604021741 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOFetchSpecification+CoreData.h" #include "EOSortOrdering+CoreData.h" #include "EOQualifier+CoreData.h" #include "common.h" @implementation EOFetchSpecification(CoreData) - (id)initWithFetchRequest:(NSFetchRequest *)_fr { NSMutableArray *so; EOQualifier *q; NSArray *sd; unsigned count; if (_fr == nil) { [self release]; return nil; } /* convert sort descriptors */ sd = [_fr sortDescriptors]; so = nil; if ((count = [sd count]) > 0) { unsigned i; so = [[NSMutableArray alloc] initWithCapacity:count]; for (i = 0; i < count; i++) { EOSortOrdering *soo; soo = [[EOSortOrdering alloc] initWithSortDescriptor: [sd objectAtIndex:i]]; if (soo == nil) { soo = [sd objectAtIndex:i]; /* oh well, this is sneaky */ NSLog(@"WARNING(%s): could not convert NSSortDescriptor to " @"EOSortOrdering: %@", __PRETTY_FUNCTION__, soo); } [so addObject:soo]; [soo release]; } } /* convert predicate */ q = [EOQualifier qualifierForPredicate:[_fr predicate]]; /* create object */ // TODO: maybe add 'affectedStores' as a hint? self = [self initWithEntityName:[[_fr entity] name] qualifier:q sortOrderings:so usesDistinct:YES isDeep:NO hints:nil]; [so release]; so = nil; [self setFetchLimit:[_fr fetchLimit]]; return self; } - (NSArray *)sortOrderingsAsSortDescriptors { NSMutableArray *ma; NSArray *a; unsigned i, count; if ((a = [self sortOrderings]) == nil) return nil; if ((count = [a count]) == 0) return nil; if (count == 1) /* common, optimization */ return [NSArray arrayWithObject:[[a objectAtIndex:0] asSortDescriptor]]; ma = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) [ma addObject:[[a objectAtIndex:i] asSortDescriptor]]; return ma; } - (NSFetchRequest *)fetchRequestWithEntity:(NSEntityDescription *)_entity { NSFetchRequest *fr; unsigned int limit; fr = [[[NSFetchRequest alloc] init] autorelease]; [fr setEntity:_entity]; if ((limit = [self fetchLimit]) > 0) [fr setFetchLimit:limit]; [fr setPredicate:[[self qualifier] asPredicate]]; [fr setSortDescriptors:[self sortOrderingsAsSortDescriptors]]; return fr; } - (NSFetchRequest *)fetchRequestWithModel:(NSManagedObjectModel *)_model { NSEntityDescription *entity; NSString *s; entity = ((s = [self entityName]) != nil) ? [[_model entitiesByName] objectForKey:s] : nil; return [self fetchRequestWithEntity:entity]; } @end /* EOFetchSpecification(CoreData) */ @implementation NSFetchRequest(EOCoreData) - (NSFetchRequest *)fetchRequestWithEntity:(NSEntityDescription *)_entity { return self; } - (NSFetchRequest *)fetchRequestWithModel:(NSManagedObjectModel *)_model { return self; } @end /* NSFetchRequest(EOCoreData) */ SOPE/sope-core/EOCoreData/NSEntityDescription+EO.m0000644000000000000000000000276115004363604020531 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSEntityDescription+EO.h" #include "common.h" @implementation NSEntityDescription(EO) - (id)relationshipNamed:(NSString *)_qname { return [[self relationshipsByName] objectForKey:_qname]; } - (id)attributeNamed:(NSString *)_qname { return [[self attributesByName] objectForKey:_qname]; } - (BOOL)isReadOnly { return NO; /* always read/write, no? */ } - (NSArray *)classPropertyNames { return [[self propertiesByName] allKeys]; } - (NSArray *)primaryKeyAttributeNames { /* such are transparent with CoreData */ return nil; } - (NSArray *)attributes { return [[self attributesByName] allValues]; } - (NSArray *)relationships { return [[self relationshipsByName] allValues]; } @end /* NSEntityDescription(EO) */ SOPE/sope-core/EOCoreData/NSExpression+EO.m0000644000000000000000000000517015004363604017205 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #include "common.h" @implementation NSExpression(EOCoreData) - (NSPredicate *)asPredicate { return nil; } - (NSExpression *)asExpression { return self; } /* key/value archiving */ - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { id tmp; [self release]; self = nil; if ((tmp = [_unarchiver decodeObjectForKey:@"constantValue"]) != nil) return [[NSExpression expressionForConstantValue:tmp] retain]; if ((tmp = [_unarchiver decodeObjectForKey:@"keyPath"]) != nil) return [[NSExpression expressionForKeyPath:tmp] retain]; if ((tmp = [_unarchiver decodeObjectForKey:@"variable"]) != nil) return [[NSExpression expressionForVariable:tmp] retain]; if ((tmp = [_unarchiver decodeObjectForKey:@"function"]) != nil) { NSArray *args; args = [_unarchiver decodeObjectForKey:@"arguments"]; return [[NSExpression expressionForFunction:tmp arguments:args] retain]; } return [[NSExpression expressionForEvaluatedObject] retain]; } - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver { switch ([self expressionType]) { case NSConstantValueExpressionType: [_archiver encodeObject:[self constantValue] forKey:@"constantValue"]; return; case NSEvaluatedObjectExpressionType: /* encode no marker */ return; case NSVariableExpressionType: [_archiver encodeObject:[self variable] forKey:@"variable"]; return; case NSKeyPathExpressionType: [_archiver encodeObject:[self keyPath] forKey:@"keyPath"]; return; case NSFunctionExpressionType: [_archiver encodeObject:[self function] forKey:@"function"]; [_archiver encodeObject:[self arguments] forKey:@"arguments"]; return; default: NSLog(@"WARNING(%s): could not encode NSExpression: %@!", __PRETTY_FUNCTION__, self); } } @end /* NSPredicate(EOCoreData) */ SOPE/sope-core/EOCoreData/EOCoreDataSource.h0000644000000000000000000000472315004363604017373 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOCoreDataSource_H__ #define __EOCoreDataSource_H__ #include /* EOCoreDataSource This wraps a NSManagedObjectContext in an EODataSource. It corresponds to the EODatabaseDataSource available in EOF. Note: if you use -setFetchRequest: all the EO related methods will be reset! */ @class NSArray, NSDictionary; @class NSManagedObjectContext, NSEntityDescription, NSFetchRequest; @class EOQualifier, EOFetchSpecification; @interface EOCoreDataSource : EODataSource { NSManagedObjectContext *managedObjectContext; NSEntityDescription *entity; EOFetchSpecification *fetchSpecification; EOQualifier *auxiliaryQualifier; NSDictionary *qualifierBindings; NSFetchRequest *fetchRequest; struct { int isFetchEnabled:1; int isEntityFromFetchSpec:1; int reserved:30; } ecdFlags; } - (id)initWithManagedObjectContext:(NSManagedObjectContext *)_moc entity:(NSEntityDescription *)_entity; /* fetch-spec */ - (void)setFetchSpecification:(EOFetchSpecification *)_fspec; - (EOFetchSpecification *)fetchSpecification; - (EOFetchSpecification *)fetchSpecificationForFetch; - (void)setAuxiliaryQualifier:(EOQualifier *)_qualifier; - (EOQualifier *)auxiliaryQualifier; - (void)setIsFetchEnabled:(BOOL)_flag; - (BOOL)isFetchEnabled; - (NSArray *)qualifierBindingKeys; - (void)setQualifierBindings:(NSDictionary *)_bindings; - (NSDictionary *)qualifierBindings; /* directly access a CoreData fetch request */ - (void)setFetchRequest:(NSFetchRequest *)_fr; - (NSFetchRequest *)fetchRequest; /* accessors */ - (NSEntityDescription *)entity; - (NSManagedObjectContext *)managedObjectContext; @end #endif /* __EOCoreDataSource_H__ */ SOPE/sope-core/EOCoreData/NSPredicate+EO.m0000644000000000000000000002172715004363604016754 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSPredicate+EO.h" #include "EOQualifier+CoreData.h" #include "common.h" @implementation NSPredicate(EOCoreData) - (NSPredicate *)asPredicate { return self; } - (NSExpression *)asExpression { return nil; } @end /* NSPredicate(EOCoreData) */ @implementation NSCompoundPredicate(EOCoreData) - (EOQualifier *)asQualifier { /* Compound predicates join other predicates, they do not deal with expressions. */ NSMutableArray *sq; NSArray *sp; unsigned i, count; Class clazz; BOOL isNot = NO; EOQualifier *q; sp = [self subpredicates]; count = [sp count]; switch ([self compoundPredicateType]) { case NSNotPredicateType: isNot = YES; clazz = [EONotQualifier class]; break; case NSAndPredicateType: clazz = [EOAndQualifier class]; break; case NSOrPredicateType: clazz = [EOOrQualifier class]; break; default: NSLog(@"ERROR(%s): unknown compound predicate type: %@", __PRETTY_FUNCTION__, self); return nil; } if (count == 0) return [[[clazz alloc] init] autorelease]; if (count == 1) { q = [sp objectAtIndex:0]; return (isNot) ? [[[EONotQualifier alloc] initWithQualifier:q] autorelease] : q; } sq = [[NSMutableArray alloc] initWithCapacity:count]; for (i = 0; i < count; i++) { q = [EOQualifier qualifierForPredicate:[sp objectAtIndex:i]]; if (q == nil) { q = [sp objectAtIndex:i]; NSLog(@"ERROR(%s): could not convert predicate to qualifier: %@", __PRETTY_FUNCTION__, q); } if (isNot) q = [[EONotQualifier alloc] initWithQualifier:q]; [sq addObject:q]; if (isNot) [q release]; q = nil; } q = [[(isNot ? [EOAndQualifier class] : clazz) alloc] initWithQualifier:q]; [sq release]; return [q autorelease]; } @end /* NSCompoundPredicate(EOCoreData) */ @implementation NSComparisonPredicate(EOCoreData) - (EOQualifier *)asQualifier { NSExpression *lhs, *rhs; lhs = [self leftExpression]; rhs = [self rightExpression]; // TODO: need to check predicate modifiers // TODO: add support for variables if ([rhs expressionType] == NSKeyPathExpressionType) { if ([lhs expressionType] == NSConstantValueExpressionType) return [EOKeyValueQualifier qualifierForComparisonPredicate:self]; if ([lhs expressionType] == NSKeyPathExpressionType) return [EOKeyComparisonQualifier qualifierForComparisonPredicate:self]; } NSLog(@"ERROR(%s): cannot map NSComparisonPredicate to EOQualifier: %@", __PRETTY_FUNCTION__, self); return (id)self; } /* key/value archiving */ - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { int opt; NSPredicateOperatorType ptype; NSComparisonPredicateModifier mod; NSExpression *left, *right; NSString *selName, *s; /* left / right - TODO: need to check 'official' keys fo rthat */ left = [_unarchiver decodeObjectForKey:@"left"]; if (left != nil && ![left isKindOfClass:[NSExpression class]]) left = [NSExpression expressionForConstantValue:left]; right = [_unarchiver decodeObjectForKey:@"right"]; if (right != nil && ![right isKindOfClass:[NSExpression class]]) right = [NSExpression expressionForConstantValue:right]; /* custom selector */ if ((selName = [_unarchiver decodeObjectForKey:@"selectorName"]) != nil) { if (![selName hasSuffix:@":"]) selName = [selName stringByAppendingString:@":"]; } else selName = [_unarchiver decodeObjectForKey:@"selector"]; if ([selName length] > 0) { return [self initWithLeftExpression:left rightExpression:right customSelector:selName ? NSSelectorFromString(selName):NULL]; } /* modifier */ if ((s = [_unarchiver decodeObjectForKey:@"modifier"]) != nil) { if ([s isEqualToString:@"direct"]) mod = NSDirectPredicateModifier; else if ([s isEqualToString:@"all"]) mod = NSAllPredicateModifier; else if ([s isEqualToString:@"any"]) mod = NSAnyPredicateModifier; else { NSLog(@"WARNING(%s): could not decode modifier (trying int): %@!", __PRETTY_FUNCTION__, s); mod = [s intValue]; } } else mod = NSDirectPredicateModifier; /* type */ if ((s = [_unarchiver decodeObjectForKey:@"type"]) != nil) { if ([s isEqualToString:@"<"]) ptype = NSLessThanPredicateOperatorType; else if ([s isEqualToString:@"=<"]) ptype = NSLessThanOrEqualToPredicateOperatorType; else if ([s isEqualToString:@">"]) ptype = NSGreaterThanPredicateOperatorType; else if ([s isEqualToString:@">="]) ptype = NSGreaterThanOrEqualToPredicateOperatorType; else if ([s isEqualToString:@"=="]) ptype = NSEqualToPredicateOperatorType; else if ([s isEqualToString:@"!="]) ptype = NSNotEqualToPredicateOperatorType; else if ([s isEqualToString:@"like"]) ptype = NSLikePredicateOperatorType; else if ([s isEqualToString:@"contains"]) ptype = NSInPredicateOperatorType; else if ([s isEqualToString:@"beginswith"]) ptype = NSBeginsWithPredicateOperatorType; else if ([s isEqualToString:@"endswith"]) ptype = NSEndsWithPredicateOperatorType; else if ([s isEqualToString:@"matches"]) ptype = NSMatchesPredicateOperatorType; else { NSLog(@"WARNING(%s): could not decode type (trying int): %@!", __PRETTY_FUNCTION__, s); ptype = [s intValue]; } } else ptype = NSEqualToPredicateOperatorType; /* options */ // TODO: use bit-compare and a set? if ((s = [_unarchiver decodeObjectForKey:@"options"]) != nil) { if ([s isEqualToString:@"caseInsensitive"]) opt = NSCaseInsensitivePredicateOption; else if ([s isEqualToString:@"diacritic"]) opt = NSDiacriticInsensitivePredicateOption; else { NSLog(@"WARNING(%s): could not decode options (trying int): %@!", __PRETTY_FUNCTION__, s); opt = [s intValue]; } } else opt = 0; /* create and return */ return [self initWithLeftExpression:left rightExpression:right modifier:mod type:ptype options:opt]; } - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver { NSString *s; [_archiver encodeObject:[self leftExpression] forKey:@"left"]; [_archiver encodeObject:[self rightExpression] forKey:@"right"]; /* type */ switch ([self predicateOperatorType]) { case NSCustomSelectorPredicateOperatorType: [_archiver encodeObject:NSStringFromSelector([self customSelector]) forKey:@"selector"]; return; /* no more info */ case NSLessThanPredicateOperatorType: s = @"<"; break; case NSLessThanOrEqualToPredicateOperatorType: s = @"=<"; break; case NSGreaterThanPredicateOperatorType: s = @">"; break; case NSGreaterThanOrEqualToPredicateOperatorType: s = @">="; break; case NSEqualToPredicateOperatorType: s = @"=="; break; case NSNotEqualToPredicateOperatorType: s = @"!="; break; case NSLikePredicateOperatorType: s = @"like"; break; case NSInPredicateOperatorType: s = @"contains"; break; case NSBeginsWithPredicateOperatorType: s = @"beginswith"; break; case NSEndsWithPredicateOperatorType: s = @"endswith"; break; case NSMatchesPredicateOperatorType: s = @"matches"; break; default: s = [NSString stringWithFormat:@"%i", [self predicateOperatorType]]; break; } if (s != nil) [_archiver encodeObject:s forKey:@"type"]; /* modifier */ switch ([self comparisonPredicateModifier]) { case NSDirectPredicateModifier: s = nil; break; case NSAllPredicateModifier: s = @"all"; break; case NSAnyPredicateModifier: s = @"any"; break; default: s = [NSString stringWithFormat:@"%i", [self comparisonPredicateModifier]]; break; } if (s != nil) [_archiver encodeObject:s forKey:@"modifier"]; /* options */ // TODO: use bit-compare and a set? if ([self options] == NSCaseInsensitivePredicateOption) [_archiver encodeObject:@"caseInsensitive" forKey:@"options"]; else if ([self options] == NSDiacriticInsensitivePredicateOption) [_archiver encodeObject:@"diacritic" forKey:@"options"]; } @end /* NSComparisonPredicate(EOCoreData) */ SOPE/sope-core/EOCoreData/COPYING0000644000000000000000000006130315004363604015163 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-core/EOCoreData/fhs.make0000644000000000000000000000160515004363604015546 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) FHS_INCLUDE_DIR=$(FHS_INSTALL_ROOT)/include/ FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib/ FHS_BIN_DIR=$(FHS_INSTALL_ROOT)/bin/ fhs-header-dirs :: $(MKDIRS) $(FHS_INCLUDE_DIR)$(libEOCoreData_HEADER_FILES_INSTALL_DIR) move-headers-to-fhs :: fhs-header-dirs @echo "moving headers to $(FHS_INCLUDE_DIR) .." mv -f $(GNUSTEP_HEADERS)$(libEOCoreData_HEADER_FILES_INSTALL_DIR)/*.h \ $(FHS_INCLUDE_DIR)$(libEOCoreData_HEADER_FILES_INSTALL_DIR)/ NONFHS_LIBDIR="$(GNUSTEP_LIBRARIES)/$(GNUSTEP_TARGET_LDIR)/" NONFHS_LIBNAME="$(LIBRARY_NAME)$(LIBRARY_NAME_SUFFIX)$(SHARED_LIBEXT)" move-libs-to-fhs :: @echo "moving libs to $(FHS_LIB_DIR) .." mv -f $(NONFHS_LIBDIR)/$(NONFHS_LIBNAME)* $(FHS_LIB_DIR)/ move-to-fhs :: move-headers-to-fhs move-libs-to-fhs after-install :: move-to-fhs endif SOPE/sope-core/EOCoreData/EOQualifier+CoreData.h0000644000000000000000000000544015004363604020124 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOQualifier_CoreData_H__ #define __EOQualifier_CoreData_H__ #import #import #include /* EOQualifier(CoreData) Convert an libEOControl EOQualifier to a CoreData compliant NSPredicate object. */ @class NSArray; @class NSPredicate, NSExpression, NSComparisonPredicate, NSCompoundPredicate; @interface EOQualifier(CoreData) + (EOQualifier *)qualifierForPredicate:(NSPredicate *)_predicate; - (NSPredicate *)asPredicate; - (NSExpression *)asExpression; /* support methods */ + (SEL)eoSelectorForForComparisonPredicate:(NSComparisonPredicate *)_p; + (NSPredicateOperatorType)predicateOperatorTypeForEOSelector:(SEL)_sel; - (NSPredicate *)predicateWithLeftExpression:(NSExpression *)_lhs rightExpression:(NSExpression *)_rhs eoSelector:(SEL)_selector; /* CoreData compatibility */ + (NSPredicate *)andPredicateWithSubpredicates:(NSArray *)_sub; + (NSPredicate *)orPredicateWithSubpredicates:(NSArray *)_sub; + (NSPredicate *)notPredicateWithSubpredicate:(id)_predicate; @end #import /* compound qualifiers */ @interface EOAndQualifier(CoreData) - (NSCompoundPredicateType)compoundPredicateType; @end @interface EOOrQualifier(CoreData) - (NSCompoundPredicateType)compoundPredicateType; @end @interface EONotQualifier(CoreData) - (NSCompoundPredicateType)compoundPredicateType; @end /* comparison qualifiers */ @interface EOKeyValueQualifier(CoreData) + (EOQualifier *)qualifierForComparisonPredicate:(NSComparisonPredicate *)_p; - (NSComparisonPredicateModifier)comparisonPredicateModifier; - (NSPredicateOperatorType)predicateOperatorType; - (SEL)customSelector; - (unsigned)options; @end @interface EOKeyComparisonQualifier(CoreData) + (EOQualifier *)qualifierForComparisonPredicate:(NSComparisonPredicate *)_p; - (NSComparisonPredicateModifier)comparisonPredicateModifier; - (NSPredicateOperatorType)predicateOperatorType; - (SEL)customSelector; - (unsigned)options; @end #endif /* __EOQualifier_CoreData_H__ */ SOPE/sope-core/EOCoreData/NSRelationshipDescription+EO.m0000644000000000000000000000177715004363604021724 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NSRelationshipDescription+EO.h" #include "common.h" @implementation NSRelationshipDescription(EO) - (NSArray *)sourceAttributes { /* such are transparent with CoreData */ return nil; } @end /* NSRelationshipDescription(EO) */ SOPE/sope-core/EOCoreData/EOCompoundQualifiers.m0000644000000000000000000000354015004363604020342 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOQualifier+CoreData.h" #include "NSPredicate+EO.h" #include "NSExpression+EO.h" #include "common.h" @implementation EOAndQualifier(CoreData) - (NSCompoundPredicateType)compoundPredicateType { return NSAndPredicateType; } - (NSPredicate *)asPredicate { NSArray *tmp; tmp = [self subqualifiers]; tmp = [tmp valueForKey:@"asPredicate"]; return [NSCompoundPredicate andPredicateWithSubpredicates:tmp]; } @end /* EOAndQualifier(CoreData) */ @implementation EOOrQualifier(CoreData) - (NSCompoundPredicateType)compoundPredicateType { return NSOrPredicateType; } - (NSPredicate *)asPredicate { NSArray *tmp; tmp = [self subqualifiers]; tmp = [tmp valueForKey:@"asPredicate"]; return [NSCompoundPredicate orPredicateWithSubpredicates:tmp]; } @end /* EOOrQualifier(CoreData) */ @implementation EONotQualifier(CoreData) - (NSCompoundPredicateType)compoundPredicateType { return NSNotPredicateType; } - (NSPredicate *)asPredicate { return [NSCompoundPredicate notPredicateWithSubpredicate: [[self qualifier] asPredicate]]; } @end /* EONotQualifier(CoreData) */ SOPE/sope-core/EOCoreData/EOKeyValueQualifier+CoreData.m0000644000000000000000000000507215004363604021600 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOQualifier+CoreData.h" #include "NSPredicate+EO.h" #include "NSExpression+EO.h" #include "common.h" @implementation EOKeyValueQualifier(CoreData) + (EOQualifier *)qualifierForComparisonPredicate:(NSComparisonPredicate *)_p { SEL sel; if ((sel = [self eoSelectorForForComparisonPredicate:_p]) == nil) return (EOQualifier *)_p; return [[[self alloc] initWithKey:[[_p leftExpression] keyPath] operatorSelector:sel value:[[_p rightExpression] constantValue]] autorelease]; } - (NSPredicate *)asPredicate { /* EOKeyValueQualifier has a key/value path expression on the left side and a constant value expression on the right side. */ NSExpression *lhs, *rhs; id tmp; tmp = [self key]; lhs = [tmp isKindOfClass:[EOQualifierVariable class]] ? [NSExpression expressionForVariable:[(EOQualifierVariable *)tmp key]] : [NSExpression expressionForKeyPath:tmp]; tmp = [self value]; rhs = [tmp isKindOfClass:[EOQualifierVariable class]] ? [NSExpression expressionForVariable:[(EOQualifierVariable *)tmp key]] : [NSExpression expressionForConstantValue:tmp]; return [self predicateWithLeftExpression:lhs rightExpression:rhs eoSelector:[self selector]]; } /* CoreData compatibility */ - (NSComparisonPredicateModifier)comparisonPredicateModifier { return NSDirectPredicateModifier; } - (NSPredicateOperatorType)predicateOperatorType { return [[self class] predicateOperatorTypeForEOSelector:[self selector]]; } - (unsigned)options { return (sel_isEqual([self selector], EOQualifierOperatorCaseInsensitiveLike)) ? NSCaseInsensitivePredicateOption : 0; } - (SEL)customSelector { return [self predicateOperatorType] == NSCustomSelectorPredicateOperatorType ? [self selector] : nil; } @end /* EOKeyValueQualifier(CoreData) */ SOPE/sope-core/EOCoreData/Version0000644000000000000000000000004515004363604015474 0ustar rootroot# version file SUBMINOR_VERSION:=12 SOPE/sope-core/EOCoreData/EOKeyComparisonQualifier+CoreData.m0000644000000000000000000000465315004363604022642 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOQualifier+CoreData.h" #include "NSPredicate+EO.h" #include "NSExpression+EO.h" #include "common.h" @implementation EOKeyComparisonQualifier(CoreData) + (EOQualifier *)qualifierForComparisonPredicate:(NSComparisonPredicate *)_p { SEL sel; if ((sel = [self eoSelectorForForComparisonPredicate:_p]) == nil) return (EOQualifier *)_p; return [[[self alloc] initWithLeftKey:[[_p leftExpression] keyPath] operatorSelector:sel rightKey:[[_p rightExpression] keyPath]] autorelease]; } - (NSPredicate *)asPredicate { NSExpression *lhs, *rhs; id tmp; tmp = [self leftKey]; lhs = [tmp isKindOfClass:[EOQualifierVariable class]] ? [NSExpression expressionForVariable:[(EOQualifierVariable *)tmp key]] : [NSExpression expressionForKeyPath:tmp]; tmp = [self rightKey]; rhs = [tmp isKindOfClass:[EOQualifierVariable class]] ? [NSExpression expressionForVariable:[(EOQualifierVariable *)tmp key]] : [NSExpression expressionForKeyPath:tmp]; return [self predicateWithLeftExpression:lhs rightExpression:rhs eoSelector:[self selector]]; } /* CoreData compatibility */ - (NSComparisonPredicateModifier)comparisonPredicateModifier { return NSDirectPredicateModifier; } - (NSPredicateOperatorType)predicateOperatorType { return [[self class] predicateOperatorTypeForEOSelector:[self selector]]; } - (unsigned)options { return (sel_isEqual([self selector], EOQualifierOperatorCaseInsensitiveLike)) ? NSCaseInsensitivePredicateOption : 0; } - (SEL)customSelector { return [self predicateOperatorType] == NSCustomSelectorPredicateOperatorType ? [self selector] : nil; } @end /* EOKeyComparisonQualifier(CoreData) */ SOPE/sope-core/EOCoreData/EOCoreDataSource.m0000644000000000000000000002662215004363604017402 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOCoreDataSource.h" #include "EOFetchSpecification+CoreData.h" #include "EOQualifier+CoreData.h" #include "common.h" static NSString *EODataSourceDidChangeNotification = @"EODataSourceDidChangeNotification"; @implementation EOCoreDataSource static BOOL debugOn = NO; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; if ((debugOn = [ud boolForKey:@"EOCoreDataSourceDebugEnabled"])) NSLog(@"EOCoreDataSource: debugging enabled."); } - (id)initWithManagedObjectContext:(NSManagedObjectContext *)_moc entity:(NSEntityDescription *)_entity { if ((self = [super init]) != nil) { if (_moc == nil) { NSLog(@"ERROR(%s): missing object-context parameter!", __PRETTY_FUNCTION__); [self release]; return nil; } self->ecdFlags.isFetchEnabled = 1; self->managedObjectContext = [_moc retain]; self->entity = [_entity retain]; } return self; } - (id)init { return [self initWithManagedObjectContext:nil entity:nil]; } - (void)dealloc { [self->qualifierBindings release]; [self->entity release]; [self->managedObjectContext release]; [self->fetchSpecification release]; [self->auxiliaryQualifier release]; [super dealloc]; } /* post datasource changes */ - (void)postDataSourceChangedNotification { /* reimplemented here to avoid linking against NGExtensions */ static NSNotificationCenter *nc = nil; if (nc == nil) nc = [[NSNotificationCenter defaultCenter] retain]; [nc postNotificationName:EODataSourceDidChangeNotification object:self]; } /* fetch-spec */ - (void)_resetFetchRequest { [self->fetchRequest release]; self->fetchRequest = nil; } - (void)setFetchSpecification:(EOFetchSpecification *)_fspec { BOOL isSameEntity; if ([self->fetchSpecification isEqual:_fspec]) return; if ([_fspec isKindOfClass:[NSFetchRequest class]]) { /* be tolerant, we ain't no Java ... */ [self setFetchRequest:(NSFetchRequest *)_fspec]; return; } isSameEntity = [[self->fetchSpecification entityName] isEqual:[_fspec entityName]]; [self->fetchSpecification autorelease]; self->fetchSpecification = [_fspec copy]; /* reset derived entities */ if (self->ecdFlags.isEntityFromFetchSpec && !isSameEntity) { self->ecdFlags.isEntityFromFetchSpec = 0; } [self _resetFetchRequest]; [self postDataSourceChangedNotification]; } - (EOFetchSpecification *)fetchSpecification { return self->fetchSpecification; } - (EOFetchSpecification *)fetchSpecificationForFetch { EOFetchSpecification *fs; EOQualifier *aq; NSDictionary *bindings; fs = [[[self fetchSpecification] copy] autorelease]; /* add auxiliary-qualifier */ if ((aq = [self auxiliaryQualifier]) != nil) { EOQualifier *q; if ((q = [fs qualifier]) != nil) { q = [[EOAndQualifier alloc] initWithQualifiers:q, aq, nil]; [fs setQualifier:q]; [q release]; q = nil; } else [fs setQualifier:aq]; } /* apply bindings */ if ((bindings = [self qualifierBindings]) != nil ) { EOQualifier *q; if ((q = [fs qualifier]) != nil) { q = [q qualifierWithBindings:[self qualifierBindings] requiresAllVariables:YES]; [fs setQualifier:q]; } } /* finished */ return fs; } - (void)setAuxiliaryQualifier:(EOQualifier *)_qualifier { if ([_qualifier isKindOfClass:[NSPredicate class]]) /* be tolerant */ _qualifier = [EOQualifier qualifierForPredicate:(NSPredicate *)_qualifier]; if ([self->auxiliaryQualifier isEqual:_qualifier]) return; ASSIGNCOPY(self->auxiliaryQualifier, _qualifier); [self _resetFetchRequest]; [self postDataSourceChangedNotification]; } - (EOQualifier *)auxiliaryQualifier { return self->auxiliaryQualifier; } - (NSArray *)qualifierBindingKeys { NSMutableSet *join; NSArray *b, *ab; b = [[[self fetchSpecification] qualifier] bindingKeys]; ab = [[self auxiliaryQualifier] bindingKeys]; if (ab == nil) return b; if (b == nil) return ab; join = [[NSMutableSet alloc] initWithCapacity:16]; [join addObjectsFromArray:b]; [join addObjectsFromArray:ab]; b = [join allObjects]; [join release]; return b; } - (void)setQualifierBindings:(NSDictionary *)_bindings { ASSIGN(self->qualifierBindings, _bindings); [self _resetFetchRequest]; [self postDataSourceChangedNotification]; } - (NSDictionary *)qualifierBindings { return self->qualifierBindings; } - (void)setIsFetchEnabled:(BOOL)_flag { int f; f = _flag ? 1 : 0; if (self->ecdFlags.isFetchEnabled == f) return; self->ecdFlags.isFetchEnabled = f; [self postDataSourceChangedNotification]; } - (BOOL)isFetchEnabled { return self->ecdFlags.isFetchEnabled ? YES : NO; } /* directly access a CoreData fetch request */ - (void)setFetchRequest:(NSFetchRequest *)_fr { if (_fr == self->fetchRequest) return; /* reset EO objects */ [self->fetchSpecification release]; self->fetchSpecification = nil; [self->auxiliaryQualifier release]; self->auxiliaryQualifier = nil; [self->qualifierBindings release]; self->qualifierBindings = nil; /* use entity of fetch-request */ if ([_fr entity] != nil) { ASSIGN(self->entity, [_fr entity]); self->ecdFlags.isEntityFromFetchSpec = 1; } ASSIGN(self->fetchRequest, _fr); } - (NSFetchRequest *)fetchRequest { return self->fetchRequest; } /* accessors */ - (NSEntityDescription *)entity { if (self->entity == nil && !self->ecdFlags.isEntityFromFetchSpec) { NSManagedObjectContext *moc; NSString *n; self->ecdFlags.isEntityFromFetchSpec = 1; /* also used for caching fails */ moc = [self managedObjectContext]; n = [[self fetchSpecification] entityName]; if (moc != nil && n != nil) { self->entity = [[NSEntityDescription entityForName:n inManagedObjectContext:moc] retain]; } } return self->entity; } - (NSManagedObjectContext *)managedObjectContext { return self->managedObjectContext; } /* fetching */ - (NSArray *)fetchObjects { EOFetchSpecification *fs; NSError *error = nil; NSArray *results; if (debugOn) NSLog(@"fetchObjects"); if (![self isFetchEnabled]) return [NSArray array]; // TODO: print a warning on entity mismatch? if (self->fetchRequest == nil) { fs = [self fetchSpecificationForFetch]; self->fetchRequest = [[fs fetchRequestWithEntity:[self entity]] retain]; } if (debugOn) NSLog(@" request: %@", self->fetchRequest); results = [[self managedObjectContext] executeFetchRequest:self->fetchRequest error:&error]; if (results == nil) { // TODO: improve (-lastException on the datasource or return the error?) NSLog(@"ERROR(%s): datasource failed to fetch: %@", __PRETTY_FUNCTION__, error); return nil; } if (debugOn) NSLog(@"=> got %d records.", [results count]); // TODO: add grouping support? return results; } /* operations */ - (void)deleteObject:(id)_object { [[self managedObjectContext] deleteObject:_object]; [self postDataSourceChangedNotification]; } - (void)insertObject:(id)_object { [[self managedObjectContext] insertObject:_object]; [self postDataSourceChangedNotification]; } - (id)createObject { Class clazz; id newObject; clazz = NSClassFromString([[self entity] managedObjectClassName]); newObject = [[clazz alloc] initWithEntity:[self entity] insertIntoManagedObjectContext: [self managedObjectContext]]; return [newObject autorelease]; } /* class description */ - (EOClassDescription *)classDescriptionForObjects { // TODO: should we create an EOClassDescription or just add // EOClassDescription description stuff to NSEntityDescription? return (id)[self entity]; } /* archiving */ - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { id lEntity, fs, ec, tmp; /* fetch object context */ ec = [_unarchiver decodeObjectReferenceForKey:@"managedObjectContext"]; if (ec == nil) ec = [_unarchiver decodeObjectReferenceForKey:@"editingContext"]; if (ec != nil && ![ec isKindOfClass:[NSManagedObjectContext class]]) { NSLog(@"WARNING(%s): decode object context is of unexpected class: %@", __PRETTY_FUNCTION__, ec); } if (ec == nil) { NSLog(@"WARNING(%s): decoded no object context from archive!", __PRETTY_FUNCTION__); } /* fetch fetch specification */ fs = [_unarchiver decodeObjectForKey:@"fetchRequest"]; if (fs == nil) fs = [_unarchiver decodeObjectForKey:@"fetchSpecification"]; if (fs != nil && [fs isKindOfClass:[NSFetchRequest class]]) fs = [[[EOFetchSpecification alloc] initWithFetchRequest:fs] autorelease]; /* setup entity */ lEntity = [_unarchiver decodeObjectForKey:@"entity"]; if (lEntity == nil && fs != nil) { /* try to determine entity from fetch-spec */ lEntity = [(EOFetchSpecification *)fs entityName]; } if ([lEntity isKindOfClass:[NSString class]] && ec != nil) { lEntity = [NSEntityDescription entityForName:lEntity inManagedObjectContext:ec]; } /* create object */ if ((self = [self initWithManagedObjectContext:ec entity:lEntity]) == nil) return nil; /* add non-initializer settings */ [self setFetchSpecification:fs]; [self setAuxiliaryQualifier: [_unarchiver decodeObjectForKey:@"auxiliaryQualifier"]]; [self setQualifierBindings: [_unarchiver decodeObjectForKey:@"qualifierBindings"]]; if ((tmp = [_unarchiver decodeObjectForKey:@"isFetchEnabled"]) != nil) [self setIsFetchEnabled:[tmp boolValue]]; return self; } - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver { // TODO: do we need to produce the reference on our own? [_archiver encodeReferenceToObject:[self managedObjectContext] forKey:@"managedObjectContext"]; [_archiver encodeObject:[self fetchSpecification] forKey:@"fetchSpecification"]; [_archiver encodeObject:[self entity] forKey:@"entity"]; [_archiver encodeObject:[self auxiliaryQualifier] forKey:@"auxiliaryQualifier"]; [_archiver encodeObject:[self qualifierBindings] forKey:@"qualifierBindings"]; [_archiver encodeBool:[self isFetchEnabled] forKey:@"isFetchEnabled"]; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:64]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if (self->fetchSpecification != nil) [ms appendFormat:@" fs=%@", self->fetchSpecification]; if (self->auxiliaryQualifier != nil) [ms appendFormat:@" aux=%@", self->auxiliaryQualifier]; if (self->entity != nil) [ms appendFormat:@" entity=%@", [self->entity name]]; [ms appendString:@">"]; return ms; } @end /* EOCoreDataSource */ SOPE/sope-core/EOCoreData/NSManagedObject+KVC.m0000644000000000000000000000212615004363604017647 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import // Note: just including NSManagedObject is a nogo #include "common.h" @implementation NSManagedObject(KVC) - (void)takeValue:(id)_value forKey:(NSString *)_key { /* Yes, I know, deprecated. But hey, don't do this to us! */ [self setValue:_value forKey:_key]; } @end /* NSManagedObject(KVC) */ SOPE/sope-core/EOCoreData/NSAttributeDescription+EO.h0000644000000000000000000000254315004363604021211 0ustar rootroot/* Copyright (C) 2005-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NSAttributeDescription_EO_H__ #define __NSAttributeDescription_EO_H__ // the next two are here to please the Leopard #import @class NSData; #import /* NSAttributeDescription(EO) Make an NSAttributeDescription behave like an EOAttribute. This is mostly to make the CoreData model objects work with DirectToWeb and EO at the same time. */ @interface NSAttributeDescription(EO) - (unsigned)width; - (BOOL)allowsNull; @end #endif /* __NSAttributeDescription_EO_H__ */ SOPE/sope-core/EOCoreData/COPYRIGHT0000644000000000000000000000010115004363604015410 0ustar rootrootCopyright (C) 2005 SKYRIX Software AG Contact: info@skyrix.com SOPE/sope-core/EOCoreData/EOQualifier+CoreData.m0000644000000000000000000001552315004363604020134 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOQualifier+CoreData.h" #include "NSPredicate+EO.h" #include "NSExpression+EO.h" #include "common.h" /* CoreData / Foundation EOF Predicates: NSComparisonPredicate EOKeyValueQualifier / EOKeyComparisonQualifier NSCompoundPredicate EOAndQualifier / EOOrQualifier / EONotQualifier NSExpressions: - constant - evaluatedObject - variable EOQualifierVariable - keypath - function EOF operators: EOQualifierOperatorEqual; EOQualifierOperatorNotEqual; EOQualifierOperatorLessThan; EOQualifierOperatorGreaterThan; EOQualifierOperatorLessThanOrEqualTo; EOQualifierOperatorGreaterThanOrEqualTo; EOQualifierOperatorContains; EOQualifierOperatorLike; EOQualifierOperatorCaseInsensitiveLike; */ @implementation EOQualifier(CoreData) + (NSPredicateOperatorType)predicateOperatorTypeForEOSelector:(SEL)_sel { if (sel_isEqual(_sel, EOQualifierOperatorEqual)) return NSEqualToPredicateOperatorType; if (sel_isEqual(_sel, EOQualifierOperatorNotEqual)) return NSNotEqualToPredicateOperatorType; if (sel_isEqual(_sel, EOQualifierOperatorLessThan)) return NSLessThanPredicateOperatorType; if (sel_isEqual(_sel, EOQualifierOperatorGreaterThan)) return NSGreaterThanPredicateOperatorType; if (sel_isEqual(_sel, EOQualifierOperatorLessThanOrEqualTo)) return NSLessThanOrEqualToPredicateOperatorType; if (sel_isEqual(_sel, EOQualifierOperatorGreaterThanOrEqualTo)) return NSGreaterThanOrEqualToPredicateOperatorType; if (sel_isEqual(_sel, EOQualifierOperatorContains)) return NSInPredicateOperatorType; if (sel_isEqual(_sel, EOQualifierOperatorLike) || sel_isEqual(_sel, EOQualifierOperatorCaseInsensitiveLike)) return NSLikePredicateOperatorType; return NSCustomSelectorPredicateOperatorType; } + (SEL)eoSelectorForForComparisonPredicate:(NSComparisonPredicate *)_p { BOOL hasOpt; SEL sel = NULL; if (_p == nil) return NULL; hasOpt = [_p options] != 0 ? YES : NO; // TODO: need to check options switch ([_p predicateOperatorType]) { case NSCustomSelectorPredicateOperatorType: sel = hasOpt ? NULL : [_p customSelector]; break; case NSLessThanPredicateOperatorType: sel = hasOpt ? NULL : EOQualifierOperatorLessThan; break; case NSLessThanOrEqualToPredicateOperatorType: sel = hasOpt ? NULL : EOQualifierOperatorLessThanOrEqualTo; break; case NSGreaterThanPredicateOperatorType: sel = hasOpt ? NULL : EOQualifierOperatorGreaterThan; break; case NSGreaterThanOrEqualToPredicateOperatorType: sel = hasOpt ? NULL : EOQualifierOperatorGreaterThanOrEqualTo; break; case NSEqualToPredicateOperatorType: sel = hasOpt ? NULL : EOQualifierOperatorEqual; break; case NSNotEqualToPredicateOperatorType: sel = hasOpt ? NULL : EOQualifierOperatorNotEqual; break; case NSLikePredicateOperatorType: sel = ([_p options] == NSCaseInsensitivePredicateOption) ? EOQualifierOperatorCaseInsensitiveLike : (hasOpt ? NULL : EOQualifierOperatorLike); break; case NSInPredicateOperatorType: // TODO: for arrays: containsObject:, for strings: containsString: sel = hasOpt ? NULL : EOQualifierOperatorContains; break; case NSBeginsWithPredicateOperatorType: sel = hasOpt ? NULL : @selector(hasPrefix:); break; case NSEndsWithPredicateOperatorType: sel = hasOpt ? NULL : @selector(hasSuffix:); break; /* unsupported predicates */ case NSMatchesPredicateOperatorType: // TODO default: sel = NULL; break; } if (sel == NULL) { NSLog(@"ERROR(%s): cannot map NSComparisonPredicate to " @"EOQualifier selector: %@", __PRETTY_FUNCTION__, _p); } return sel; } - (NSPredicate *)predicateWithLeftExpression:(NSExpression *)_lhs rightExpression:(NSExpression *)_rhs eoSelector:(SEL)_selector { // TODO: create non-custom predicate if possible NSComparisonPredicateModifier pmod; NSPredicateOperatorType ptype; unsigned popts; if (_selector == NULL) { NSLog(@"ERROR(0x%p/%@): missing selector for predicate construction: %@", self, NSStringFromClass([self class]), self); return nil; } ptype = [EOQualifier predicateOperatorTypeForEOSelector:_selector]; if (ptype == NSCustomSelectorPredicateOperatorType) { return [NSComparisonPredicate predicateWithLeftExpression:_lhs rightExpression:_rhs customSelector:_selector]; } pmod = NSDirectPredicateModifier; popts = 0; if (sel_isEqual(_selector, EOQualifierOperatorCaseInsensitiveLike)) popts = NSCaseInsensitivePredicateOption; return [NSComparisonPredicate predicateWithLeftExpression:_lhs rightExpression:_rhs modifier:pmod type:ptype options:popts]; } + (EOQualifier *)qualifierForPredicate:(NSPredicate *)_predicate { if (_predicate == nil) return nil; if ([_predicate respondsToSelector:@selector(asQualifier)]) return [_predicate asQualifier]; NSLog(@"ERROR(%s): cannot convert NSPredicate class %@!", __PRETTY_FUNCTION__, NSStringFromClass([self class])); return nil; } - (EOQualifier *)asQualifier { return self; } - (NSPredicate *)asPredicate { NSLog(@"TODO(%s): implement me for class %@!", __PRETTY_FUNCTION__, NSStringFromClass([self class])); return nil; } - (NSExpression *)asExpression { return nil; } /* CoreData compatibility */ + (NSPredicate *)andPredicateWithSubpredicates:(NSArray *)_sub { return [NSCompoundPredicate andPredicateWithSubpredicates: [_sub valueForKey:@"asPredicate"]]; } + (NSPredicate *)orPredicateWithSubpredicates:(NSArray *)_sub { return [NSCompoundPredicate orPredicateWithSubpredicates: [_sub valueForKey:@"asPredicate"]]; } + (NSPredicate *)notPredicateWithSubpredicate:(id)_predicate { return [NSCompoundPredicate notPredicateWithSubpredicate: [_predicate asPredicate]]; } - (NSPredicate *)predicateWithSubstitutionVariables:(NSDictionary *)_vars { return [[self asPredicate] predicateWithSubstitutionVariables:_vars]; } - (NSString *)predicateFormat { return [[self asPredicate] predicateFormat]; } @end /* EOQualifier(CoreData) */ SOPE/sope-core/EOCoreData/EOCoreData.h0000644000000000000000000000215015004363604016202 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOCoreData_H__ #define __EOCoreData_H__ #include #include #include #include #include #include #endif /* __EOCoreData_H__ */ SOPE/sope-core/EOCoreData/README.txt0000644000000000000000000000030715004363604015623 0ustar rootrootEOCoreData ========== This is a library/framework which wraps the new MacOSX 10.4 CoreData objects in EOControl objects. It provides various methods to convert objects between the two environments. SOPE/sope-core/EOCoreData/NSString+CoreData.m0000644000000000000000000000170415004363604017472 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" @implementation NSString(CoreData) - (NSPredicate *)asPredicate { return [NSPredicate predicateWithFormat:self arguments:nil]; } @end /* NSString(CoreData) */ SOPE/sope-core/EOCoreData/EOFetchSpecification+CoreData.h0000644000000000000000000000310415004363604021730 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOFetchSpecification_CoreData_H__ #define __EOFetchSpecification_CoreData_H__ #include /* EOFetchSpecification(CoreData) Convert an libEOControl EOFetchSpecification to a CoreData compliant fetch specification. A major difference is that a CoreData NSFetchRequest takes the entity object while in EOF we just pass the name of it. */ @class NSArray; @class NSFetchRequest, NSManagedObjectModel, NSEntityDescription; @interface EOFetchSpecification(CoreData) - (id)initWithFetchRequest:(NSFetchRequest *)_fr; - (NSFetchRequest *)fetchRequestWithEntity:(NSEntityDescription *)_entity; - (NSFetchRequest *)fetchRequestWithModel:(NSManagedObjectModel *)_model; - (NSArray *)sortOrderingsAsSortDescriptors; @end #endif /* __EOFetchSpecification_CoreData_H__ */ SOPE/sope-core/EOCoreData/GNUmakefile.preamble0000644000000000000000000000215215004363604017765 0ustar rootroot# GNUstep Makefile ADDITIONAL_CPP_FLAGS += -Wall -Wno-import -Wno-protocol -O2 libEOCoreData_INCLUDE_DIRS += -I.. ADDITIONAL_CPPFLAGS += -Wall -funsigned-char libEOCoreData_LIBRARIES_DEPEND_UPON += -lEOControl EOCoreData_LIBRARIES_DEPEND_UPON += -framework EOControl # library/framework search pathes DEP_DIRS = ../EOControl ifneq ($(frameworks),yes) ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),\ -L$(GNUSTEP_BUILD_DIR)/$(dir)/$(GNUSTEP_OBJ_DIR_NAME)) else ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir)) endif SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib # libFoundation, gstep-base ifeq ($(FOUNDATION_LIB),fd) libEOCoreData_LIBRARIES_DEPEND_UPON += -lFoundation endif ifeq ($(FOUNDATION_LIB),gnu) libEOCoreData_LIBRARIES_DEPEND_UPON += -lgnustep-base endif # Apple ifeq ($(FOUNDATION_LIB),apple) # TODO: libEOCoreData_PREBIND_ADDR="0xC1000000" ifneq ($(libEOCoreData_PREBIND_ADDR),) libEOCoreData_LDFLAGS += -seg1addr $(libEOCoreData_PREBIND_ADDR) EOCoreData_LDFLAGS += -seg1addr $(libEOCoreData_PREBIND_ADDR) endif ADDITIONAL_LDFLAGS += -framework CoreData endif SOPE/sope-gdl1/0000755000000000000000000000000015004363604012116 5ustar rootrootSOPE/sope-gdl1/Oracle8/0000755000000000000000000000000015004363604013413 5ustar rootrootSOPE/sope-gdl1/Oracle8/OracleValues.h0000644000000000000000000000255515004363604016160 0ustar rootroot/* ** OracleValues.h ** ** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _OracleValues_H #define _OracleValues_H #import #import #include @interface NSNumber (OracleExtensions) - (NSString *) stringValueForOracleType: (ub2) theType attribute: (EOAttribute *) theAttribute; @end @interface NSString (OracleExtensions) - (NSString *) stringValueForOracleType: (ub2) theType attribute: (EOAttribute *) theAttribute; @end #endif SOPE/sope-gdl1/Oracle8/obj/0000755000000000000000000000000015004363604014165 5ustar rootrootSOPE/sope-gdl1/Oracle8/obj/err.d0000644000000000000000000002652115004363604015130 0ustar rootrootobj/err.o: err.m err.h /usr/include/oracle/10.2.0.3/client/oci.h \ /usr/include/oracle/10.2.0.3/client/oratypes.h \ /usr/include/oracle/10.2.0.3/client/ocidfn.h \ /usr/include/oracle/10.2.0.3/client/oci1.h \ /usr/include/oracle/10.2.0.3/client/oro.h \ /usr/include/oracle/10.2.0.3/client/ori.h \ /usr/include/oracle/10.2.0.3/client/ort.h \ /usr/include/oracle/10.2.0.3/client/orl.h \ /usr/include/oracle/10.2.0.3/client/ociextp.h \ /usr/include/oracle/10.2.0.3/client/ociapr.h \ /usr/include/oracle/10.2.0.3/client/ociap.h \ /usr/include/oracle/10.2.0.3/client/nzt.h \ /usr/include/oracle/10.2.0.3/client/nzerror.h \ /usr/include/oracle/10.2.0.3/client/ocixmldb.h \ /usr/include/oracle/10.2.0.3/client/oci8dp.h \ /usr/include/GNUstep/Foundation/Foundation.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/Foundation/FoundationErrors.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h \ /usr/include/GNUstep/Foundation/NSDebug.h \ /usr/include/GNUstep/Foundation/NSProcessInfo.h \ /usr/include/GNUstep/Foundation/NSAffineTransform.h \ /usr/include/GNUstep/Foundation/NSGeometry.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h \ /usr/include/GNUstep/Foundation/NSArchiver.h \ /usr/include/GNUstep/Foundation/NSCoder.h \ /usr/include/GNUstep/Foundation/NSArray.h \ /usr/include/GNUstep/Foundation/NSAttributedString.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/GNUstep/Foundation/NSAutoreleasePool.h \ /usr/include/GNUstep/Foundation/NSBundle.h \ /usr/include/GNUstep/Foundation/NSByteOrder.h \ /usr/include/GNUstep/Foundation/NSCalendarDate.h \ /usr/include/GNUstep/Foundation/NSCharacterSet.h \ /usr/include/GNUstep/Foundation/NSClassDescription.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/Foundation/NSComparisonPredicate.h \ /usr/include/GNUstep/Foundation/NSExpression.h \ /usr/include/GNUstep/Foundation/NSPredicate.h \ /usr/include/GNUstep/Foundation/NSCompoundPredicate.h \ /usr/include/GNUstep/Foundation/NSConnection.h \ /usr/include/GNUstep/Foundation/NSTimer.h \ /usr/include/GNUstep/Foundation/NSRunLoop.h \ /usr/include/GNUstep/Foundation/NSMapTable.h \ /usr/include/GNUstep/Foundation/NSData.h \ /usr/include/GNUstep/Foundation/NSSerialization.h \ /usr/include/GNUstep/Foundation/NSDateFormatter.h \ /usr/include/GNUstep/Foundation/NSFormatter.h \ /usr/include/GNUstep/Foundation/NSDecimalNumber.h \ /usr/include/GNUstep/Foundation/NSDecimal.h \ /usr/include/GNUstep/Foundation/NSValue.h \ /usr/include/GNUstep/Foundation/NSDistantObject.h \ /usr/include/GNUstep/Foundation/NSProxy.h \ /usr/include/GNUstep/Foundation/NSDistributedLock.h \ /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h \ /usr/include/GNUstep/Foundation/NSLock.h \ /usr/include/GNUstep/Foundation/NSNotification.h \ /usr/include/GNUstep/Foundation/NSEnumerator.h \ /usr/include/GNUstep/Foundation/NSError.h \ /usr/include/GNUstep/Foundation/NSFileHandle.h \ /usr/include/GNUstep/Foundation/NSFileManager.h \ /usr/include/GNUstep/Foundation/NSHashTable.h \ /usr/include/GNUstep/Foundation/NSHost.h \ /usr/include/GNUstep/Foundation/NSHTTPCookie.h \ /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h \ /usr/include/GNUstep/Foundation/NSIndexPath.h \ /usr/include/GNUstep/Foundation/NSIndexSet.h \ /usr/include/GNUstep/Foundation/NSInvocation.h \ /usr/include/GNUstep/Foundation/NSMethodSignature.h \ /usr/include/GNUstep/Foundation/NSKeyedArchiver.h \ /usr/include/GNUstep/Foundation/NSPropertyList.h \ /usr/include/GNUstep/Foundation/NSKeyValueCoding.h \ /usr/include/GNUstep/Foundation/NSNotificationQueue.h \ /usr/include/GNUstep/Foundation/NSNetServices.h \ /usr/include/GNUstep/Foundation/NSNull.h \ /usr/include/GNUstep/Foundation/NSNumberFormatter.h \ /usr/include/GNUstep/Foundation/NSPathUtilities.h \ /usr/include/GNUstep/Foundation/NSPortCoder.h \ /usr/include/GNUstep/Foundation/NSPortMessage.h \ /usr/include/GNUstep/Foundation/NSPort.h \ /usr/include/GNUstep/Foundation/NSPortNameServer.h \ /usr/include/GNUstep/Foundation/NSProtocolChecker.h \ /usr/include/GNUstep/Foundation/NSScanner.h \ /usr/include/GNUstep/Foundation/NSSet.h \ /usr/include/GNUstep/Foundation/NSSortDescriptor.h \ /usr/include/GNUstep/Foundation/NSSpellServer.h \ /usr/include/GNUstep/Foundation/NSStream.h \ /usr/include/GNUstep/Foundation/NSTask.h \ /usr/include/GNUstep/Foundation/NSThread.h \ /usr/include/GNUstep/Foundation/NSTimeZone.h \ /usr/include/GNUstep/Foundation/NSUndoManager.h \ /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h \ /usr/include/GNUstep/Foundation/NSURLCache.h \ /usr/include/GNUstep/Foundation/NSURLConnection.h \ /usr/include/GNUstep/Foundation/NSURLCredential.h \ /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h \ /usr/include/GNUstep/Foundation/NSURLDownload.h \ /usr/include/GNUstep/Foundation/NSURLError.h \ /usr/include/GNUstep/Foundation/NSURL.h \ /usr/include/GNUstep/Foundation/NSURLHandle.h \ /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h \ /usr/include/GNUstep/Foundation/NSURLProtocol.h \ /usr/include/GNUstep/Foundation/NSURLRequest.h \ /usr/include/GNUstep/Foundation/NSURLResponse.h \ /usr/include/GNUstep/Foundation/NSUserDefaults.h \ /usr/include/GNUstep/Foundation/NSValueTransformer.h \ /usr/include/GNUstep/Foundation/NSXMLParser.h err.h: /usr/include/oracle/10.2.0.3/client/oci.h: /usr/include/oracle/10.2.0.3/client/oratypes.h: /usr/include/oracle/10.2.0.3/client/ocidfn.h: /usr/include/oracle/10.2.0.3/client/oci1.h: /usr/include/oracle/10.2.0.3/client/oro.h: /usr/include/oracle/10.2.0.3/client/ori.h: /usr/include/oracle/10.2.0.3/client/ort.h: /usr/include/oracle/10.2.0.3/client/orl.h: /usr/include/oracle/10.2.0.3/client/ociextp.h: /usr/include/oracle/10.2.0.3/client/ociapr.h: /usr/include/oracle/10.2.0.3/client/ociap.h: /usr/include/oracle/10.2.0.3/client/nzt.h: /usr/include/oracle/10.2.0.3/client/nzerror.h: /usr/include/oracle/10.2.0.3/client/ocixmldb.h: /usr/include/oracle/10.2.0.3/client/oci8dp.h: /usr/include/GNUstep/Foundation/Foundation.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/Foundation/FoundationErrors.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: /usr/include/GNUstep/Foundation/NSDebug.h: /usr/include/GNUstep/Foundation/NSProcessInfo.h: /usr/include/GNUstep/Foundation/NSAffineTransform.h: /usr/include/GNUstep/Foundation/NSGeometry.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: /usr/include/GNUstep/Foundation/NSArchiver.h: /usr/include/GNUstep/Foundation/NSCoder.h: /usr/include/GNUstep/Foundation/NSArray.h: /usr/include/GNUstep/Foundation/NSAttributedString.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/GNUstep/Foundation/NSAutoreleasePool.h: /usr/include/GNUstep/Foundation/NSBundle.h: /usr/include/GNUstep/Foundation/NSByteOrder.h: /usr/include/GNUstep/Foundation/NSCalendarDate.h: /usr/include/GNUstep/Foundation/NSCharacterSet.h: /usr/include/GNUstep/Foundation/NSClassDescription.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/Foundation/NSComparisonPredicate.h: /usr/include/GNUstep/Foundation/NSExpression.h: /usr/include/GNUstep/Foundation/NSPredicate.h: /usr/include/GNUstep/Foundation/NSCompoundPredicate.h: /usr/include/GNUstep/Foundation/NSConnection.h: /usr/include/GNUstep/Foundation/NSTimer.h: /usr/include/GNUstep/Foundation/NSRunLoop.h: /usr/include/GNUstep/Foundation/NSMapTable.h: /usr/include/GNUstep/Foundation/NSData.h: /usr/include/GNUstep/Foundation/NSSerialization.h: /usr/include/GNUstep/Foundation/NSDateFormatter.h: /usr/include/GNUstep/Foundation/NSFormatter.h: /usr/include/GNUstep/Foundation/NSDecimalNumber.h: /usr/include/GNUstep/Foundation/NSDecimal.h: /usr/include/GNUstep/Foundation/NSValue.h: /usr/include/GNUstep/Foundation/NSDistantObject.h: /usr/include/GNUstep/Foundation/NSProxy.h: /usr/include/GNUstep/Foundation/NSDistributedLock.h: /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h: /usr/include/GNUstep/Foundation/NSLock.h: /usr/include/GNUstep/Foundation/NSNotification.h: /usr/include/GNUstep/Foundation/NSEnumerator.h: /usr/include/GNUstep/Foundation/NSError.h: /usr/include/GNUstep/Foundation/NSFileHandle.h: /usr/include/GNUstep/Foundation/NSFileManager.h: /usr/include/GNUstep/Foundation/NSHashTable.h: /usr/include/GNUstep/Foundation/NSHost.h: /usr/include/GNUstep/Foundation/NSHTTPCookie.h: /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h: /usr/include/GNUstep/Foundation/NSIndexPath.h: /usr/include/GNUstep/Foundation/NSIndexSet.h: /usr/include/GNUstep/Foundation/NSInvocation.h: /usr/include/GNUstep/Foundation/NSMethodSignature.h: /usr/include/GNUstep/Foundation/NSKeyedArchiver.h: /usr/include/GNUstep/Foundation/NSPropertyList.h: /usr/include/GNUstep/Foundation/NSKeyValueCoding.h: /usr/include/GNUstep/Foundation/NSNotificationQueue.h: /usr/include/GNUstep/Foundation/NSNetServices.h: /usr/include/GNUstep/Foundation/NSNull.h: /usr/include/GNUstep/Foundation/NSNumberFormatter.h: /usr/include/GNUstep/Foundation/NSPathUtilities.h: /usr/include/GNUstep/Foundation/NSPortCoder.h: /usr/include/GNUstep/Foundation/NSPortMessage.h: /usr/include/GNUstep/Foundation/NSPort.h: /usr/include/GNUstep/Foundation/NSPortNameServer.h: /usr/include/GNUstep/Foundation/NSProtocolChecker.h: /usr/include/GNUstep/Foundation/NSScanner.h: /usr/include/GNUstep/Foundation/NSSet.h: /usr/include/GNUstep/Foundation/NSSortDescriptor.h: /usr/include/GNUstep/Foundation/NSSpellServer.h: /usr/include/GNUstep/Foundation/NSStream.h: /usr/include/GNUstep/Foundation/NSTask.h: /usr/include/GNUstep/Foundation/NSThread.h: /usr/include/GNUstep/Foundation/NSTimeZone.h: /usr/include/GNUstep/Foundation/NSUndoManager.h: /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h: /usr/include/GNUstep/Foundation/NSURLCache.h: /usr/include/GNUstep/Foundation/NSURLConnection.h: /usr/include/GNUstep/Foundation/NSURLCredential.h: /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h: /usr/include/GNUstep/Foundation/NSURLDownload.h: /usr/include/GNUstep/Foundation/NSURLError.h: /usr/include/GNUstep/Foundation/NSURL.h: /usr/include/GNUstep/Foundation/NSURLHandle.h: /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h: /usr/include/GNUstep/Foundation/NSURLProtocol.h: /usr/include/GNUstep/Foundation/NSURLRequest.h: /usr/include/GNUstep/Foundation/NSURLResponse.h: /usr/include/GNUstep/Foundation/NSUserDefaults.h: /usr/include/GNUstep/Foundation/NSValueTransformer.h: /usr/include/GNUstep/Foundation/NSXMLParser.h: SOPE/sope-gdl1/Oracle8/obj/OracleAdaptorChannelController.d0000644000000000000000000003026315004363604022413 0ustar rootrootobj/OracleAdaptorChannelController.o: OracleAdaptorChannelController.m \ OracleAdaptorChannelController.h ../GDLAccess/EODelegateResponse.h \ ../GDLAccess/EOEntity.h /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h \ /usr/include/GNUstep/Foundation/NSRange.h \ ../../sope-core/EOControl/EOClassDescription.h \ /usr/include/GNUstep/Foundation/Foundation.h \ /usr/include/GNUstep/Foundation/FoundationErrors.h \ /usr/include/GNUstep/Foundation/NSDebug.h \ /usr/include/GNUstep/Foundation/NSProcessInfo.h \ /usr/include/GNUstep/Foundation/NSAffineTransform.h \ /usr/include/GNUstep/Foundation/NSGeometry.h \ /usr/include/GNUstep/Foundation/NSArchiver.h \ /usr/include/GNUstep/Foundation/NSCoder.h \ /usr/include/GNUstep/Foundation/NSArray.h \ /usr/include/GNUstep/Foundation/NSAttributedString.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/GNUstep/Foundation/NSAutoreleasePool.h \ /usr/include/GNUstep/Foundation/NSBundle.h \ /usr/include/GNUstep/Foundation/NSByteOrder.h \ /usr/include/GNUstep/Foundation/NSCalendarDate.h \ /usr/include/GNUstep/Foundation/NSCharacterSet.h \ /usr/include/GNUstep/Foundation/NSClassDescription.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/Foundation/NSComparisonPredicate.h \ /usr/include/GNUstep/Foundation/NSExpression.h \ /usr/include/GNUstep/Foundation/NSPredicate.h \ /usr/include/GNUstep/Foundation/NSCompoundPredicate.h \ /usr/include/GNUstep/Foundation/NSConnection.h \ /usr/include/GNUstep/Foundation/NSTimer.h \ /usr/include/GNUstep/Foundation/NSRunLoop.h \ /usr/include/GNUstep/Foundation/NSMapTable.h \ /usr/include/GNUstep/Foundation/NSData.h \ /usr/include/GNUstep/Foundation/NSSerialization.h \ /usr/include/GNUstep/Foundation/NSDateFormatter.h \ /usr/include/GNUstep/Foundation/NSFormatter.h \ /usr/include/GNUstep/Foundation/NSDecimalNumber.h \ /usr/include/GNUstep/Foundation/NSDecimal.h \ /usr/include/GNUstep/Foundation/NSValue.h \ /usr/include/GNUstep/Foundation/NSDistantObject.h \ /usr/include/GNUstep/Foundation/NSProxy.h \ /usr/include/GNUstep/Foundation/NSDistributedLock.h \ /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h \ /usr/include/GNUstep/Foundation/NSLock.h \ /usr/include/GNUstep/Foundation/NSNotification.h \ /usr/include/GNUstep/Foundation/NSEnumerator.h \ /usr/include/GNUstep/Foundation/NSError.h \ /usr/include/GNUstep/Foundation/NSFileHandle.h \ /usr/include/GNUstep/Foundation/NSFileManager.h \ /usr/include/GNUstep/Foundation/NSHashTable.h \ /usr/include/GNUstep/Foundation/NSHost.h \ /usr/include/GNUstep/Foundation/NSHTTPCookie.h \ /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h \ /usr/include/GNUstep/Foundation/NSIndexPath.h \ /usr/include/GNUstep/Foundation/NSIndexSet.h \ /usr/include/GNUstep/Foundation/NSInvocation.h \ /usr/include/GNUstep/Foundation/NSMethodSignature.h \ /usr/include/GNUstep/Foundation/NSKeyedArchiver.h \ /usr/include/GNUstep/Foundation/NSPropertyList.h \ /usr/include/GNUstep/Foundation/NSKeyValueCoding.h \ /usr/include/GNUstep/Foundation/NSNotificationQueue.h \ /usr/include/GNUstep/Foundation/NSNetServices.h \ /usr/include/GNUstep/Foundation/NSNull.h \ /usr/include/GNUstep/Foundation/NSNumberFormatter.h \ /usr/include/GNUstep/Foundation/NSPathUtilities.h \ /usr/include/GNUstep/Foundation/NSPortCoder.h \ /usr/include/GNUstep/Foundation/NSPortMessage.h \ /usr/include/GNUstep/Foundation/NSPort.h \ /usr/include/GNUstep/Foundation/NSPortNameServer.h \ /usr/include/GNUstep/Foundation/NSProtocolChecker.h \ /usr/include/GNUstep/Foundation/NSScanner.h \ /usr/include/GNUstep/Foundation/NSSet.h \ /usr/include/GNUstep/Foundation/NSSortDescriptor.h \ /usr/include/GNUstep/Foundation/NSSpellServer.h \ /usr/include/GNUstep/Foundation/NSStream.h \ /usr/include/GNUstep/Foundation/NSTask.h \ /usr/include/GNUstep/Foundation/NSThread.h \ /usr/include/GNUstep/Foundation/NSTimeZone.h \ /usr/include/GNUstep/Foundation/NSUndoManager.h \ /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h \ /usr/include/GNUstep/Foundation/NSURLCache.h \ /usr/include/GNUstep/Foundation/NSURLConnection.h \ /usr/include/GNUstep/Foundation/NSURLCredential.h \ /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h \ /usr/include/GNUstep/Foundation/NSURLDownload.h \ /usr/include/GNUstep/Foundation/NSURLError.h \ /usr/include/GNUstep/Foundation/NSURL.h \ /usr/include/GNUstep/Foundation/NSURLHandle.h \ /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h \ /usr/include/GNUstep/Foundation/NSURLProtocol.h \ /usr/include/GNUstep/Foundation/NSURLRequest.h \ /usr/include/GNUstep/Foundation/NSURLResponse.h \ /usr/include/GNUstep/Foundation/NSUserDefaults.h \ /usr/include/GNUstep/Foundation/NSValueTransformer.h \ /usr/include/GNUstep/Foundation/NSXMLParser.h \ ../../sope-core/EOControl/EOGlobalID.h \ /usr/include/oracle/10.2.0.3/client/oci.h \ /usr/include/oracle/10.2.0.3/client/oratypes.h \ /usr/include/oracle/10.2.0.3/client/ocidfn.h \ /usr/include/oracle/10.2.0.3/client/oci1.h \ /usr/include/oracle/10.2.0.3/client/oro.h \ /usr/include/oracle/10.2.0.3/client/ori.h \ /usr/include/oracle/10.2.0.3/client/ort.h \ /usr/include/oracle/10.2.0.3/client/orl.h \ /usr/include/oracle/10.2.0.3/client/ociextp.h \ /usr/include/oracle/10.2.0.3/client/ociapr.h \ /usr/include/oracle/10.2.0.3/client/ociap.h \ /usr/include/oracle/10.2.0.3/client/nzt.h \ /usr/include/oracle/10.2.0.3/client/nzerror.h \ /usr/include/oracle/10.2.0.3/client/ocixmldb.h \ /usr/include/oracle/10.2.0.3/client/oci8dp.h err.h \ OracleAdaptorChannel.h ../GDLAccess/EOAdaptorChannel.h \ OracleAdaptorContext.h ../GDLAccess/EOAdaptorContext.h \ ../GDLAccess/EOSQLExpression.h ../GDLAccess/EOExpressionArray.h \ ../GDLAccess/EOJoinTypes.h OracleAdaptorChannelController.h: ../GDLAccess/EODelegateResponse.h: ../GDLAccess/EOEntity.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: /usr/include/GNUstep/Foundation/NSRange.h: ../../sope-core/EOControl/EOClassDescription.h: /usr/include/GNUstep/Foundation/Foundation.h: /usr/include/GNUstep/Foundation/FoundationErrors.h: /usr/include/GNUstep/Foundation/NSDebug.h: /usr/include/GNUstep/Foundation/NSProcessInfo.h: /usr/include/GNUstep/Foundation/NSAffineTransform.h: /usr/include/GNUstep/Foundation/NSGeometry.h: /usr/include/GNUstep/Foundation/NSArchiver.h: /usr/include/GNUstep/Foundation/NSCoder.h: /usr/include/GNUstep/Foundation/NSArray.h: /usr/include/GNUstep/Foundation/NSAttributedString.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/GNUstep/Foundation/NSAutoreleasePool.h: /usr/include/GNUstep/Foundation/NSBundle.h: /usr/include/GNUstep/Foundation/NSByteOrder.h: /usr/include/GNUstep/Foundation/NSCalendarDate.h: /usr/include/GNUstep/Foundation/NSCharacterSet.h: /usr/include/GNUstep/Foundation/NSClassDescription.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/Foundation/NSComparisonPredicate.h: /usr/include/GNUstep/Foundation/NSExpression.h: /usr/include/GNUstep/Foundation/NSPredicate.h: /usr/include/GNUstep/Foundation/NSCompoundPredicate.h: /usr/include/GNUstep/Foundation/NSConnection.h: /usr/include/GNUstep/Foundation/NSTimer.h: /usr/include/GNUstep/Foundation/NSRunLoop.h: /usr/include/GNUstep/Foundation/NSMapTable.h: /usr/include/GNUstep/Foundation/NSData.h: /usr/include/GNUstep/Foundation/NSSerialization.h: /usr/include/GNUstep/Foundation/NSDateFormatter.h: /usr/include/GNUstep/Foundation/NSFormatter.h: /usr/include/GNUstep/Foundation/NSDecimalNumber.h: /usr/include/GNUstep/Foundation/NSDecimal.h: /usr/include/GNUstep/Foundation/NSValue.h: /usr/include/GNUstep/Foundation/NSDistantObject.h: /usr/include/GNUstep/Foundation/NSProxy.h: /usr/include/GNUstep/Foundation/NSDistributedLock.h: /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h: /usr/include/GNUstep/Foundation/NSLock.h: /usr/include/GNUstep/Foundation/NSNotification.h: /usr/include/GNUstep/Foundation/NSEnumerator.h: /usr/include/GNUstep/Foundation/NSError.h: /usr/include/GNUstep/Foundation/NSFileHandle.h: /usr/include/GNUstep/Foundation/NSFileManager.h: /usr/include/GNUstep/Foundation/NSHashTable.h: /usr/include/GNUstep/Foundation/NSHost.h: /usr/include/GNUstep/Foundation/NSHTTPCookie.h: /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h: /usr/include/GNUstep/Foundation/NSIndexPath.h: /usr/include/GNUstep/Foundation/NSIndexSet.h: /usr/include/GNUstep/Foundation/NSInvocation.h: /usr/include/GNUstep/Foundation/NSMethodSignature.h: /usr/include/GNUstep/Foundation/NSKeyedArchiver.h: /usr/include/GNUstep/Foundation/NSPropertyList.h: /usr/include/GNUstep/Foundation/NSKeyValueCoding.h: /usr/include/GNUstep/Foundation/NSNotificationQueue.h: /usr/include/GNUstep/Foundation/NSNetServices.h: /usr/include/GNUstep/Foundation/NSNull.h: /usr/include/GNUstep/Foundation/NSNumberFormatter.h: /usr/include/GNUstep/Foundation/NSPathUtilities.h: /usr/include/GNUstep/Foundation/NSPortCoder.h: /usr/include/GNUstep/Foundation/NSPortMessage.h: /usr/include/GNUstep/Foundation/NSPort.h: /usr/include/GNUstep/Foundation/NSPortNameServer.h: /usr/include/GNUstep/Foundation/NSProtocolChecker.h: /usr/include/GNUstep/Foundation/NSScanner.h: /usr/include/GNUstep/Foundation/NSSet.h: /usr/include/GNUstep/Foundation/NSSortDescriptor.h: /usr/include/GNUstep/Foundation/NSSpellServer.h: /usr/include/GNUstep/Foundation/NSStream.h: /usr/include/GNUstep/Foundation/NSTask.h: /usr/include/GNUstep/Foundation/NSThread.h: /usr/include/GNUstep/Foundation/NSTimeZone.h: /usr/include/GNUstep/Foundation/NSUndoManager.h: /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h: /usr/include/GNUstep/Foundation/NSURLCache.h: /usr/include/GNUstep/Foundation/NSURLConnection.h: /usr/include/GNUstep/Foundation/NSURLCredential.h: /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h: /usr/include/GNUstep/Foundation/NSURLDownload.h: /usr/include/GNUstep/Foundation/NSURLError.h: /usr/include/GNUstep/Foundation/NSURL.h: /usr/include/GNUstep/Foundation/NSURLHandle.h: /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h: /usr/include/GNUstep/Foundation/NSURLProtocol.h: /usr/include/GNUstep/Foundation/NSURLRequest.h: /usr/include/GNUstep/Foundation/NSURLResponse.h: /usr/include/GNUstep/Foundation/NSUserDefaults.h: /usr/include/GNUstep/Foundation/NSValueTransformer.h: /usr/include/GNUstep/Foundation/NSXMLParser.h: ../../sope-core/EOControl/EOGlobalID.h: /usr/include/oracle/10.2.0.3/client/oci.h: /usr/include/oracle/10.2.0.3/client/oratypes.h: /usr/include/oracle/10.2.0.3/client/ocidfn.h: /usr/include/oracle/10.2.0.3/client/oci1.h: /usr/include/oracle/10.2.0.3/client/oro.h: /usr/include/oracle/10.2.0.3/client/ori.h: /usr/include/oracle/10.2.0.3/client/ort.h: /usr/include/oracle/10.2.0.3/client/orl.h: /usr/include/oracle/10.2.0.3/client/ociextp.h: /usr/include/oracle/10.2.0.3/client/ociapr.h: /usr/include/oracle/10.2.0.3/client/ociap.h: /usr/include/oracle/10.2.0.3/client/nzt.h: /usr/include/oracle/10.2.0.3/client/nzerror.h: /usr/include/oracle/10.2.0.3/client/ocixmldb.h: /usr/include/oracle/10.2.0.3/client/oci8dp.h: err.h: OracleAdaptorChannel.h: ../GDLAccess/EOAdaptorChannel.h: OracleAdaptorContext.h: ../GDLAccess/EOAdaptorContext.h: ../GDLAccess/EOSQLExpression.h: ../GDLAccess/EOExpressionArray.h: ../GDLAccess/EOJoinTypes.h: SOPE/sope-gdl1/Oracle8/obj/OracleValues.d0000644000000000000000000002666115004363604016732 0ustar rootrootobj/OracleValues.o: OracleValues.m OracleValues.h \ /usr/include/GNUstep/Foundation/Foundation.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/Foundation/FoundationErrors.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h \ /usr/include/GNUstep/Foundation/NSDebug.h \ /usr/include/GNUstep/Foundation/NSProcessInfo.h \ /usr/include/GNUstep/Foundation/NSAffineTransform.h \ /usr/include/GNUstep/Foundation/NSGeometry.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h \ /usr/include/GNUstep/Foundation/NSArchiver.h \ /usr/include/GNUstep/Foundation/NSCoder.h \ /usr/include/GNUstep/Foundation/NSArray.h \ /usr/include/GNUstep/Foundation/NSAttributedString.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/GNUstep/Foundation/NSAutoreleasePool.h \ /usr/include/GNUstep/Foundation/NSBundle.h \ /usr/include/GNUstep/Foundation/NSByteOrder.h \ /usr/include/GNUstep/Foundation/NSCalendarDate.h \ /usr/include/GNUstep/Foundation/NSCharacterSet.h \ /usr/include/GNUstep/Foundation/NSClassDescription.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/Foundation/NSComparisonPredicate.h \ /usr/include/GNUstep/Foundation/NSExpression.h \ /usr/include/GNUstep/Foundation/NSPredicate.h \ /usr/include/GNUstep/Foundation/NSCompoundPredicate.h \ /usr/include/GNUstep/Foundation/NSConnection.h \ /usr/include/GNUstep/Foundation/NSTimer.h \ /usr/include/GNUstep/Foundation/NSRunLoop.h \ /usr/include/GNUstep/Foundation/NSMapTable.h \ /usr/include/GNUstep/Foundation/NSData.h \ /usr/include/GNUstep/Foundation/NSSerialization.h \ /usr/include/GNUstep/Foundation/NSDateFormatter.h \ /usr/include/GNUstep/Foundation/NSFormatter.h \ /usr/include/GNUstep/Foundation/NSDecimalNumber.h \ /usr/include/GNUstep/Foundation/NSDecimal.h \ /usr/include/GNUstep/Foundation/NSValue.h \ /usr/include/GNUstep/Foundation/NSDistantObject.h \ /usr/include/GNUstep/Foundation/NSProxy.h \ /usr/include/GNUstep/Foundation/NSDistributedLock.h \ /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h \ /usr/include/GNUstep/Foundation/NSLock.h \ /usr/include/GNUstep/Foundation/NSNotification.h \ /usr/include/GNUstep/Foundation/NSEnumerator.h \ /usr/include/GNUstep/Foundation/NSError.h \ /usr/include/GNUstep/Foundation/NSFileHandle.h \ /usr/include/GNUstep/Foundation/NSFileManager.h \ /usr/include/GNUstep/Foundation/NSHashTable.h \ /usr/include/GNUstep/Foundation/NSHost.h \ /usr/include/GNUstep/Foundation/NSHTTPCookie.h \ /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h \ /usr/include/GNUstep/Foundation/NSIndexPath.h \ /usr/include/GNUstep/Foundation/NSIndexSet.h \ /usr/include/GNUstep/Foundation/NSInvocation.h \ /usr/include/GNUstep/Foundation/NSMethodSignature.h \ /usr/include/GNUstep/Foundation/NSKeyedArchiver.h \ /usr/include/GNUstep/Foundation/NSPropertyList.h \ /usr/include/GNUstep/Foundation/NSKeyValueCoding.h \ /usr/include/GNUstep/Foundation/NSNotificationQueue.h \ /usr/include/GNUstep/Foundation/NSNetServices.h \ /usr/include/GNUstep/Foundation/NSNull.h \ /usr/include/GNUstep/Foundation/NSNumberFormatter.h \ /usr/include/GNUstep/Foundation/NSPathUtilities.h \ /usr/include/GNUstep/Foundation/NSPortCoder.h \ /usr/include/GNUstep/Foundation/NSPortMessage.h \ /usr/include/GNUstep/Foundation/NSPort.h \ /usr/include/GNUstep/Foundation/NSPortNameServer.h \ /usr/include/GNUstep/Foundation/NSProtocolChecker.h \ /usr/include/GNUstep/Foundation/NSScanner.h \ /usr/include/GNUstep/Foundation/NSSet.h \ /usr/include/GNUstep/Foundation/NSSortDescriptor.h \ /usr/include/GNUstep/Foundation/NSSpellServer.h \ /usr/include/GNUstep/Foundation/NSStream.h \ /usr/include/GNUstep/Foundation/NSTask.h \ /usr/include/GNUstep/Foundation/NSThread.h \ /usr/include/GNUstep/Foundation/NSTimeZone.h \ /usr/include/GNUstep/Foundation/NSUndoManager.h \ /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h \ /usr/include/GNUstep/Foundation/NSURLCache.h \ /usr/include/GNUstep/Foundation/NSURLConnection.h \ /usr/include/GNUstep/Foundation/NSURLCredential.h \ /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h \ /usr/include/GNUstep/Foundation/NSURLDownload.h \ /usr/include/GNUstep/Foundation/NSURLError.h \ /usr/include/GNUstep/Foundation/NSURL.h \ /usr/include/GNUstep/Foundation/NSURLHandle.h \ /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h \ /usr/include/GNUstep/Foundation/NSURLProtocol.h \ /usr/include/GNUstep/Foundation/NSURLRequest.h \ /usr/include/GNUstep/Foundation/NSURLResponse.h \ /usr/include/GNUstep/Foundation/NSUserDefaults.h \ /usr/include/GNUstep/Foundation/NSValueTransformer.h \ /usr/include/GNUstep/Foundation/NSXMLParser.h \ ../GDLAccess/EOAttribute.h /usr/include/oracle/10.2.0.3/client/oci.h \ /usr/include/oracle/10.2.0.3/client/oratypes.h \ /usr/include/oracle/10.2.0.3/client/ocidfn.h \ /usr/include/oracle/10.2.0.3/client/oci1.h \ /usr/include/oracle/10.2.0.3/client/oro.h \ /usr/include/oracle/10.2.0.3/client/ori.h \ /usr/include/oracle/10.2.0.3/client/ort.h \ /usr/include/oracle/10.2.0.3/client/orl.h \ /usr/include/oracle/10.2.0.3/client/ociextp.h \ /usr/include/oracle/10.2.0.3/client/ociapr.h \ /usr/include/oracle/10.2.0.3/client/ociap.h \ /usr/include/oracle/10.2.0.3/client/nzt.h \ /usr/include/oracle/10.2.0.3/client/nzerror.h \ /usr/include/oracle/10.2.0.3/client/ocixmldb.h \ /usr/include/oracle/10.2.0.3/client/oci8dp.h OracleValues.h: /usr/include/GNUstep/Foundation/Foundation.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/Foundation/FoundationErrors.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: /usr/include/GNUstep/Foundation/NSDebug.h: /usr/include/GNUstep/Foundation/NSProcessInfo.h: /usr/include/GNUstep/Foundation/NSAffineTransform.h: /usr/include/GNUstep/Foundation/NSGeometry.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: /usr/include/GNUstep/Foundation/NSArchiver.h: /usr/include/GNUstep/Foundation/NSCoder.h: /usr/include/GNUstep/Foundation/NSArray.h: /usr/include/GNUstep/Foundation/NSAttributedString.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/GNUstep/Foundation/NSAutoreleasePool.h: /usr/include/GNUstep/Foundation/NSBundle.h: /usr/include/GNUstep/Foundation/NSByteOrder.h: /usr/include/GNUstep/Foundation/NSCalendarDate.h: /usr/include/GNUstep/Foundation/NSCharacterSet.h: /usr/include/GNUstep/Foundation/NSClassDescription.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/Foundation/NSComparisonPredicate.h: /usr/include/GNUstep/Foundation/NSExpression.h: /usr/include/GNUstep/Foundation/NSPredicate.h: /usr/include/GNUstep/Foundation/NSCompoundPredicate.h: /usr/include/GNUstep/Foundation/NSConnection.h: /usr/include/GNUstep/Foundation/NSTimer.h: /usr/include/GNUstep/Foundation/NSRunLoop.h: /usr/include/GNUstep/Foundation/NSMapTable.h: /usr/include/GNUstep/Foundation/NSData.h: /usr/include/GNUstep/Foundation/NSSerialization.h: /usr/include/GNUstep/Foundation/NSDateFormatter.h: /usr/include/GNUstep/Foundation/NSFormatter.h: /usr/include/GNUstep/Foundation/NSDecimalNumber.h: /usr/include/GNUstep/Foundation/NSDecimal.h: /usr/include/GNUstep/Foundation/NSValue.h: /usr/include/GNUstep/Foundation/NSDistantObject.h: /usr/include/GNUstep/Foundation/NSProxy.h: /usr/include/GNUstep/Foundation/NSDistributedLock.h: /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h: /usr/include/GNUstep/Foundation/NSLock.h: /usr/include/GNUstep/Foundation/NSNotification.h: /usr/include/GNUstep/Foundation/NSEnumerator.h: /usr/include/GNUstep/Foundation/NSError.h: /usr/include/GNUstep/Foundation/NSFileHandle.h: /usr/include/GNUstep/Foundation/NSFileManager.h: /usr/include/GNUstep/Foundation/NSHashTable.h: /usr/include/GNUstep/Foundation/NSHost.h: /usr/include/GNUstep/Foundation/NSHTTPCookie.h: /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h: /usr/include/GNUstep/Foundation/NSIndexPath.h: /usr/include/GNUstep/Foundation/NSIndexSet.h: /usr/include/GNUstep/Foundation/NSInvocation.h: /usr/include/GNUstep/Foundation/NSMethodSignature.h: /usr/include/GNUstep/Foundation/NSKeyedArchiver.h: /usr/include/GNUstep/Foundation/NSPropertyList.h: /usr/include/GNUstep/Foundation/NSKeyValueCoding.h: /usr/include/GNUstep/Foundation/NSNotificationQueue.h: /usr/include/GNUstep/Foundation/NSNetServices.h: /usr/include/GNUstep/Foundation/NSNull.h: /usr/include/GNUstep/Foundation/NSNumberFormatter.h: /usr/include/GNUstep/Foundation/NSPathUtilities.h: /usr/include/GNUstep/Foundation/NSPortCoder.h: /usr/include/GNUstep/Foundation/NSPortMessage.h: /usr/include/GNUstep/Foundation/NSPort.h: /usr/include/GNUstep/Foundation/NSPortNameServer.h: /usr/include/GNUstep/Foundation/NSProtocolChecker.h: /usr/include/GNUstep/Foundation/NSScanner.h: /usr/include/GNUstep/Foundation/NSSet.h: /usr/include/GNUstep/Foundation/NSSortDescriptor.h: /usr/include/GNUstep/Foundation/NSSpellServer.h: /usr/include/GNUstep/Foundation/NSStream.h: /usr/include/GNUstep/Foundation/NSTask.h: /usr/include/GNUstep/Foundation/NSThread.h: /usr/include/GNUstep/Foundation/NSTimeZone.h: /usr/include/GNUstep/Foundation/NSUndoManager.h: /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h: /usr/include/GNUstep/Foundation/NSURLCache.h: /usr/include/GNUstep/Foundation/NSURLConnection.h: /usr/include/GNUstep/Foundation/NSURLCredential.h: /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h: /usr/include/GNUstep/Foundation/NSURLDownload.h: /usr/include/GNUstep/Foundation/NSURLError.h: /usr/include/GNUstep/Foundation/NSURL.h: /usr/include/GNUstep/Foundation/NSURLHandle.h: /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h: /usr/include/GNUstep/Foundation/NSURLProtocol.h: /usr/include/GNUstep/Foundation/NSURLRequest.h: /usr/include/GNUstep/Foundation/NSURLResponse.h: /usr/include/GNUstep/Foundation/NSUserDefaults.h: /usr/include/GNUstep/Foundation/NSValueTransformer.h: /usr/include/GNUstep/Foundation/NSXMLParser.h: ../GDLAccess/EOAttribute.h: /usr/include/oracle/10.2.0.3/client/oci.h: /usr/include/oracle/10.2.0.3/client/oratypes.h: /usr/include/oracle/10.2.0.3/client/ocidfn.h: /usr/include/oracle/10.2.0.3/client/oci1.h: /usr/include/oracle/10.2.0.3/client/oro.h: /usr/include/oracle/10.2.0.3/client/ori.h: /usr/include/oracle/10.2.0.3/client/ort.h: /usr/include/oracle/10.2.0.3/client/orl.h: /usr/include/oracle/10.2.0.3/client/ociextp.h: /usr/include/oracle/10.2.0.3/client/ociapr.h: /usr/include/oracle/10.2.0.3/client/ociap.h: /usr/include/oracle/10.2.0.3/client/nzt.h: /usr/include/oracle/10.2.0.3/client/nzerror.h: /usr/include/oracle/10.2.0.3/client/ocixmldb.h: /usr/include/oracle/10.2.0.3/client/oci8dp.h: SOPE/sope-gdl1/Oracle8/obj/EOAttribute+Oracle.d0000644000000000000000000000536315004363604017731 0ustar rootrootobj/EOAttribute+Oracle.o: EOAttribute+Oracle.m EOAttribute+Oracle.h \ ../GDLAccess/EOAttribute.h /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h \ /usr/include/GNUstep/Foundation/NSRange.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/oracle/10.2.0.3/client/oci.h \ /usr/include/oracle/10.2.0.3/client/oratypes.h \ /usr/include/oracle/10.2.0.3/client/ocidfn.h \ /usr/include/oracle/10.2.0.3/client/oci1.h \ /usr/include/oracle/10.2.0.3/client/oro.h \ /usr/include/oracle/10.2.0.3/client/ori.h \ /usr/include/oracle/10.2.0.3/client/ort.h \ /usr/include/oracle/10.2.0.3/client/orl.h \ /usr/include/oracle/10.2.0.3/client/ociextp.h \ /usr/include/oracle/10.2.0.3/client/ociapr.h \ /usr/include/oracle/10.2.0.3/client/ociap.h \ /usr/include/oracle/10.2.0.3/client/nzt.h \ /usr/include/oracle/10.2.0.3/client/nzerror.h \ /usr/include/oracle/10.2.0.3/client/ocixmldb.h \ /usr/include/oracle/10.2.0.3/client/oci8dp.h EOAttribute+Oracle.h: ../GDLAccess/EOAttribute.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: /usr/include/GNUstep/Foundation/NSRange.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/oracle/10.2.0.3/client/oci.h: /usr/include/oracle/10.2.0.3/client/oratypes.h: /usr/include/oracle/10.2.0.3/client/ocidfn.h: /usr/include/oracle/10.2.0.3/client/oci1.h: /usr/include/oracle/10.2.0.3/client/oro.h: /usr/include/oracle/10.2.0.3/client/ori.h: /usr/include/oracle/10.2.0.3/client/ort.h: /usr/include/oracle/10.2.0.3/client/orl.h: /usr/include/oracle/10.2.0.3/client/ociextp.h: /usr/include/oracle/10.2.0.3/client/ociapr.h: /usr/include/oracle/10.2.0.3/client/ociap.h: /usr/include/oracle/10.2.0.3/client/nzt.h: /usr/include/oracle/10.2.0.3/client/nzerror.h: /usr/include/oracle/10.2.0.3/client/ocixmldb.h: /usr/include/oracle/10.2.0.3/client/oci8dp.h: SOPE/sope-gdl1/Oracle8/obj/OracleAdaptor.d0000644000000000000000000003006115004363604017052 0ustar rootrootobj/OracleAdaptor.o: OracleAdaptor.m OracleAdaptor.h \ /usr/include/GNUstep/Foundation/Foundation.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/Foundation/FoundationErrors.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h \ /usr/include/GNUstep/Foundation/NSDebug.h \ /usr/include/GNUstep/Foundation/NSProcessInfo.h \ /usr/include/GNUstep/Foundation/NSAffineTransform.h \ /usr/include/GNUstep/Foundation/NSGeometry.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h \ /usr/include/GNUstep/Foundation/NSArchiver.h \ /usr/include/GNUstep/Foundation/NSCoder.h \ /usr/include/GNUstep/Foundation/NSArray.h \ /usr/include/GNUstep/Foundation/NSAttributedString.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/GNUstep/Foundation/NSAutoreleasePool.h \ /usr/include/GNUstep/Foundation/NSBundle.h \ /usr/include/GNUstep/Foundation/NSByteOrder.h \ /usr/include/GNUstep/Foundation/NSCalendarDate.h \ /usr/include/GNUstep/Foundation/NSCharacterSet.h \ /usr/include/GNUstep/Foundation/NSClassDescription.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/Foundation/NSComparisonPredicate.h \ /usr/include/GNUstep/Foundation/NSExpression.h \ /usr/include/GNUstep/Foundation/NSPredicate.h \ /usr/include/GNUstep/Foundation/NSCompoundPredicate.h \ /usr/include/GNUstep/Foundation/NSConnection.h \ /usr/include/GNUstep/Foundation/NSTimer.h \ /usr/include/GNUstep/Foundation/NSRunLoop.h \ /usr/include/GNUstep/Foundation/NSMapTable.h \ /usr/include/GNUstep/Foundation/NSData.h \ /usr/include/GNUstep/Foundation/NSSerialization.h \ /usr/include/GNUstep/Foundation/NSDateFormatter.h \ /usr/include/GNUstep/Foundation/NSFormatter.h \ /usr/include/GNUstep/Foundation/NSDecimalNumber.h \ /usr/include/GNUstep/Foundation/NSDecimal.h \ /usr/include/GNUstep/Foundation/NSValue.h \ /usr/include/GNUstep/Foundation/NSDistantObject.h \ /usr/include/GNUstep/Foundation/NSProxy.h \ /usr/include/GNUstep/Foundation/NSDistributedLock.h \ /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h \ /usr/include/GNUstep/Foundation/NSLock.h \ /usr/include/GNUstep/Foundation/NSNotification.h \ /usr/include/GNUstep/Foundation/NSEnumerator.h \ /usr/include/GNUstep/Foundation/NSError.h \ /usr/include/GNUstep/Foundation/NSFileHandle.h \ /usr/include/GNUstep/Foundation/NSFileManager.h \ /usr/include/GNUstep/Foundation/NSHashTable.h \ /usr/include/GNUstep/Foundation/NSHost.h \ /usr/include/GNUstep/Foundation/NSHTTPCookie.h \ /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h \ /usr/include/GNUstep/Foundation/NSIndexPath.h \ /usr/include/GNUstep/Foundation/NSIndexSet.h \ /usr/include/GNUstep/Foundation/NSInvocation.h \ /usr/include/GNUstep/Foundation/NSMethodSignature.h \ /usr/include/GNUstep/Foundation/NSKeyedArchiver.h \ /usr/include/GNUstep/Foundation/NSPropertyList.h \ /usr/include/GNUstep/Foundation/NSKeyValueCoding.h \ /usr/include/GNUstep/Foundation/NSNotificationQueue.h \ /usr/include/GNUstep/Foundation/NSNetServices.h \ /usr/include/GNUstep/Foundation/NSNull.h \ /usr/include/GNUstep/Foundation/NSNumberFormatter.h \ /usr/include/GNUstep/Foundation/NSPathUtilities.h \ /usr/include/GNUstep/Foundation/NSPortCoder.h \ /usr/include/GNUstep/Foundation/NSPortMessage.h \ /usr/include/GNUstep/Foundation/NSPort.h \ /usr/include/GNUstep/Foundation/NSPortNameServer.h \ /usr/include/GNUstep/Foundation/NSProtocolChecker.h \ /usr/include/GNUstep/Foundation/NSScanner.h \ /usr/include/GNUstep/Foundation/NSSet.h \ /usr/include/GNUstep/Foundation/NSSortDescriptor.h \ /usr/include/GNUstep/Foundation/NSSpellServer.h \ /usr/include/GNUstep/Foundation/NSStream.h \ /usr/include/GNUstep/Foundation/NSTask.h \ /usr/include/GNUstep/Foundation/NSThread.h \ /usr/include/GNUstep/Foundation/NSTimeZone.h \ /usr/include/GNUstep/Foundation/NSUndoManager.h \ /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h \ /usr/include/GNUstep/Foundation/NSURLCache.h \ /usr/include/GNUstep/Foundation/NSURLConnection.h \ /usr/include/GNUstep/Foundation/NSURLCredential.h \ /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h \ /usr/include/GNUstep/Foundation/NSURLDownload.h \ /usr/include/GNUstep/Foundation/NSURLError.h \ /usr/include/GNUstep/Foundation/NSURL.h \ /usr/include/GNUstep/Foundation/NSURLHandle.h \ /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h \ /usr/include/GNUstep/Foundation/NSURLProtocol.h \ /usr/include/GNUstep/Foundation/NSURLRequest.h \ /usr/include/GNUstep/Foundation/NSURLResponse.h \ /usr/include/GNUstep/Foundation/NSUserDefaults.h \ /usr/include/GNUstep/Foundation/NSValueTransformer.h \ /usr/include/GNUstep/Foundation/NSXMLParser.h ../GDLAccess/EOAdaptor.h \ OracleAdaptorChannel.h /usr/include/oracle/10.2.0.3/client/oci.h \ /usr/include/oracle/10.2.0.3/client/oratypes.h \ /usr/include/oracle/10.2.0.3/client/ocidfn.h \ /usr/include/oracle/10.2.0.3/client/oci1.h \ /usr/include/oracle/10.2.0.3/client/oro.h \ /usr/include/oracle/10.2.0.3/client/ori.h \ /usr/include/oracle/10.2.0.3/client/ort.h \ /usr/include/oracle/10.2.0.3/client/orl.h \ /usr/include/oracle/10.2.0.3/client/ociextp.h \ /usr/include/oracle/10.2.0.3/client/ociapr.h \ /usr/include/oracle/10.2.0.3/client/ociap.h \ /usr/include/oracle/10.2.0.3/client/nzt.h \ /usr/include/oracle/10.2.0.3/client/nzerror.h \ /usr/include/oracle/10.2.0.3/client/ocixmldb.h \ /usr/include/oracle/10.2.0.3/client/oci8dp.h \ ../GDLAccess/EOAdaptorChannel.h ../GDLAccess/EODelegateResponse.h \ OracleAdaptorContext.h ../GDLAccess/EOAdaptorContext.h \ OracleSQLExpression.h ../GDLAccess/EOSQLExpression.h \ ../GDLAccess/EOExpressionArray.h ../GDLAccess/EOJoinTypes.h \ OracleValues.h ../GDLAccess/EOAttribute.h OracleAdaptor.h: /usr/include/GNUstep/Foundation/Foundation.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/Foundation/FoundationErrors.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: /usr/include/GNUstep/Foundation/NSDebug.h: /usr/include/GNUstep/Foundation/NSProcessInfo.h: /usr/include/GNUstep/Foundation/NSAffineTransform.h: /usr/include/GNUstep/Foundation/NSGeometry.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: /usr/include/GNUstep/Foundation/NSArchiver.h: /usr/include/GNUstep/Foundation/NSCoder.h: /usr/include/GNUstep/Foundation/NSArray.h: /usr/include/GNUstep/Foundation/NSAttributedString.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/GNUstep/Foundation/NSAutoreleasePool.h: /usr/include/GNUstep/Foundation/NSBundle.h: /usr/include/GNUstep/Foundation/NSByteOrder.h: /usr/include/GNUstep/Foundation/NSCalendarDate.h: /usr/include/GNUstep/Foundation/NSCharacterSet.h: /usr/include/GNUstep/Foundation/NSClassDescription.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/Foundation/NSComparisonPredicate.h: /usr/include/GNUstep/Foundation/NSExpression.h: /usr/include/GNUstep/Foundation/NSPredicate.h: /usr/include/GNUstep/Foundation/NSCompoundPredicate.h: /usr/include/GNUstep/Foundation/NSConnection.h: /usr/include/GNUstep/Foundation/NSTimer.h: /usr/include/GNUstep/Foundation/NSRunLoop.h: /usr/include/GNUstep/Foundation/NSMapTable.h: /usr/include/GNUstep/Foundation/NSData.h: /usr/include/GNUstep/Foundation/NSSerialization.h: /usr/include/GNUstep/Foundation/NSDateFormatter.h: /usr/include/GNUstep/Foundation/NSFormatter.h: /usr/include/GNUstep/Foundation/NSDecimalNumber.h: /usr/include/GNUstep/Foundation/NSDecimal.h: /usr/include/GNUstep/Foundation/NSValue.h: /usr/include/GNUstep/Foundation/NSDistantObject.h: /usr/include/GNUstep/Foundation/NSProxy.h: /usr/include/GNUstep/Foundation/NSDistributedLock.h: /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h: /usr/include/GNUstep/Foundation/NSLock.h: /usr/include/GNUstep/Foundation/NSNotification.h: /usr/include/GNUstep/Foundation/NSEnumerator.h: /usr/include/GNUstep/Foundation/NSError.h: /usr/include/GNUstep/Foundation/NSFileHandle.h: /usr/include/GNUstep/Foundation/NSFileManager.h: /usr/include/GNUstep/Foundation/NSHashTable.h: /usr/include/GNUstep/Foundation/NSHost.h: /usr/include/GNUstep/Foundation/NSHTTPCookie.h: /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h: /usr/include/GNUstep/Foundation/NSIndexPath.h: /usr/include/GNUstep/Foundation/NSIndexSet.h: /usr/include/GNUstep/Foundation/NSInvocation.h: /usr/include/GNUstep/Foundation/NSMethodSignature.h: /usr/include/GNUstep/Foundation/NSKeyedArchiver.h: /usr/include/GNUstep/Foundation/NSPropertyList.h: /usr/include/GNUstep/Foundation/NSKeyValueCoding.h: /usr/include/GNUstep/Foundation/NSNotificationQueue.h: /usr/include/GNUstep/Foundation/NSNetServices.h: /usr/include/GNUstep/Foundation/NSNull.h: /usr/include/GNUstep/Foundation/NSNumberFormatter.h: /usr/include/GNUstep/Foundation/NSPathUtilities.h: /usr/include/GNUstep/Foundation/NSPortCoder.h: /usr/include/GNUstep/Foundation/NSPortMessage.h: /usr/include/GNUstep/Foundation/NSPort.h: /usr/include/GNUstep/Foundation/NSPortNameServer.h: /usr/include/GNUstep/Foundation/NSProtocolChecker.h: /usr/include/GNUstep/Foundation/NSScanner.h: /usr/include/GNUstep/Foundation/NSSet.h: /usr/include/GNUstep/Foundation/NSSortDescriptor.h: /usr/include/GNUstep/Foundation/NSSpellServer.h: /usr/include/GNUstep/Foundation/NSStream.h: /usr/include/GNUstep/Foundation/NSTask.h: /usr/include/GNUstep/Foundation/NSThread.h: /usr/include/GNUstep/Foundation/NSTimeZone.h: /usr/include/GNUstep/Foundation/NSUndoManager.h: /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h: /usr/include/GNUstep/Foundation/NSURLCache.h: /usr/include/GNUstep/Foundation/NSURLConnection.h: /usr/include/GNUstep/Foundation/NSURLCredential.h: /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h: /usr/include/GNUstep/Foundation/NSURLDownload.h: /usr/include/GNUstep/Foundation/NSURLError.h: /usr/include/GNUstep/Foundation/NSURL.h: /usr/include/GNUstep/Foundation/NSURLHandle.h: /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h: /usr/include/GNUstep/Foundation/NSURLProtocol.h: /usr/include/GNUstep/Foundation/NSURLRequest.h: /usr/include/GNUstep/Foundation/NSURLResponse.h: /usr/include/GNUstep/Foundation/NSUserDefaults.h: /usr/include/GNUstep/Foundation/NSValueTransformer.h: /usr/include/GNUstep/Foundation/NSXMLParser.h: ../GDLAccess/EOAdaptor.h: OracleAdaptorChannel.h: /usr/include/oracle/10.2.0.3/client/oci.h: /usr/include/oracle/10.2.0.3/client/oratypes.h: /usr/include/oracle/10.2.0.3/client/ocidfn.h: /usr/include/oracle/10.2.0.3/client/oci1.h: /usr/include/oracle/10.2.0.3/client/oro.h: /usr/include/oracle/10.2.0.3/client/ori.h: /usr/include/oracle/10.2.0.3/client/ort.h: /usr/include/oracle/10.2.0.3/client/orl.h: /usr/include/oracle/10.2.0.3/client/ociextp.h: /usr/include/oracle/10.2.0.3/client/ociapr.h: /usr/include/oracle/10.2.0.3/client/ociap.h: /usr/include/oracle/10.2.0.3/client/nzt.h: /usr/include/oracle/10.2.0.3/client/nzerror.h: /usr/include/oracle/10.2.0.3/client/ocixmldb.h: /usr/include/oracle/10.2.0.3/client/oci8dp.h: ../GDLAccess/EOAdaptorChannel.h: ../GDLAccess/EODelegateResponse.h: OracleAdaptorContext.h: ../GDLAccess/EOAdaptorContext.h: OracleSQLExpression.h: ../GDLAccess/EOSQLExpression.h: ../GDLAccess/EOExpressionArray.h: ../GDLAccess/EOJoinTypes.h: OracleValues.h: ../GDLAccess/EOAttribute.h: SOPE/sope-gdl1/Oracle8/obj/OracleAdaptorContext.d0000644000000000000000000002723315004363604020426 0ustar rootrootobj/OracleAdaptorContext.o: OracleAdaptorContext.m OracleAdaptorContext.h \ /usr/include/GNUstep/Foundation/Foundation.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/Foundation/FoundationErrors.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h \ /usr/include/GNUstep/Foundation/NSDebug.h \ /usr/include/GNUstep/Foundation/NSProcessInfo.h \ /usr/include/GNUstep/Foundation/NSAffineTransform.h \ /usr/include/GNUstep/Foundation/NSGeometry.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h \ /usr/include/GNUstep/Foundation/NSArchiver.h \ /usr/include/GNUstep/Foundation/NSCoder.h \ /usr/include/GNUstep/Foundation/NSArray.h \ /usr/include/GNUstep/Foundation/NSAttributedString.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/GNUstep/Foundation/NSAutoreleasePool.h \ /usr/include/GNUstep/Foundation/NSBundle.h \ /usr/include/GNUstep/Foundation/NSByteOrder.h \ /usr/include/GNUstep/Foundation/NSCalendarDate.h \ /usr/include/GNUstep/Foundation/NSCharacterSet.h \ /usr/include/GNUstep/Foundation/NSClassDescription.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/Foundation/NSComparisonPredicate.h \ /usr/include/GNUstep/Foundation/NSExpression.h \ /usr/include/GNUstep/Foundation/NSPredicate.h \ /usr/include/GNUstep/Foundation/NSCompoundPredicate.h \ /usr/include/GNUstep/Foundation/NSConnection.h \ /usr/include/GNUstep/Foundation/NSTimer.h \ /usr/include/GNUstep/Foundation/NSRunLoop.h \ /usr/include/GNUstep/Foundation/NSMapTable.h \ /usr/include/GNUstep/Foundation/NSData.h \ /usr/include/GNUstep/Foundation/NSSerialization.h \ /usr/include/GNUstep/Foundation/NSDateFormatter.h \ /usr/include/GNUstep/Foundation/NSFormatter.h \ /usr/include/GNUstep/Foundation/NSDecimalNumber.h \ /usr/include/GNUstep/Foundation/NSDecimal.h \ /usr/include/GNUstep/Foundation/NSValue.h \ /usr/include/GNUstep/Foundation/NSDistantObject.h \ /usr/include/GNUstep/Foundation/NSProxy.h \ /usr/include/GNUstep/Foundation/NSDistributedLock.h \ /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h \ /usr/include/GNUstep/Foundation/NSLock.h \ /usr/include/GNUstep/Foundation/NSNotification.h \ /usr/include/GNUstep/Foundation/NSEnumerator.h \ /usr/include/GNUstep/Foundation/NSError.h \ /usr/include/GNUstep/Foundation/NSFileHandle.h \ /usr/include/GNUstep/Foundation/NSFileManager.h \ /usr/include/GNUstep/Foundation/NSHashTable.h \ /usr/include/GNUstep/Foundation/NSHost.h \ /usr/include/GNUstep/Foundation/NSHTTPCookie.h \ /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h \ /usr/include/GNUstep/Foundation/NSIndexPath.h \ /usr/include/GNUstep/Foundation/NSIndexSet.h \ /usr/include/GNUstep/Foundation/NSInvocation.h \ /usr/include/GNUstep/Foundation/NSMethodSignature.h \ /usr/include/GNUstep/Foundation/NSKeyedArchiver.h \ /usr/include/GNUstep/Foundation/NSPropertyList.h \ /usr/include/GNUstep/Foundation/NSKeyValueCoding.h \ /usr/include/GNUstep/Foundation/NSNotificationQueue.h \ /usr/include/GNUstep/Foundation/NSNetServices.h \ /usr/include/GNUstep/Foundation/NSNull.h \ /usr/include/GNUstep/Foundation/NSNumberFormatter.h \ /usr/include/GNUstep/Foundation/NSPathUtilities.h \ /usr/include/GNUstep/Foundation/NSPortCoder.h \ /usr/include/GNUstep/Foundation/NSPortMessage.h \ /usr/include/GNUstep/Foundation/NSPort.h \ /usr/include/GNUstep/Foundation/NSPortNameServer.h \ /usr/include/GNUstep/Foundation/NSProtocolChecker.h \ /usr/include/GNUstep/Foundation/NSScanner.h \ /usr/include/GNUstep/Foundation/NSSet.h \ /usr/include/GNUstep/Foundation/NSSortDescriptor.h \ /usr/include/GNUstep/Foundation/NSSpellServer.h \ /usr/include/GNUstep/Foundation/NSStream.h \ /usr/include/GNUstep/Foundation/NSTask.h \ /usr/include/GNUstep/Foundation/NSThread.h \ /usr/include/GNUstep/Foundation/NSTimeZone.h \ /usr/include/GNUstep/Foundation/NSUndoManager.h \ /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h \ /usr/include/GNUstep/Foundation/NSURLCache.h \ /usr/include/GNUstep/Foundation/NSURLConnection.h \ /usr/include/GNUstep/Foundation/NSURLCredential.h \ /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h \ /usr/include/GNUstep/Foundation/NSURLDownload.h \ /usr/include/GNUstep/Foundation/NSURLError.h \ /usr/include/GNUstep/Foundation/NSURL.h \ /usr/include/GNUstep/Foundation/NSURLHandle.h \ /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h \ /usr/include/GNUstep/Foundation/NSURLProtocol.h \ /usr/include/GNUstep/Foundation/NSURLRequest.h \ /usr/include/GNUstep/Foundation/NSURLResponse.h \ /usr/include/GNUstep/Foundation/NSUserDefaults.h \ /usr/include/GNUstep/Foundation/NSValueTransformer.h \ /usr/include/GNUstep/Foundation/NSXMLParser.h \ ../GDLAccess/EOAdaptorContext.h ../GDLAccess/EODelegateResponse.h \ OracleAdaptorChannel.h /usr/include/oracle/10.2.0.3/client/oci.h \ /usr/include/oracle/10.2.0.3/client/oratypes.h \ /usr/include/oracle/10.2.0.3/client/ocidfn.h \ /usr/include/oracle/10.2.0.3/client/oci1.h \ /usr/include/oracle/10.2.0.3/client/oro.h \ /usr/include/oracle/10.2.0.3/client/ori.h \ /usr/include/oracle/10.2.0.3/client/ort.h \ /usr/include/oracle/10.2.0.3/client/orl.h \ /usr/include/oracle/10.2.0.3/client/ociextp.h \ /usr/include/oracle/10.2.0.3/client/ociapr.h \ /usr/include/oracle/10.2.0.3/client/ociap.h \ /usr/include/oracle/10.2.0.3/client/nzt.h \ /usr/include/oracle/10.2.0.3/client/nzerror.h \ /usr/include/oracle/10.2.0.3/client/ocixmldb.h \ /usr/include/oracle/10.2.0.3/client/oci8dp.h \ ../GDLAccess/EOAdaptorChannel.h OracleAdaptorContext.h: /usr/include/GNUstep/Foundation/Foundation.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/Foundation/FoundationErrors.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: /usr/include/GNUstep/Foundation/NSDebug.h: /usr/include/GNUstep/Foundation/NSProcessInfo.h: /usr/include/GNUstep/Foundation/NSAffineTransform.h: /usr/include/GNUstep/Foundation/NSGeometry.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: /usr/include/GNUstep/Foundation/NSArchiver.h: /usr/include/GNUstep/Foundation/NSCoder.h: /usr/include/GNUstep/Foundation/NSArray.h: /usr/include/GNUstep/Foundation/NSAttributedString.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/GNUstep/Foundation/NSAutoreleasePool.h: /usr/include/GNUstep/Foundation/NSBundle.h: /usr/include/GNUstep/Foundation/NSByteOrder.h: /usr/include/GNUstep/Foundation/NSCalendarDate.h: /usr/include/GNUstep/Foundation/NSCharacterSet.h: /usr/include/GNUstep/Foundation/NSClassDescription.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/Foundation/NSComparisonPredicate.h: /usr/include/GNUstep/Foundation/NSExpression.h: /usr/include/GNUstep/Foundation/NSPredicate.h: /usr/include/GNUstep/Foundation/NSCompoundPredicate.h: /usr/include/GNUstep/Foundation/NSConnection.h: /usr/include/GNUstep/Foundation/NSTimer.h: /usr/include/GNUstep/Foundation/NSRunLoop.h: /usr/include/GNUstep/Foundation/NSMapTable.h: /usr/include/GNUstep/Foundation/NSData.h: /usr/include/GNUstep/Foundation/NSSerialization.h: /usr/include/GNUstep/Foundation/NSDateFormatter.h: /usr/include/GNUstep/Foundation/NSFormatter.h: /usr/include/GNUstep/Foundation/NSDecimalNumber.h: /usr/include/GNUstep/Foundation/NSDecimal.h: /usr/include/GNUstep/Foundation/NSValue.h: /usr/include/GNUstep/Foundation/NSDistantObject.h: /usr/include/GNUstep/Foundation/NSProxy.h: /usr/include/GNUstep/Foundation/NSDistributedLock.h: /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h: /usr/include/GNUstep/Foundation/NSLock.h: /usr/include/GNUstep/Foundation/NSNotification.h: /usr/include/GNUstep/Foundation/NSEnumerator.h: /usr/include/GNUstep/Foundation/NSError.h: /usr/include/GNUstep/Foundation/NSFileHandle.h: /usr/include/GNUstep/Foundation/NSFileManager.h: /usr/include/GNUstep/Foundation/NSHashTable.h: /usr/include/GNUstep/Foundation/NSHost.h: /usr/include/GNUstep/Foundation/NSHTTPCookie.h: /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h: /usr/include/GNUstep/Foundation/NSIndexPath.h: /usr/include/GNUstep/Foundation/NSIndexSet.h: /usr/include/GNUstep/Foundation/NSInvocation.h: /usr/include/GNUstep/Foundation/NSMethodSignature.h: /usr/include/GNUstep/Foundation/NSKeyedArchiver.h: /usr/include/GNUstep/Foundation/NSPropertyList.h: /usr/include/GNUstep/Foundation/NSKeyValueCoding.h: /usr/include/GNUstep/Foundation/NSNotificationQueue.h: /usr/include/GNUstep/Foundation/NSNetServices.h: /usr/include/GNUstep/Foundation/NSNull.h: /usr/include/GNUstep/Foundation/NSNumberFormatter.h: /usr/include/GNUstep/Foundation/NSPathUtilities.h: /usr/include/GNUstep/Foundation/NSPortCoder.h: /usr/include/GNUstep/Foundation/NSPortMessage.h: /usr/include/GNUstep/Foundation/NSPort.h: /usr/include/GNUstep/Foundation/NSPortNameServer.h: /usr/include/GNUstep/Foundation/NSProtocolChecker.h: /usr/include/GNUstep/Foundation/NSScanner.h: /usr/include/GNUstep/Foundation/NSSet.h: /usr/include/GNUstep/Foundation/NSSortDescriptor.h: /usr/include/GNUstep/Foundation/NSSpellServer.h: /usr/include/GNUstep/Foundation/NSStream.h: /usr/include/GNUstep/Foundation/NSTask.h: /usr/include/GNUstep/Foundation/NSThread.h: /usr/include/GNUstep/Foundation/NSTimeZone.h: /usr/include/GNUstep/Foundation/NSUndoManager.h: /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h: /usr/include/GNUstep/Foundation/NSURLCache.h: /usr/include/GNUstep/Foundation/NSURLConnection.h: /usr/include/GNUstep/Foundation/NSURLCredential.h: /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h: /usr/include/GNUstep/Foundation/NSURLDownload.h: /usr/include/GNUstep/Foundation/NSURLError.h: /usr/include/GNUstep/Foundation/NSURL.h: /usr/include/GNUstep/Foundation/NSURLHandle.h: /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h: /usr/include/GNUstep/Foundation/NSURLProtocol.h: /usr/include/GNUstep/Foundation/NSURLRequest.h: /usr/include/GNUstep/Foundation/NSURLResponse.h: /usr/include/GNUstep/Foundation/NSUserDefaults.h: /usr/include/GNUstep/Foundation/NSValueTransformer.h: /usr/include/GNUstep/Foundation/NSXMLParser.h: ../GDLAccess/EOAdaptorContext.h: ../GDLAccess/EODelegateResponse.h: OracleAdaptorChannel.h: /usr/include/oracle/10.2.0.3/client/oci.h: /usr/include/oracle/10.2.0.3/client/oratypes.h: /usr/include/oracle/10.2.0.3/client/ocidfn.h: /usr/include/oracle/10.2.0.3/client/oci1.h: /usr/include/oracle/10.2.0.3/client/oro.h: /usr/include/oracle/10.2.0.3/client/ori.h: /usr/include/oracle/10.2.0.3/client/ort.h: /usr/include/oracle/10.2.0.3/client/orl.h: /usr/include/oracle/10.2.0.3/client/ociextp.h: /usr/include/oracle/10.2.0.3/client/ociapr.h: /usr/include/oracle/10.2.0.3/client/ociap.h: /usr/include/oracle/10.2.0.3/client/nzt.h: /usr/include/oracle/10.2.0.3/client/nzerror.h: /usr/include/oracle/10.2.0.3/client/ocixmldb.h: /usr/include/oracle/10.2.0.3/client/oci8dp.h: ../GDLAccess/EOAdaptorChannel.h: SOPE/sope-gdl1/Oracle8/obj/OracleAdaptorChannel.d0000644000000000000000000003042715004363604020351 0ustar rootrootobj/OracleAdaptorChannel.o: OracleAdaptorChannel.m OracleAdaptorChannel.h \ /usr/include/oracle/10.2.0.3/client/oci.h \ /usr/include/oracle/10.2.0.3/client/oratypes.h \ /usr/include/oracle/10.2.0.3/client/ocidfn.h \ /usr/include/oracle/10.2.0.3/client/oci1.h \ /usr/include/oracle/10.2.0.3/client/oro.h \ /usr/include/oracle/10.2.0.3/client/ori.h \ /usr/include/oracle/10.2.0.3/client/ort.h \ /usr/include/oracle/10.2.0.3/client/orl.h \ /usr/include/oracle/10.2.0.3/client/ociextp.h \ /usr/include/oracle/10.2.0.3/client/ociapr.h \ /usr/include/oracle/10.2.0.3/client/ociap.h \ /usr/include/oracle/10.2.0.3/client/nzt.h \ /usr/include/oracle/10.2.0.3/client/nzerror.h \ /usr/include/oracle/10.2.0.3/client/ocixmldb.h \ /usr/include/oracle/10.2.0.3/client/oci8dp.h \ ../GDLAccess/EOAdaptorChannel.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h \ ../GDLAccess/EODelegateResponse.h err.h OracleAdaptor.h \ /usr/include/GNUstep/Foundation/Foundation.h \ /usr/include/GNUstep/Foundation/FoundationErrors.h \ /usr/include/GNUstep/Foundation/NSDebug.h \ /usr/include/GNUstep/Foundation/NSProcessInfo.h \ /usr/include/GNUstep/Foundation/NSAffineTransform.h \ /usr/include/GNUstep/Foundation/NSGeometry.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h \ /usr/include/GNUstep/Foundation/NSArchiver.h \ /usr/include/GNUstep/Foundation/NSCoder.h \ /usr/include/GNUstep/Foundation/NSArray.h \ /usr/include/GNUstep/Foundation/NSAttributedString.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/GNUstep/Foundation/NSAutoreleasePool.h \ /usr/include/GNUstep/Foundation/NSBundle.h \ /usr/include/GNUstep/Foundation/NSByteOrder.h \ /usr/include/GNUstep/Foundation/NSCalendarDate.h \ /usr/include/GNUstep/Foundation/NSCharacterSet.h \ /usr/include/GNUstep/Foundation/NSClassDescription.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/Foundation/NSComparisonPredicate.h \ /usr/include/GNUstep/Foundation/NSExpression.h \ /usr/include/GNUstep/Foundation/NSPredicate.h \ /usr/include/GNUstep/Foundation/NSCompoundPredicate.h \ /usr/include/GNUstep/Foundation/NSConnection.h \ /usr/include/GNUstep/Foundation/NSTimer.h \ /usr/include/GNUstep/Foundation/NSRunLoop.h \ /usr/include/GNUstep/Foundation/NSMapTable.h \ /usr/include/GNUstep/Foundation/NSData.h \ /usr/include/GNUstep/Foundation/NSSerialization.h \ /usr/include/GNUstep/Foundation/NSDateFormatter.h \ /usr/include/GNUstep/Foundation/NSFormatter.h \ /usr/include/GNUstep/Foundation/NSDecimalNumber.h \ /usr/include/GNUstep/Foundation/NSDecimal.h \ /usr/include/GNUstep/Foundation/NSValue.h \ /usr/include/GNUstep/Foundation/NSDistantObject.h \ /usr/include/GNUstep/Foundation/NSProxy.h \ /usr/include/GNUstep/Foundation/NSDistributedLock.h \ /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h \ /usr/include/GNUstep/Foundation/NSLock.h \ /usr/include/GNUstep/Foundation/NSNotification.h \ /usr/include/GNUstep/Foundation/NSEnumerator.h \ /usr/include/GNUstep/Foundation/NSError.h \ /usr/include/GNUstep/Foundation/NSFileHandle.h \ /usr/include/GNUstep/Foundation/NSFileManager.h \ /usr/include/GNUstep/Foundation/NSHashTable.h \ /usr/include/GNUstep/Foundation/NSHost.h \ /usr/include/GNUstep/Foundation/NSHTTPCookie.h \ /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h \ /usr/include/GNUstep/Foundation/NSIndexPath.h \ /usr/include/GNUstep/Foundation/NSIndexSet.h \ /usr/include/GNUstep/Foundation/NSInvocation.h \ /usr/include/GNUstep/Foundation/NSMethodSignature.h \ /usr/include/GNUstep/Foundation/NSKeyedArchiver.h \ /usr/include/GNUstep/Foundation/NSPropertyList.h \ /usr/include/GNUstep/Foundation/NSKeyValueCoding.h \ /usr/include/GNUstep/Foundation/NSNotificationQueue.h \ /usr/include/GNUstep/Foundation/NSNetServices.h \ /usr/include/GNUstep/Foundation/NSNull.h \ /usr/include/GNUstep/Foundation/NSNumberFormatter.h \ /usr/include/GNUstep/Foundation/NSPathUtilities.h \ /usr/include/GNUstep/Foundation/NSPortCoder.h \ /usr/include/GNUstep/Foundation/NSPortMessage.h \ /usr/include/GNUstep/Foundation/NSPort.h \ /usr/include/GNUstep/Foundation/NSPortNameServer.h \ /usr/include/GNUstep/Foundation/NSProtocolChecker.h \ /usr/include/GNUstep/Foundation/NSScanner.h \ /usr/include/GNUstep/Foundation/NSSet.h \ /usr/include/GNUstep/Foundation/NSSortDescriptor.h \ /usr/include/GNUstep/Foundation/NSSpellServer.h \ /usr/include/GNUstep/Foundation/NSStream.h \ /usr/include/GNUstep/Foundation/NSTask.h \ /usr/include/GNUstep/Foundation/NSThread.h \ /usr/include/GNUstep/Foundation/NSTimeZone.h \ /usr/include/GNUstep/Foundation/NSUndoManager.h \ /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h \ /usr/include/GNUstep/Foundation/NSURLCache.h \ /usr/include/GNUstep/Foundation/NSURLConnection.h \ /usr/include/GNUstep/Foundation/NSURLCredential.h \ /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h \ /usr/include/GNUstep/Foundation/NSURLDownload.h \ /usr/include/GNUstep/Foundation/NSURLError.h \ /usr/include/GNUstep/Foundation/NSURL.h \ /usr/include/GNUstep/Foundation/NSURLHandle.h \ /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h \ /usr/include/GNUstep/Foundation/NSURLProtocol.h \ /usr/include/GNUstep/Foundation/NSURLRequest.h \ /usr/include/GNUstep/Foundation/NSURLResponse.h \ /usr/include/GNUstep/Foundation/NSUserDefaults.h \ /usr/include/GNUstep/Foundation/NSValueTransformer.h \ /usr/include/GNUstep/Foundation/NSXMLParser.h ../GDLAccess/EOAdaptor.h \ OracleAdaptorChannelController.h ../GDLAccess/EOEntity.h \ ../../sope-core/EOControl/EOClassDescription.h \ ../../sope-core/EOControl/EOGlobalID.h OracleAdaptorContext.h \ ../GDLAccess/EOAdaptorContext.h EOAttribute+Oracle.h \ ../GDLAccess/EOAttribute.h \ ../../sope-core/NGExtensions/NGExtensions/NSObject+Logs.h OracleAdaptorChannel.h: /usr/include/oracle/10.2.0.3/client/oci.h: /usr/include/oracle/10.2.0.3/client/oratypes.h: /usr/include/oracle/10.2.0.3/client/ocidfn.h: /usr/include/oracle/10.2.0.3/client/oci1.h: /usr/include/oracle/10.2.0.3/client/oro.h: /usr/include/oracle/10.2.0.3/client/ori.h: /usr/include/oracle/10.2.0.3/client/ort.h: /usr/include/oracle/10.2.0.3/client/orl.h: /usr/include/oracle/10.2.0.3/client/ociextp.h: /usr/include/oracle/10.2.0.3/client/ociapr.h: /usr/include/oracle/10.2.0.3/client/ociap.h: /usr/include/oracle/10.2.0.3/client/nzt.h: /usr/include/oracle/10.2.0.3/client/nzerror.h: /usr/include/oracle/10.2.0.3/client/ocixmldb.h: /usr/include/oracle/10.2.0.3/client/oci8dp.h: ../GDLAccess/EOAdaptorChannel.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: ../GDLAccess/EODelegateResponse.h: err.h: OracleAdaptor.h: /usr/include/GNUstep/Foundation/Foundation.h: /usr/include/GNUstep/Foundation/FoundationErrors.h: /usr/include/GNUstep/Foundation/NSDebug.h: /usr/include/GNUstep/Foundation/NSProcessInfo.h: /usr/include/GNUstep/Foundation/NSAffineTransform.h: /usr/include/GNUstep/Foundation/NSGeometry.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: /usr/include/GNUstep/Foundation/NSArchiver.h: /usr/include/GNUstep/Foundation/NSCoder.h: /usr/include/GNUstep/Foundation/NSArray.h: /usr/include/GNUstep/Foundation/NSAttributedString.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/GNUstep/Foundation/NSAutoreleasePool.h: /usr/include/GNUstep/Foundation/NSBundle.h: /usr/include/GNUstep/Foundation/NSByteOrder.h: /usr/include/GNUstep/Foundation/NSCalendarDate.h: /usr/include/GNUstep/Foundation/NSCharacterSet.h: /usr/include/GNUstep/Foundation/NSClassDescription.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/Foundation/NSComparisonPredicate.h: /usr/include/GNUstep/Foundation/NSExpression.h: /usr/include/GNUstep/Foundation/NSPredicate.h: /usr/include/GNUstep/Foundation/NSCompoundPredicate.h: /usr/include/GNUstep/Foundation/NSConnection.h: /usr/include/GNUstep/Foundation/NSTimer.h: /usr/include/GNUstep/Foundation/NSRunLoop.h: /usr/include/GNUstep/Foundation/NSMapTable.h: /usr/include/GNUstep/Foundation/NSData.h: /usr/include/GNUstep/Foundation/NSSerialization.h: /usr/include/GNUstep/Foundation/NSDateFormatter.h: /usr/include/GNUstep/Foundation/NSFormatter.h: /usr/include/GNUstep/Foundation/NSDecimalNumber.h: /usr/include/GNUstep/Foundation/NSDecimal.h: /usr/include/GNUstep/Foundation/NSValue.h: /usr/include/GNUstep/Foundation/NSDistantObject.h: /usr/include/GNUstep/Foundation/NSProxy.h: /usr/include/GNUstep/Foundation/NSDistributedLock.h: /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h: /usr/include/GNUstep/Foundation/NSLock.h: /usr/include/GNUstep/Foundation/NSNotification.h: /usr/include/GNUstep/Foundation/NSEnumerator.h: /usr/include/GNUstep/Foundation/NSError.h: /usr/include/GNUstep/Foundation/NSFileHandle.h: /usr/include/GNUstep/Foundation/NSFileManager.h: /usr/include/GNUstep/Foundation/NSHashTable.h: /usr/include/GNUstep/Foundation/NSHost.h: /usr/include/GNUstep/Foundation/NSHTTPCookie.h: /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h: /usr/include/GNUstep/Foundation/NSIndexPath.h: /usr/include/GNUstep/Foundation/NSIndexSet.h: /usr/include/GNUstep/Foundation/NSInvocation.h: /usr/include/GNUstep/Foundation/NSMethodSignature.h: /usr/include/GNUstep/Foundation/NSKeyedArchiver.h: /usr/include/GNUstep/Foundation/NSPropertyList.h: /usr/include/GNUstep/Foundation/NSKeyValueCoding.h: /usr/include/GNUstep/Foundation/NSNotificationQueue.h: /usr/include/GNUstep/Foundation/NSNetServices.h: /usr/include/GNUstep/Foundation/NSNull.h: /usr/include/GNUstep/Foundation/NSNumberFormatter.h: /usr/include/GNUstep/Foundation/NSPathUtilities.h: /usr/include/GNUstep/Foundation/NSPortCoder.h: /usr/include/GNUstep/Foundation/NSPortMessage.h: /usr/include/GNUstep/Foundation/NSPort.h: /usr/include/GNUstep/Foundation/NSPortNameServer.h: /usr/include/GNUstep/Foundation/NSProtocolChecker.h: /usr/include/GNUstep/Foundation/NSScanner.h: /usr/include/GNUstep/Foundation/NSSet.h: /usr/include/GNUstep/Foundation/NSSortDescriptor.h: /usr/include/GNUstep/Foundation/NSSpellServer.h: /usr/include/GNUstep/Foundation/NSStream.h: /usr/include/GNUstep/Foundation/NSTask.h: /usr/include/GNUstep/Foundation/NSThread.h: /usr/include/GNUstep/Foundation/NSTimeZone.h: /usr/include/GNUstep/Foundation/NSUndoManager.h: /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h: /usr/include/GNUstep/Foundation/NSURLCache.h: /usr/include/GNUstep/Foundation/NSURLConnection.h: /usr/include/GNUstep/Foundation/NSURLCredential.h: /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h: /usr/include/GNUstep/Foundation/NSURLDownload.h: /usr/include/GNUstep/Foundation/NSURLError.h: /usr/include/GNUstep/Foundation/NSURL.h: /usr/include/GNUstep/Foundation/NSURLHandle.h: /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h: /usr/include/GNUstep/Foundation/NSURLProtocol.h: /usr/include/GNUstep/Foundation/NSURLRequest.h: /usr/include/GNUstep/Foundation/NSURLResponse.h: /usr/include/GNUstep/Foundation/NSUserDefaults.h: /usr/include/GNUstep/Foundation/NSValueTransformer.h: /usr/include/GNUstep/Foundation/NSXMLParser.h: ../GDLAccess/EOAdaptor.h: OracleAdaptorChannelController.h: ../GDLAccess/EOEntity.h: ../../sope-core/EOControl/EOClassDescription.h: ../../sope-core/EOControl/EOGlobalID.h: OracleAdaptorContext.h: ../GDLAccess/EOAdaptorContext.h: EOAttribute+Oracle.h: ../GDLAccess/EOAttribute.h: ../../sope-core/NGExtensions/NGExtensions/NSObject+Logs.h: SOPE/sope-gdl1/Oracle8/obj/OracleSQLExpression.d0000644000000000000000000002432715004363604020207 0ustar rootrootobj/OracleSQLExpression.o: OracleSQLExpression.m OracleSQLExpression.h \ /usr/include/GNUstep/Foundation/Foundation.h \ /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h \ /usr/include/GNUstep/Foundation/FoundationErrors.h \ /usr/include/GNUstep/Foundation/NSObject.h \ /usr/include/GNUstep/Foundation/NSObjCRuntime.h \ /usr/include/GNUstep/GNUstepBase/preface.h \ /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h \ /usr/include/GNUstep/GNUstepBase/GSConfig.h \ /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h \ /usr/include/GNUstep/Foundation/NSZone.h \ /usr/include/GNUstep/GNUstepBase/GNUstep.h \ /usr/include/GNUstep/Foundation/NSDate.h \ /usr/include/GNUstep/Foundation/NSDebug.h \ /usr/include/GNUstep/Foundation/NSProcessInfo.h \ /usr/include/GNUstep/Foundation/NSAffineTransform.h \ /usr/include/GNUstep/Foundation/NSGeometry.h \ /usr/include/GNUstep/Foundation/NSString.h \ /usr/include/GNUstep/Foundation/NSRange.h \ /usr/include/GNUstep/Foundation/NSArchiver.h \ /usr/include/GNUstep/Foundation/NSCoder.h \ /usr/include/GNUstep/Foundation/NSArray.h \ /usr/include/GNUstep/Foundation/NSAttributedString.h \ /usr/include/GNUstep/Foundation/NSDictionary.h \ /usr/include/GNUstep/Foundation/NSAutoreleasePool.h \ /usr/include/GNUstep/Foundation/NSBundle.h \ /usr/include/GNUstep/Foundation/NSByteOrder.h \ /usr/include/GNUstep/Foundation/NSCalendarDate.h \ /usr/include/GNUstep/Foundation/NSCharacterSet.h \ /usr/include/GNUstep/Foundation/NSClassDescription.h \ /usr/include/GNUstep/Foundation/NSException.h \ /usr/include/GNUstep/Foundation/NSComparisonPredicate.h \ /usr/include/GNUstep/Foundation/NSExpression.h \ /usr/include/GNUstep/Foundation/NSPredicate.h \ /usr/include/GNUstep/Foundation/NSCompoundPredicate.h \ /usr/include/GNUstep/Foundation/NSConnection.h \ /usr/include/GNUstep/Foundation/NSTimer.h \ /usr/include/GNUstep/Foundation/NSRunLoop.h \ /usr/include/GNUstep/Foundation/NSMapTable.h \ /usr/include/GNUstep/Foundation/NSData.h \ /usr/include/GNUstep/Foundation/NSSerialization.h \ /usr/include/GNUstep/Foundation/NSDateFormatter.h \ /usr/include/GNUstep/Foundation/NSFormatter.h \ /usr/include/GNUstep/Foundation/NSDecimalNumber.h \ /usr/include/GNUstep/Foundation/NSDecimal.h \ /usr/include/GNUstep/Foundation/NSValue.h \ /usr/include/GNUstep/Foundation/NSDistantObject.h \ /usr/include/GNUstep/Foundation/NSProxy.h \ /usr/include/GNUstep/Foundation/NSDistributedLock.h \ /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h \ /usr/include/GNUstep/Foundation/NSLock.h \ /usr/include/GNUstep/Foundation/NSNotification.h \ /usr/include/GNUstep/Foundation/NSEnumerator.h \ /usr/include/GNUstep/Foundation/NSError.h \ /usr/include/GNUstep/Foundation/NSFileHandle.h \ /usr/include/GNUstep/Foundation/NSFileManager.h \ /usr/include/GNUstep/Foundation/NSHashTable.h \ /usr/include/GNUstep/Foundation/NSHost.h \ /usr/include/GNUstep/Foundation/NSHTTPCookie.h \ /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h \ /usr/include/GNUstep/Foundation/NSIndexPath.h \ /usr/include/GNUstep/Foundation/NSIndexSet.h \ /usr/include/GNUstep/Foundation/NSInvocation.h \ /usr/include/GNUstep/Foundation/NSMethodSignature.h \ /usr/include/GNUstep/Foundation/NSKeyedArchiver.h \ /usr/include/GNUstep/Foundation/NSPropertyList.h \ /usr/include/GNUstep/Foundation/NSKeyValueCoding.h \ /usr/include/GNUstep/Foundation/NSNotificationQueue.h \ /usr/include/GNUstep/Foundation/NSNetServices.h \ /usr/include/GNUstep/Foundation/NSNull.h \ /usr/include/GNUstep/Foundation/NSNumberFormatter.h \ /usr/include/GNUstep/Foundation/NSPathUtilities.h \ /usr/include/GNUstep/Foundation/NSPortCoder.h \ /usr/include/GNUstep/Foundation/NSPortMessage.h \ /usr/include/GNUstep/Foundation/NSPort.h \ /usr/include/GNUstep/Foundation/NSPortNameServer.h \ /usr/include/GNUstep/Foundation/NSProtocolChecker.h \ /usr/include/GNUstep/Foundation/NSScanner.h \ /usr/include/GNUstep/Foundation/NSSet.h \ /usr/include/GNUstep/Foundation/NSSortDescriptor.h \ /usr/include/GNUstep/Foundation/NSSpellServer.h \ /usr/include/GNUstep/Foundation/NSStream.h \ /usr/include/GNUstep/Foundation/NSTask.h \ /usr/include/GNUstep/Foundation/NSThread.h \ /usr/include/GNUstep/Foundation/NSTimeZone.h \ /usr/include/GNUstep/Foundation/NSUndoManager.h \ /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h \ /usr/include/GNUstep/Foundation/NSURLCache.h \ /usr/include/GNUstep/Foundation/NSURLConnection.h \ /usr/include/GNUstep/Foundation/NSURLCredential.h \ /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h \ /usr/include/GNUstep/Foundation/NSURLDownload.h \ /usr/include/GNUstep/Foundation/NSURLError.h \ /usr/include/GNUstep/Foundation/NSURL.h \ /usr/include/GNUstep/Foundation/NSURLHandle.h \ /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h \ /usr/include/GNUstep/Foundation/NSURLProtocol.h \ /usr/include/GNUstep/Foundation/NSURLRequest.h \ /usr/include/GNUstep/Foundation/NSURLResponse.h \ /usr/include/GNUstep/Foundation/NSUserDefaults.h \ /usr/include/GNUstep/Foundation/NSValueTransformer.h \ /usr/include/GNUstep/Foundation/NSXMLParser.h \ ../GDLAccess/EOSQLExpression.h ../GDLAccess/EOExpressionArray.h \ ../GDLAccess/EOJoinTypes.h OracleSQLExpression.h: /usr/include/GNUstep/Foundation/Foundation.h: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h: /usr/include/GNUstep/Foundation/FoundationErrors.h: /usr/include/GNUstep/Foundation/NSObject.h: /usr/include/GNUstep/Foundation/NSObjCRuntime.h: /usr/include/GNUstep/GNUstepBase/preface.h: /usr/include/GNUstep/GNUstepBase/objc-gnu2next.h: /usr/include/GNUstep/GNUstepBase/GSConfig.h: /usr/include/GNUstep/GNUstepBase/GSObjCRuntime.h: /usr/include/GNUstep/Foundation/NSZone.h: /usr/include/GNUstep/GNUstepBase/GNUstep.h: /usr/include/GNUstep/Foundation/NSDate.h: /usr/include/GNUstep/Foundation/NSDebug.h: /usr/include/GNUstep/Foundation/NSProcessInfo.h: /usr/include/GNUstep/Foundation/NSAffineTransform.h: /usr/include/GNUstep/Foundation/NSGeometry.h: /usr/include/GNUstep/Foundation/NSString.h: /usr/include/GNUstep/Foundation/NSRange.h: /usr/include/GNUstep/Foundation/NSArchiver.h: /usr/include/GNUstep/Foundation/NSCoder.h: /usr/include/GNUstep/Foundation/NSArray.h: /usr/include/GNUstep/Foundation/NSAttributedString.h: /usr/include/GNUstep/Foundation/NSDictionary.h: /usr/include/GNUstep/Foundation/NSAutoreleasePool.h: /usr/include/GNUstep/Foundation/NSBundle.h: /usr/include/GNUstep/Foundation/NSByteOrder.h: /usr/include/GNUstep/Foundation/NSCalendarDate.h: /usr/include/GNUstep/Foundation/NSCharacterSet.h: /usr/include/GNUstep/Foundation/NSClassDescription.h: /usr/include/GNUstep/Foundation/NSException.h: /usr/include/GNUstep/Foundation/NSComparisonPredicate.h: /usr/include/GNUstep/Foundation/NSExpression.h: /usr/include/GNUstep/Foundation/NSPredicate.h: /usr/include/GNUstep/Foundation/NSCompoundPredicate.h: /usr/include/GNUstep/Foundation/NSConnection.h: /usr/include/GNUstep/Foundation/NSTimer.h: /usr/include/GNUstep/Foundation/NSRunLoop.h: /usr/include/GNUstep/Foundation/NSMapTable.h: /usr/include/GNUstep/Foundation/NSData.h: /usr/include/GNUstep/Foundation/NSSerialization.h: /usr/include/GNUstep/Foundation/NSDateFormatter.h: /usr/include/GNUstep/Foundation/NSFormatter.h: /usr/include/GNUstep/Foundation/NSDecimalNumber.h: /usr/include/GNUstep/Foundation/NSDecimal.h: /usr/include/GNUstep/Foundation/NSValue.h: /usr/include/GNUstep/Foundation/NSDistantObject.h: /usr/include/GNUstep/Foundation/NSProxy.h: /usr/include/GNUstep/Foundation/NSDistributedLock.h: /usr/include/GNUstep/Foundation/NSDistributedNotificationCenter.h: /usr/include/GNUstep/Foundation/NSLock.h: /usr/include/GNUstep/Foundation/NSNotification.h: /usr/include/GNUstep/Foundation/NSEnumerator.h: /usr/include/GNUstep/Foundation/NSError.h: /usr/include/GNUstep/Foundation/NSFileHandle.h: /usr/include/GNUstep/Foundation/NSFileManager.h: /usr/include/GNUstep/Foundation/NSHashTable.h: /usr/include/GNUstep/Foundation/NSHost.h: /usr/include/GNUstep/Foundation/NSHTTPCookie.h: /usr/include/GNUstep/Foundation/NSHTTPCookieStorage.h: /usr/include/GNUstep/Foundation/NSIndexPath.h: /usr/include/GNUstep/Foundation/NSIndexSet.h: /usr/include/GNUstep/Foundation/NSInvocation.h: /usr/include/GNUstep/Foundation/NSMethodSignature.h: /usr/include/GNUstep/Foundation/NSKeyedArchiver.h: /usr/include/GNUstep/Foundation/NSPropertyList.h: /usr/include/GNUstep/Foundation/NSKeyValueCoding.h: /usr/include/GNUstep/Foundation/NSNotificationQueue.h: /usr/include/GNUstep/Foundation/NSNetServices.h: /usr/include/GNUstep/Foundation/NSNull.h: /usr/include/GNUstep/Foundation/NSNumberFormatter.h: /usr/include/GNUstep/Foundation/NSPathUtilities.h: /usr/include/GNUstep/Foundation/NSPortCoder.h: /usr/include/GNUstep/Foundation/NSPortMessage.h: /usr/include/GNUstep/Foundation/NSPort.h: /usr/include/GNUstep/Foundation/NSPortNameServer.h: /usr/include/GNUstep/Foundation/NSProtocolChecker.h: /usr/include/GNUstep/Foundation/NSScanner.h: /usr/include/GNUstep/Foundation/NSSet.h: /usr/include/GNUstep/Foundation/NSSortDescriptor.h: /usr/include/GNUstep/Foundation/NSSpellServer.h: /usr/include/GNUstep/Foundation/NSStream.h: /usr/include/GNUstep/Foundation/NSTask.h: /usr/include/GNUstep/Foundation/NSThread.h: /usr/include/GNUstep/Foundation/NSTimeZone.h: /usr/include/GNUstep/Foundation/NSUndoManager.h: /usr/include/GNUstep/Foundation/NSURLAuthenticationChallenge.h: /usr/include/GNUstep/Foundation/NSURLCache.h: /usr/include/GNUstep/Foundation/NSURLConnection.h: /usr/include/GNUstep/Foundation/NSURLCredential.h: /usr/include/GNUstep/Foundation/NSURLCredentialStorage.h: /usr/include/GNUstep/Foundation/NSURLDownload.h: /usr/include/GNUstep/Foundation/NSURLError.h: /usr/include/GNUstep/Foundation/NSURL.h: /usr/include/GNUstep/Foundation/NSURLHandle.h: /usr/include/GNUstep/Foundation/NSURLProtectionSpace.h: /usr/include/GNUstep/Foundation/NSURLProtocol.h: /usr/include/GNUstep/Foundation/NSURLRequest.h: /usr/include/GNUstep/Foundation/NSURLResponse.h: /usr/include/GNUstep/Foundation/NSUserDefaults.h: /usr/include/GNUstep/Foundation/NSValueTransformer.h: /usr/include/GNUstep/Foundation/NSXMLParser.h: ../GDLAccess/EOSQLExpression.h: ../GDLAccess/EOExpressionArray.h: ../GDLAccess/EOJoinTypes.h: SOPE/sope-gdl1/Oracle8/err.h0000644000000000000000000000174415004363604014362 0ustar rootroot/* ** err.h ** ** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _err_H #define _err_H #include void checkerr(OCIError *errhp, sword status); #endif SOPE/sope-gdl1/Oracle8/GNUmakefile0000644000000000000000000000525215004363604015471 0ustar rootroot# # GNUmakefile # # Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte # # Author: Ludovic Marcotte # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # include ../../config.make include $(GNUSTEP_MAKEFILES)/common.make include ../Version include ./Version # Global properties and dependancies SOPE_ROOT=../.. ORACLE_VERSION=$(shell echo /usr/include/oracle/* | awk '{ print $$NF }' | awk -F / '{ print $$NF }') #ORACLE_VERSION=10.2.0.3 #ORACLE_VERSION=11.1.0.1 ADDITIONAL_INCLUDE_DIRS += -I../../sope-core -I../../sope-core/NGExtensions -I../GDLAccess -I.. -I/usr/include/oracle/$(ORACLE_VERSION)/client64 -I/usr/include/oracle/$(ORACLE_VERSION)/client local_arch = $(subst 64,,$(shell uname -m)) ifeq ($(local_arch),ppc) PPC_LDFLAGS=-L/opt/ibmcmp/lib -libmc++ else PPC_LDFLAGS= endif ifneq ($(frameworks),yes) common_LIBS = -L/usr/lib/oracle/$(ORACLE_VERSION)/client64/lib/ -L/usr/lib/oracle/$(ORACLE_VERSION)/client/lib/ -locci -lociei -lclntsh -lnnz11 -L../GDLAccess/obj -lGDLAccess -L../../sope-core/EOControl/obj -lEOControl $(PPC_LDFLAGS) else common_LIBS = -L/usr/lib/oracle/$(ORACLE_VERSION)/client64/lib/ -L/usr/lib/oracle/$(ORACLE_VERSION)/client/lib/ -locci -lociei -lclntsh -lnnz11 -framework GDLAccess -framework EOControl $(PPC_LDFLAGS) endif Oracle8_BUNDLE_LIBS += $(common_LIBS) otest_TOOL_LIBS += $(common_LIBS) # Bundle BUNDLE_NAME = Oracle8 ifeq ($(frameworks),yes) BUNDLE_INSTALL_DIR := $(FRAMEWORK_INSTALL_DIR)/GDLAccess.framework/Resources/GDLAdaptors/ else BUNDLE_INSTALL_DIR = $(SOPE_DBADAPTORS)/ endif Oracle8_OBJC_FILES = \ EOAttribute+Oracle.m \ OracleAdaptor.m \ OracleAdaptorChannel.m \ OracleAdaptorChannelController.m \ OracleAdaptorContext.m \ OracleSQLExpression.m \ OracleValues.m \ err.m Oracle8_PRINCIPAL_CLASS = OracleAdaptor BUNDLE_INSTALL = Oracle8 BUNDLE_EXTENSION = .gdladaptor Oracle8_RESOURCE_FILES += Version # Tool TOOL_NAME = otest otest_OBJC_FILES = otest.m include $(GNUSTEP_MAKEFILES)/bundle.make include $(GNUSTEP_MAKEFILES)/tool.make SOPE/sope-gdl1/Oracle8/OracleAdaptorChannelController.h0000644000000000000000000000277415004363604021653 0ustar rootroot/* ** OracleAdaptorChannelController.h ** ** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _OracleAdaptorChannelController_H #define _OracleAdaptorChannelController_H #import #import @interface OracleAdaptorChannelController : NSObject - (EODelegateResponse) adaptorChannel: (id) theChannel willInsertRow: (NSMutableDictionary *) theRow forEntity: (EOEntity *) theEntity; - (EODelegateResponse) adaptorChannel: (id) theChannel willUpdateRow: (NSMutableDictionary *) theRow describedByQualifier: (EOSQLQualifier *) theQualifier; @end #endif SOPE/sope-gdl1/Oracle8/ChangeLog0000644000000000000000000000315615004363604015172 0ustar rootroot2011-11-14 Francis Lachapelle * OracleValues.m (-stringValueForOracleType:attribute:): boolean values are now converted to 0 or 1. 2010-03-31 Wolfgang Sourdeau * OracleAdaptorChannel.m (+initialize): set the prefetch memory size from a new "OracleAdaptorPrefetchMemorySize" userdefault. Use "16 * 1024" by default. (-evaluateExpression:): make use of the new prefetchMemorySize variable to configure the OCI_ATTR_PREFETCH_MEMORY on the statement. We also set OCI_ATTR_PREFETCH_ROWS to an unreasonably high number to ensure the memory size always has precedence. 2007-11-15 Ludovic Marcotte * fixes 2007-10-19 Ludovic Marcotte * We call OCITerminate() in OracleAdaptorChannel: -closeChannel: * Some formatting cleanups. 2007-10-05 Ludovic Marcotte * Fixed otest wrt bundle name. * Modified sqlFolderFormat so that for the c_deleted columns, we default the value to 0. * Added full CLOB support for reading / writing more than 4000 characters in a CLOB column. 2007-09-20 Ludovic Marcotte * Small fix for 64-bit platforms. 2007-08-29 Helge Hess * Changed bundle name from Oracle to Oracle8 to avoid clashes with older adaptors. 2007-07-25 Ludovic Marcotte * Initial version of the SOPE GDL1 Oracle connector which makes use of the new Oracle OCI API. The initial version has been tested extensively with the Inverse edition of SOGo. See the READMe file for all details. SOPE/sope-gdl1/Oracle8/OracleAdaptorChannelController.m0000644000000000000000000001732715004363604021660 0ustar rootroot/* ** OracleAdaptorChannelController.m ** ** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "OracleAdaptorChannelController.h" #include #include "err.h" #include "OracleAdaptorChannel.h" #include "OracleAdaptorContext.h" #import #import static BOOL debugOn = NO; // // // @interface OracleAdaptorChannelController (Private) - (BOOL) _evaluateExpression: (NSString *) theExpression keys: (NSArray *) theKeys values: (NSMutableDictionary *) theValues channel: (id) theChannel; @end // // // @implementation OracleAdaptorChannelController + (void) initialize { NSUserDefaults *ud; ud = [NSUserDefaults standardUserDefaults]; debugOn = [ud boolForKey: @"OracleAdaptorDebug"]; } - (EODelegateResponse) adaptorChannel: (id) theChannel willInsertRow: (NSMutableDictionary *) theRow forEntity: (EOEntity *) theEntity { NSMutableString *s; NSArray *keys; int i, c; if (debugOn) NSLog(@"willInsertRow: %@ %@", [theRow description], [theEntity description]); s = AUTORELEASE([[NSMutableString alloc] init]); [s appendFormat: @"INSERT INTO %@ (", [theEntity externalName]]; keys = [theRow allKeys]; c = [keys count]; for (i = 0; i < c; i++) { [s appendString: [keys objectAtIndex: i]]; if (i < c-1) [s appendString: @", "]; } [s appendString: @") VALUES ("]; for (i = 0; i < c; i++) { [s appendFormat: @":%d", i+1]; if (i < c-1) [s appendString: @", "]; } [s appendString: @")"]; if ([self _evaluateExpression: s keys: keys values: theRow channel: theChannel]) { return EODelegateOverrides; } return EODelegateRejects; } // // // - (EODelegateResponse) adaptorChannel: (id) theChannel willUpdateRow: (NSMutableDictionary *) theRow describedByQualifier: (EOSQLQualifier *) theQualifier { NSMutableString *s; NSArray *keys; int i, c; if (debugOn) NSLog(@"willUpdateRow: %@ %@", [theRow description], [theQualifier description]); s = AUTORELEASE([[NSMutableString alloc] init]); [s appendFormat: @"UPDATE %@ SET ", [[theQualifier entity] externalName]]; keys = [theRow allKeys]; c = [keys count]; for (i = 0; i < c; i++) { [s appendFormat: @"%@ = :%d", [keys objectAtIndex: i], i+1]; if (i < c-1) [s appendString: @", "]; } [s appendFormat: @" WHERE %@", [theQualifier expressionValueForContext: AUTORELEASE([[EOSQLExpression alloc] initWithEntity: [theQualifier entity]])]];; if ([self _evaluateExpression: s keys: keys values: theRow channel: theChannel]) { return EODelegateOverrides; } return EODelegateRejects; } @end // // // @implementation OracleAdaptorChannelController (Private) - (void) _cleanup: (NSArray *) theColumns statement: (OCIStmt *) theStatement channel: (id) theChannel { column_info *info; int c; c = [theColumns count]; while (c--) { info = [[theColumns objectAtIndex: c] pointerValue]; if (info->type == SQLT_INT) { free(info->value); } else if (info->type == SQLT_CLOB) { OCILobFreeTemporary([theChannel serviceContext], [theChannel errorHandle], info->value); OCIDescriptorFree((dvoid *)info->value, (ub4)OCI_DTYPE_LOB); } free(info); } [theColumns release]; OCIHandleFree(theStatement, OCI_HTYPE_STMT); } // // // - (BOOL) _evaluateExpression: (NSString *) theExpression keys: (NSArray *) theKeys values: (NSMutableDictionary *) theValues channel: (id) theChannel { NSMutableArray *columns;; OCIStmt* current_stm; OCIBind* bind; column_info *info; sword status; text *sql; int i,c; id v; sql = (text *)[theExpression UTF8String]; // We alloc our statement handle if (OCIHandleAlloc((dvoid *)[theChannel environment], (dvoid **)¤t_stm, (ub4)OCI_HTYPE_STMT, (CONST size_t) 0, (dvoid **) 0)) { NSLog(@"Can't allocate statement."); return NO; } // We prepare the statement if (OCIStmtPrepare(current_stm, [theChannel errorHandle], sql, (ub4)strlen((char *)sql), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)) { NSLog(@"FAILED: OCIStmtPrepare() insert\n"); return NO; } columns = [[NSMutableArray alloc] init]; c = [theKeys count]; // We bind all input variables for (i = 0; i < c; i++) { info = (void *)malloc(sizeof(column_info)); [columns addObject: [NSValue valueWithPointer: info]]; v = [theValues objectForKey: [theKeys objectAtIndex: i]]; bind = (OCIBind *)0; if ([v isKindOfClass: [NSString class]]) { const char *buf; ub4 len; buf = [v UTF8String]; len = strlen(buf); if (len <= 4000) { info->type = SQLT_CHR; info->value = (dvoid *)buf; info->width = len; } else { info->type = SQLT_CLOB; info->width = sizeof(OCILobLocator *); if ((status = OCIDescriptorAlloc((dvoid *)[theChannel environment], &(info->value), (ub4)OCI_DTYPE_LOB, (size_t)0, (dvoid **)0)) != OCI_SUCCESS) { [self _cleanup: columns statement: current_stm channel: theChannel]; checkerr([theChannel errorHandle], status); NSLog(@"OracleAdaptorChannelController - Unable to alloc descriptor"); return NO; } OCILobCreateTemporary([theChannel serviceContext], [theChannel errorHandle], info->value, OCI_DEFAULT, SQLCS_IMPLICIT, OCI_TEMP_CLOB, FALSE, OCI_DURATION_SESSION); OCILobWrite([theChannel serviceContext], [theChannel errorHandle], info->value, &len, 1, (dvoid *)buf, len, OCI_ONE_PIECE, (dvoid *)0, (sb4 (*)())0, (ub2)0, (ub1)SQLCS_IMPLICIT); } } else { int x; info->type = SQLT_INT; x = [v intValue]; info->width = sizeof(x); info->value = calloc(info->width, 1); *(int *)info->value = x; } if ((status = (OCIBindByPos(current_stm, &bind, [theChannel errorHandle], (ub4)i+1, (info->type == SQLT_CLOB ? &info->value : (dvoid *)info->value), (sb4)info->width, info->type, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)0, (ub4 *)0, (ub4)OCI_DEFAULT))) != OCI_SUCCESS) { [self _cleanup: columns statement: current_stm channel: theChannel]; checkerr([theChannel errorHandle], status); NSLog(@"OracleAdaptorChannelController - Unable to bind variable"); return NO; } } // We execute the statement if ((status = OCIStmtExecute([theChannel serviceContext], current_stm, [theChannel errorHandle], (ub4)1, (ub4)0, (CONST OCISnapshot*)0, (OCISnapshot*)0, ([(OracleAdaptorContext *)[theChannel adaptorContext] autoCommit] ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT))) != OCI_SUCCESS) { [self _cleanup: columns statement: current_stm channel: theChannel]; checkerr([theChannel errorHandle], status); return NO; } [self _cleanup: columns statement: current_stm channel: theChannel]; return YES; } @end SOPE/sope-gdl1/Oracle8/COPYING.LIB0000644000000000000000000006126115004363604015061 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 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. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-gdl1/Oracle8/README0000644000000000000000000000356315004363604014302 0ustar rootrootOracle 10g GDL Adaptor Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ==================================================================== This adaptor allows you to use an Oracle 10g (or above/below) server togeter with GDL. It makes use of the new OCI API from Oracle. In order to compile and use this adaptor, you must install the Oracle Instant Client. For Linux-based operating systems, please refer to the following page for installation instructions: http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/linuxsoft.html You'll have to install the following packages from Oracle: * oracle-instantclient-basic * oracle-instantclient-devel Once you've installed the requirements, follow the installation and configuration instructions to get the adaptor working. Installation and Configuration ============================== 1- Based on where you've installed the Oracle dependancies, modify the GNUmakefile so gnustep-make can find the location of Oracle's headers and client librairies. You would want to modify at least: ORACLE_VERSION -lnnz 2- Compile and install the adaptor: % make % make install Testing the Oracle Adaptor ========================== The adaptor comes with a simple testing tool called 'otest'. To try it, first modify the database connection parameters specified in the 'condict.plist' file. Then, simply run the tool: % ./obj/otest This will do a simple "SELECT * FROM all_tables" Current limitations =================== The adaptor currently supports only the following data types: - CLOB - DATE - INTEGER - NUMBER - STRING - VARCHAR2 CLOB are read as strings. The adaptor does not yet support the EOModel kungfu. The following improvements are also coming soon: - primary key generation support - schema selection support - delegate calls, when required - more datatypes support SOPE/sope-gdl1/Oracle8/EOAttribute+Oracle.m0000644000000000000000000000572615004363604017173 0ustar rootroot/* ** OracleEOAttribute.m ** ** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "EOAttribute+Oracle.h" @implementation EOAttribute (OracleExtensions) + (id) attributeWithOracleType: (ub2) theType name: (text *) theName length: (ub4) theLength width: (ub4) theWidth { EOAttribute *attr; NSString *s; attr = [[EOAttribute alloc] init]; s = AUTORELEASE([[NSString alloc] initWithBytes: theName length: theLength encoding: NSASCIIStringEncoding]); // Oracle returns us the column names using uppercase strings. // We change that to avoid lameness in other parts of GDL. s = [s lowercaseString]; [attr setName: s]; [attr setColumnName: s]; [attr setWidth: (unsigned)theWidth]; switch (theType) { case SQLT_CHR: [attr setExternalType: @"VARCHAR2"]; [attr setValueClassName: @"NSString"]; break; case SQLT_CLOB: [attr setExternalType: @"CLOB"]; [attr setValueClassName: @"NSString"]; break; case SQLT_DAT: // char[7] that contains the date and time but no time zone information. [attr setExternalType: @"DATE"]; [attr setValueClassName: @"NSDate"]; break; case SQLT_INT: [attr setExternalType: @"INTEGER"]; [attr setValueClassName: @"NSNumber"]; [attr setValueType: @"d"]; break; case SQLT_NUM: // char[22] [attr setExternalType: @"NUMBER"]; [attr setValueClassName: @"NSNumber"]; [attr setValueType: @"d"]; break; case SQLT_STR: [attr setExternalType: @"STRING"]; [attr setValueClassName: @"NSString"]; break; case SQLT_TIMESTAMP: [attr setExternalType: @"TIMESTAMP"]; [attr setValueClassName: @"NSCalendarDate"]; break; case SQLT_TIMESTAMP_TZ: [attr setExternalType: @"TIMESTAMP WITH TIME ZONE"]; [attr setValueClassName: @"NSCalendarDate"]; break; case SQLT_TIMESTAMP_LTZ: [attr setExternalType: @"TIMESTAMP WITH LOCAL TIME ZONE"]; [attr setValueClassName: @"NSCalendarDate"]; break; default: NSLog(@"Unsupported type! %d\n", theType); } return AUTORELEASE(attr); } @end SOPE/sope-gdl1/Oracle8/condict.plist0000644000000000000000000000021215004363604016106 0ustar rootroot{ hostName = "oracle"; userName = "focus"; password = "focusrocks"; databaseName = "oracle"; port = 1521; } SOPE/sope-gdl1/Oracle8/OracleAdaptorContext.m0000644000000000000000000000472015004363604017661 0ustar rootroot/* ** OracleAdaptorContext.m ** ** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "OracleAdaptorContext.h" #import "OracleAdaptorChannel.h" #define DEFAULT_TRANSACTION_TIMEOUT 60 // // // @implementation OracleAdaptorContext - (id) copyWithZone: (NSZone *) theZone { return [self retain]; } // // // - (BOOL) canNestTransactions { return NO; } // // // - (void) channelDidInit: (id) theChannel { if ([[self channels] count] > 0) { [NSException raise: @"OracleContextException" format: @"Channel already initiated for the actual context"]; } [super channelDidInit: theChannel]; } // // // - (EOAdaptorChannel *) createAdaptorChannel { return AUTORELEASE([[OracleAdaptorChannel alloc] initWithAdaptorContext: self]); } // // // - (id) initWithAdaptor: (EOAdaptor *) theAdaptor { self = [super initWithAdaptor: theAdaptor]; _autocommit = YES; return self; } // // // - (BOOL) primaryBeginTransaction { id o; o = [[self channels] lastObject]; return (OCITransStart([o serviceContext], [o errorHandle], (uword)DEFAULT_TRANSACTION_TIMEOUT, OCI_TRANS_NEW) == OCI_ERROR ? NO : YES); } // // // - (BOOL) primaryCommitTransaction { id o; o = [[self channels] lastObject]; return (OCITransCommit([o serviceContext], [o errorHandle], OCI_DEFAULT) == OCI_ERROR ? NO : YES); } // // // - (BOOL) primaryRollbackTransaction { id o; o = [[self channels] lastObject]; return (OCITransRollback([o serviceContext], [o errorHandle], OCI_DEFAULT) == OCI_ERROR ? NO : YES); } // // // - (BOOL) autoCommit { return _autocommit; } // // // - (void) setAutoCommit: (BOOL) theBOOL { _autocommit = theBOOL; } @end SOPE/sope-gdl1/Oracle8/OracleAdaptorChannel.h0000644000000000000000000000345215004363604017601 0ustar rootroot/* ** OracleAdaptorChannel.h ** ** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _OracleAdaptorChannel_H #define _OracleAdaptorChannel_H #include #import //#import "../GDLContentStore/EOAdaptorChannel+GCS.h" @class NSMutableArray; typedef struct { OCIDefine *def; // The define information handle of the column dvoid *value; // The value of the column (the buffer size is max_width bytes) ub2 type; // The type of the column ub2 width; // The current width of the value that has been read ub2 max_width; // The maximum width of the column } column_info; @interface OracleAdaptorChannel : EOAdaptorChannel { @private // Oracle's related ivars OCIEnv* _oci_env; OCISvcCtx* _oci_ctx; OCIError* _oci_err; OCIStmt* _current_stm; // ... NSMutableArray *_resultSetProperties; NSMutableArray *_row_buffer; } - (OCIEnv *) environment; - (OCISvcCtx *) serviceContext; - (OCIError *) errorHandle; @end #endif SOPE/sope-gdl1/Oracle8/Version0000644000000000000000000000004415004363604014761 0ustar rootroot# Version file SUBMINOR_VERSION:=2 SOPE/sope-gdl1/Oracle8/OracleSQLExpression.m0000644000000000000000000000173015004363604017437 0ustar rootroot/* ** OracleSQLExpression.m ** ** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "OracleSQLExpression.h" @implementation OracleSQLExpression @end SOPE/sope-gdl1/Oracle8/OracleAdaptor.h0000644000000000000000000000227215004363604016307 0ustar rootroot/* ** OracleAdaptor.h ** ** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _OracleAdaptor_H #define _OracleAdaptor_H #import #import @interface OracleAdaptor : EOAdaptor { } - (NSString *) serverName; - (NSString *) loginName; - (NSString *) loginPassword; - (NSString *) databaseName; - (NSString *) port; @end #endif SOPE/sope-gdl1/Oracle8/OracleSQLExpression.h0000644000000000000000000000213015004363604017425 0ustar rootroot/* ** OracleSQLExpression.h ** ** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _OracleSQLExpression_H #define _OracleSQLExpression_H #import #import @interface OracleSQLExpression : EOSQLExpression { } @end #endif SOPE/sope-gdl1/Oracle8/EOAttribute+Oracle.h0000644000000000000000000000236415004363604017161 0ustar rootroot/* ** EOAttribute+Oracle.h ** ** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _OracleEOAttribute_H #define _OracleEOAttribute_H #import #include @interface EOAttribute (OracleExtensions) + (id) attributeWithOracleType: (ub2) theType name: (text *) theName length: (ub4) theLength width: (ub4) theWidth; @end #endif SOPE/sope-gdl1/Oracle8/OracleAdaptor.m0000644000000000000000000001062115004363604016311 0ustar rootroot/* ** OracleAdaptor.h ** ** Copyright (c) 2007 Inverse groupe conseil inc. Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "OracleAdaptor.h" #import "OracleAdaptorChannel.h" #import "OracleAdaptorContext.h" #import "OracleSQLExpression.h" #import "OracleValues.h" // // // @interface OracleAdaptor (Private) - (ub2) typeForName: (NSString *) theName; @end @implementation OracleAdaptor (Private) - (ub2) typeForName: (NSString *) theName { ub2 t; theName = [theName uppercaseString]; if ([theName hasPrefix: @"VARCHAR2"]) { t = SQLT_CHR; } else if ([theName hasPrefix: @"VARCHAR"]) { t = SQLT_VCS; } else if ([theName isEqualToString: @"LONG VARCHAR"]) { t = SQLT_LVC; } else if ([theName isEqualToString: @"CLOB"]) { t = SQLT_CLOB; } else if ([theName isEqualToString: @"DATE"]) { t = SQLT_DAT; } else if ([theName isEqualToString: @"INTEGER"]) { t = SQLT_INT; } else if ([theName isEqualToString: @"NUMBER"]) { t = SQLT_NUM; } else if ([theName isEqualToString: @"STRING"]) { t = SQLT_STR; } else if ([theName isEqualToString: @"TIMESTAMP"]) { t = SQLT_TIMESTAMP; } else if ([theName isEqualToString: @"TIMESTAMP WITH TIME ZONE"]) { t = SQLT_TIMESTAMP_TZ; } else if ([theName isEqualToString: @"TIMESTAMP WITH LOCAL TIME ZONE"]) { t = SQLT_TIMESTAMP_LTZ; } else { [self logWithFormat: @"unknown Oracle type: %@ (fallback to SQLT_CHR)", theName]; t = SQLT_CHR; } return t; } @end // // // @implementation OracleAdaptor - (id) initWithName: (NSString *) theName { if ((self = [super initWithName: theName])) { // On Oracle, we must set the NLS_LANG in order to let Oracle perform // charset transformations for us. Since, when we write data to the database // and when we read data from it we assume that we are using UTF-8, we // set NLS_LANG to the proper value. setenv("NLS_LANG", "AMERICAN_AMERICA.UTF8", 1); return self; } return nil; } // // // - (id) copyWithZone: (NSZone *) theZone { return [self retain]; } // // // - (Class) adaptorContextClass { return [OracleAdaptorContext class]; } // // // - (Class) adaptorChannelClass { return [OracleAdaptorChannel class]; } // // // - (Class) expressionClass { return [OracleSQLExpression class]; } // // // - (EOAdaptorContext *) createAdaptorContext { return AUTORELEASE([[OracleAdaptorContext alloc] initWithAdaptor: self]); } // // // - (NSString *) databaseName { return [[self connectionDictionary] objectForKey: @"databaseName"]; } // // // - (id) formatValue: (id) theValue forAttribute: (EOAttribute *) theAttribute { NSString *s; s = [theValue stringValueForOracleType: [self typeForName: [theAttribute externalType]] attribute: theAttribute]; // NSLog(@"Formatted %@ (%@) to %@ (NSString)", theValue, NSStringFromClass([theValue class]), s); return s; } // // We don't check the values inside the connection // dictionary for now.s // - (BOOL) hasValidConnectionDictionary { return ([self connectionDictionary] ? YES : NO); } // // // - (BOOL) isValidQualifierType: (NSString *) theTypeName { return YES; } // // // - (NSString *) loginName; { return [[self connectionDictionary] objectForKey: @"userName"]; } // // // - (NSString *) loginPassword { return [[self connectionDictionary] objectForKey: @"password"]; } // // // - (NSString *) port { return [[self connectionDictionary] objectForKey: @"port"]; } // // // - (NSString *) serverName { return [[self connectionDictionary] objectForKey: @"hostName"]; } @end SOPE/sope-gdl1/Oracle8/otest.m0000644000000000000000000001034515004363604014732 0ustar rootroot/* ** otest.m ** ** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #import #import // // // void evaluate(EOAdaptorChannel *c, NSString *s) { NSLog(@"Evaluating:\t%@",s); if ([c evaluateExpression: s] && [c isFetchInProgress]) { NSDictionary *record; NSArray *attributes; attributes = [c describeResults]; NSLog(@"attributes = %@", [attributes description]); while ((record = [c fetchAttributes: attributes withZone: NULL])) { NSLog(@"record = %@", record); } } } // // // void insert(EOAdaptorChannel *channel, EOEntity *entity, NSMutableDictionary *row) { [row setObject: @"foo" forKey: @"c_name"]; [row setObject: @"barrr" forKey: @"c_content"]; [row setObject: [NSNumber numberWithInt: 1] forKey: @"c_creationdate"]; [row setObject: [NSNumber numberWithInt: 2] forKey: @"c_lastmodified"]; [row setObject: [NSNumber numberWithInt: 0] forKey: @"c_version"]; [channel insertRow: row forEntity: entity]; } // // // void update(EOAdaptorChannel *channel, EOEntity *entity, NSMutableDictionary *row) { EOSQLQualifier *qualifier; qualifier = [[EOSQLQualifier alloc] initWithEntity: entity qualifierFormat: @"%A = 'foo'", @"c_name"]; [row setObject: @"bazzzzzzzzzzz" forKey: @"c_content"]; [row setObject: [NSNumber numberWithInt: 2] forKey: @"c_creationdate"]; [row setObject: [NSNumber numberWithInt: 3] forKey: @"c_lastmodified"]; [row setObject: [NSNumber numberWithInt: 1] forKey: @"c_version"]; [channel updateRow: row describedByQualifier: qualifier]; } // // // int main (int argc, char **argv, char **env) { NSAutoreleasePool *pool; EOAdaptorChannel *channel; NSMutableDictionary *row; EOAdaptorContext *ctx; EOAdaptor *adaptor; EOEntity *entity; EOAttribute *attribute; pool = [[NSAutoreleasePool alloc] init]; [NSProcessInfo initializeWithArguments: argv count: argc environment: env]; adaptor = [EOAdaptor adaptorWithName: @"Oracle8"]; [adaptor setConnectionDictionary: [NSDictionary dictionaryWithContentsOfFile: @"condict.plist"]]; ctx = [adaptor createAdaptorContext]; channel = [ctx createAdaptorChannel]; [channel openChannel]; [ctx beginTransaction]; //evaluate(channel, @"SELECT * FROM all_tables"); evaluate(channel, @"SELECT COUNT(*) FROM all_tables"); evaluate(channel, @"SELECT 1 FROM dual"); evaluate(channel, @"SELECT sysdate FROM dual"); evaluate(channel, @"DROP table otest_demo"); evaluate(channel, @"CREATE TABLE otest_demo (\nc_name VARCHAR2 (256) NOT NULL,\n c_content CLOB NOT NULL,\n c_creationdate INTEGER NOT NULL,\n c_lastmodified INTEGER NOT NULL,\n c_version INTEGER NOT NULL,\n c_deleted INTEGER DEFAULT 0 NOT NULL\n)"); evaluate(channel, @"DELETE FROM otest_demo where c_name = 'foo'"); entity = [[EOEntity alloc] init]; [entity setName: @"otest_demo"]; [entity setExternalName: @"otest_demo"]; // table name attribute = AUTORELEASE([[EOAttribute alloc] init]); [attribute setName: @"c_name"]; [attribute setColumnName: @"c_name"]; [entity addAttribute: attribute]; row = [[NSMutableDictionary alloc] init]; insert(channel, entity, row); evaluate(channel, @"SELECT * FROM otest_demo where c_name = 'foo'"); update(channel, entity, row); evaluate(channel, @"SELECT * FROM otest_demo where c_name = 'foo'"); RELEASE(entity); RELEASE(row); [ctx commitTransaction]; [channel closeChannel]; [pool release]; return 0; } SOPE/sope-gdl1/Oracle8/OracleAdaptorChannel.m0000644000000000000000000004465315004363604017616 0ustar rootroot/* ** OracleAdaptorChannel.m ** ** Copyright (c) 2007-2009 Inverse inc. and Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "OracleAdaptorChannel.h" #include "err.h" #include "OracleAdaptor.h" #include "OracleAdaptorChannelController.h" #include "OracleAdaptorContext.h" #include "EOAttribute+Oracle.h" #import #include static BOOL debugOn = NO; static int prefetchMemorySize; static int maxTry = 3; static int maxSleep = 500; // // // @interface OracleAdaptorChannel (Private) - (void) _cleanup; @end @implementation OracleAdaptorChannel (Private) - (void) _cleanup { column_info *info; int c; sword result; [_resultSetProperties removeAllObjects]; c = [_row_buffer count]; while (c--) { info = [[_row_buffer objectAtIndex: c] pointerValue]; // We free our LOB object. If it fails, it likely mean it isn't a LOB // so we just free the value instead. if (info->value) { if (info->type == SQLT_CLOB || info->type == SQLT_BLOB || info->type == SQLT_BFILEE || info->type == SQLT_CFILEE) { result = OCIDescriptorFree((dvoid *)info->value, (ub4) OCI_DTYPE_LOB); if (result != OCI_SUCCESS) { NSLog (@"value was not a LOB descriptor"); abort(); } } else free(info->value); info->value = NULL; } else { NSLog (@"trying to free an already freed value!"); abort(); } free(info); [_row_buffer removeObjectAtIndex: c]; } OCIHandleFree(_current_stm, OCI_HTYPE_STMT); _current_stm = (OCIStmt *)0; } @end // // // @implementation OracleAdaptorChannel static void DBTerminate() { if (OCITerminate(OCI_DEFAULT)) NSLog(@"FAILED: OCITerminate()"); else NSLog(@"Oracle8: environment shut down"); } + (void) initialize { NSUserDefaults *ud; ud = [NSUserDefaults standardUserDefaults]; debugOn = [ud boolForKey: @"OracleAdaptorDebug"]; prefetchMemorySize = [ud integerForKey: @"OracleAdaptorPrefetchMemorySize"]; if (!prefetchMemorySize) prefetchMemorySize = 16 * 1024; /* 16Kb */ // We Initialize the OCI process environment. if (OCIInitialize((ub4)OCI_DEFAULT, (dvoid *)0, (dvoid * (*)(dvoid *, size_t)) 0, (dvoid * (*)(dvoid *, dvoid *, size_t))0, (void (*)(dvoid *, dvoid *)) 0 )) NSLog(@"FAILED: OCIInitialize()"); else { NSLog(@"Oracle8: environment initialized"); atexit(DBTerminate); } } - (id) initWithAdaptorContext: (EOAdaptorContext *) theAdaptorContext { if ((self = [super initWithAdaptorContext: theAdaptorContext])) { _resultSetProperties = [[NSMutableArray alloc] init]; _row_buffer = [[NSMutableArray alloc] init]; _oci_env = (OCIEnv *)0; _oci_err = (OCIError *)0; _current_stm = (OCIStmt *)0; // This will also initialize ivars in EOAdaptorChannel for // delegate calls so it's important to call -setDelegate: [self setDelegate: [[OracleAdaptorChannelController alloc] init]]; return self; } return nil; } // // // - (id) copyWithZone: (NSZone *) theZone { return [self retain]; } // // // - (void) cancelFetch { // Oracle's doc says: "If you call OCIStmtFetch2() with the nrows parameter set to 0, this cancels the cursor." if (OCIStmtFetch2(_current_stm, _oci_err, (ub4)0, (ub4)OCI_FETCH_NEXT, (sb4)0, (ub4)OCI_DEFAULT)) { NSLog(@"Fetch cancellation failed"); } [self _cleanup]; [super cancelFetch]; } // // // - (void) closeChannel { if ([self isOpen]) { if (debugOn) [self logWithFormat: @"closing Oracle adaptor channel"]; [super closeChannel]; // We logoff from the database. if (!_oci_ctx || !_oci_err || OCILogoff(_oci_ctx, _oci_err)) { NSLog(@"FAILED: OCILogoff()"); } if (_oci_ctx) OCIHandleFree(_oci_ctx, OCI_HTYPE_SVCCTX); if (_oci_err) OCIHandleFree(_oci_err, OCI_HTYPE_ERROR); // OCIHandleFree(_oci_env, OCI_HTYPE_ENV); _oci_ctx = (OCISvcCtx *)0; _oci_err = (OCIError *)0; _oci_env = (OCIEnv *)0; } } // // // - (void) dealloc { if (debugOn) NSLog(@"OracleAdaptorChannel: -dealloc"); [self _cleanup]; RELEASE(_resultSetProperties); RELEASE(delegate); [super dealloc]; } // // TODO later // - (EOModel*) describeModelWithTableNames: (NSArray *) theTableNames { return nil; } // // TODO later // - (NSArray *) describeTableNames { return nil; } // // This breaks EOF 4.5 support. // - (NSArray *) describeResults: (BOOL) theBOOL { return [NSArray arrayWithArray: _resultSetProperties]; } // // This breaks EOF 4.5 support. // // We must: 1. send the database request // 2. process the results // 3. call -adaptorChannel:didEvaluateExpression: // - (BOOL) evaluateExpression: (NSString *) theExpression { EOAttribute *attribute; OCIParam *param; int rCount; column_info *info; ub4 i, clen, count; text *sql, *cname; sword status; ub2 type; ub4 memory, prefetchrows; [self _cleanup]; if (debugOn) [self logWithFormat: @"expression: %@", theExpression]; if (!theExpression || ![theExpression length]) { [NSException raise: @"OracleInvalidExpressionException" format: @"Passed an invalid (nil or length == 0) SQL expression"]; } if (![self isOpen]) { [NSException raise: @"OracleChannelNotOpenException" format: @"Called -evaluateExpression: prior to -openChannel"]; } sql = (text *)[theExpression UTF8String]; rCount = 0; retry: // We alloc our statement handle if ((status = OCIHandleAlloc((dvoid *)_oci_env, (dvoid **)&_current_stm, (ub4)OCI_HTYPE_STMT, (CONST size_t) 0, (dvoid **) 0))) { checkerr(_oci_err, status); NSLog(@"Can't allocate statement."); return NO; } prefetchrows = 100000; /* huge numbers here force a fallback on the memory limit below, which is what we really are interested in */ if ((status = OCIAttrSet(_current_stm, (ub4)OCI_HTYPE_STMT, (dvoid *)&prefetchrows, (ub4) sizeof(ub4), (ub4)OCI_ATTR_PREFETCH_ROWS, _oci_err))) { checkerr(_oci_err, status); NSLog(@"Can't set prefetch rows (%d).", prefetchrows); return NO; } memory = prefetchMemorySize; if ((status = OCIAttrSet(_current_stm, (ub4)OCI_HTYPE_STMT, (dvoid *)&memory, (ub4) sizeof(ub4), (ub4)OCI_ATTR_PREFETCH_MEMORY, _oci_err))) { checkerr(_oci_err, status); NSLog(@"Can't set prefetch memory (%d).", memory); return NO; } // We prepare our statement if ((status = OCIStmtPrepare(_current_stm, _oci_err, sql, strlen((const char *)sql), OCI_NTV_SYNTAX, OCI_DEFAULT))) { checkerr(_oci_err, status); NSLog(@"Prepare failed: OCI_ERROR"); return NO; } // We check if we're doing a SELECT and if so, we're fetching data! OCIAttrGet(_current_stm, OCI_HTYPE_STMT, &type, 0, OCI_ATTR_STMT_TYPE, _oci_err); self->isFetchInProgress = (type == OCI_STMT_SELECT ? YES : NO); // We execute our statement. Not that we _MUST_ set iter to 0 for non-SELECT statements. if ((status = OCIStmtExecute(_oci_ctx, _current_stm, _oci_err, (self->isFetchInProgress ? (ub4)0 : (ub4)1), (ub4)0, (CONST OCISnapshot *)NULL, (OCISnapshot *)NULL, ([(OracleAdaptorContext *)[self adaptorContext] autoCommit] ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT)))) { ub4 serverStatus; checkerr(_oci_err, status); NSLog(@"Statement execute failed (OCI_ERROR): %@", theExpression); #if 0 // We check to see if we lost connection and need to reconnect. serverStatus = 0; OCIAttrGet((dvoid *)_oci_env, OCI_HTYPE_SERVER, (dvoid *)&serverStatus, (ub4 *)0, OCI_ATTR_SERVER_STATUS, _oci_err); if (serverStatus == OCI_SERVER_NOT_CONNECTED) { // We cleanup our previous handles [self cancelFetch]; [self closeChannel]; // We try to reconnect a couple of times before giving up... while (rCount < maxTry) { usleep(maxSleep); rCount++; if ([self openChannel]) { NSLog(@"Connection re-established to Oracle - retrying to process the statement."); goto retry; } else NSLog(@"Could not re-establish connection to Oracle - statement re-processing aborted."); } } #endif return NO; } // We check the number of params (ie., columns) if ((status = OCIAttrGet((dvoid *)_current_stm, OCI_HTYPE_STMT, (dvoid *)&count, (ub4 *)0, OCI_ATTR_PARAM_COUNT, _oci_err))) { checkerr(_oci_err, status); NSLog(@"Attribute get failed (OCI_ERROR): %@", theExpression); return NO; } // We decode the columns' types for (i = 1; i < count+1; i++) { // We alloc our info structure. This will hold the values being // read when we fetch data from the result set. info = (void *)malloc(sizeof(column_info)); // We fetch the parameter status = OCIParamGet((dvoid *)_current_stm, OCI_HTYPE_STMT, _oci_err, (dvoid **)¶m, (ub4)i); // We get the param's type status = OCIAttrGet((dvoid*)param, (ub4)OCI_DTYPE_PARAM, (dvoid*)&(info->type), (ub4 *)0, (ub4)OCI_ATTR_DATA_TYPE, (OCIError *)_oci_err); // We read the column's name (name of the param) and name's length clen = 0; status = OCIAttrGet((dvoid*)param, (ub4)OCI_DTYPE_PARAM, (dvoid**)&cname, (ub4 *)&clen, (ub4)OCI_ATTR_NAME, (OCIError *)_oci_err); // We read the maximum width of a column info->max_width = 0; status = OCIAttrGet((dvoid*)param, (ub4)OCI_DTYPE_PARAM, (dvoid*)&(info->max_width), (ub4 *)0, (ub4)OCI_ATTR_DATA_SIZE, (OCIError *)_oci_err); if (debugOn) NSLog(@"name: %s, type: %d", cname, info->type); attribute = [EOAttribute attributeWithOracleType: info->type name: cname length: clen width: info->max_width]; [_resultSetProperties addObject: attribute]; // We now must bind our column name with a buffer in which we'll read into info->value = calloc(info->max_width, 1); // // Oracle's doc says: "SQLT_CHAR and SQLT_LNG can be specified for CLOB columns, and SQLT_BIN sand SQLT_LBI for BLOB columns." // Also, for LOB, it says: "The bind of more than 4 kilobytes of data to a LOB column uses space from the temporary tablespace." // // For now, we read - SQLT_CLOB as SQLT_CHR // - SQLT_NUM as SQLT_INT // switch (info->type) { case SQLT_CLOB: //type = SQLT_CHR; type = SQLT_CLOB; free(info->value); if (OCIDescriptorAlloc((dvoid *)_oci_env, &(info->value), (ub4)OCI_DTYPE_LOB, (size_t)0, (dvoid **)0) != OCI_SUCCESS) { NSLog(@"Unable to alloc descriptor"); abort(); } // "For descriptors, locators, or REFs, whose size is unknown to client applications, use the size of the structure you // are passing in: for example, sizeof (OCILobLocator *). info->max_width = sizeof(OCILobLocator *); break; case SQLT_NUM: type = SQLT_INT; info->max_width = 4; break; default: type = info->type; } // // Oracle's documentation says:"For a LOB, the buffer pointer must be a pointer to a LOB locator of type OCILobLocator. // Give the address of the pointer." // info->def = (OCIDefine*)0; #warning cleanup if ((status = OCIDefineByPos(_current_stm, &(info->def), _oci_err, i, (info->type == SQLT_CLOB ? &info->value : (dvoid *)info->value), info->max_width, type, (dvoid *)0, (ub2 *)&(info->width), (ub2 *)0, OCI_DEFAULT))) { NSLog(@"OCIDefineByPos FAILED"); abort(); } [_row_buffer addObject: [NSValue valueWithPointer: info]]; // We free up our param handle. OCIHandleFree((dvoid*)param, OCI_HTYPE_STMT); } return YES; } // // // - (OCIError *) errorHandle { return _oci_err; } // // // - (BOOL) isOpen { return (_oci_env ? YES : NO); } // // This breaks EOF 4.5 support. // - (BOOL) openChannel { OracleAdaptor *o; const char *username, *password, *database; sword status; if (debugOn) [self logWithFormat: @"opening Oracle adaptor channel"]; if (![super openChannel] || [self isOpen]) { return NO; } if (OCIEnvInit((OCIEnv **)&_oci_env, (ub4)OCI_DEFAULT, (size_t)0, (dvoid **)0)) { NSLog(@"FAILED: OCIEnvInit()"); [self closeChannel]; return NO; } if (OCIHandleAlloc((dvoid *)_oci_env, (dvoid *)&_oci_err, (ub4)OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0)) { NSLog(@"FAILED: OCIHandleAlloc() on errhp"); [self closeChannel]; return NO; } o = (OracleAdaptor *)[[self adaptorContext] adaptor]; username = [[o loginName] UTF8String]; password = [[o loginPassword] UTF8String]; // Under Oracle 10g, the third parameter of OCILogon() has the form: [//]host[:port][/service_name] // See http://download-west.oracle.com/docs/cd/B12037_01/network.101/b10775/naming.htm#i498306 for // all juicy details. if ([o serverName] && [o port]) database = [[NSString stringWithFormat:@"%@:%@/%@", [o serverName], [o port], [o databaseName]] UTF8String]; else database = [[o databaseName] UTF8String]; // We logon to the database. if ((status = OCILogon(_oci_env, _oci_err, &_oci_ctx, (const OraText*)username, strlen(username), (const OraText*)password, strlen(password), (const OraText*)database, strlen(database)))) { NSLog(@"FAILED: OCILogon(). username = %s password = %s" @" database = %s", username, password, database); checkerr(_oci_err, status); [self closeChannel]; return NO; } return YES; } // // We map the attributes to the values. // // For now, we ignore the passed attributes and we initialize the full row. // - (NSMutableDictionary *) primaryFetchAttributes: (NSArray *) theAttributes withZone: (NSZone *) theZone { sword status; // We check if our connection is open prior to trying to fetch any data. OCIStmtFetch2() returns // NO error code if the OCI environment is set up but the OCILogon() has failed. if (![self isOpen]) return nil; status = OCIStmtFetch2(_current_stm, _oci_err, (ub4)1, (ub4)OCI_FETCH_NEXT, (sb4)0, (ub4)OCI_DEFAULT); if (status == OCI_NO_DATA) { self->isFetchInProgress = NO; } else { NSMutableDictionary *row; column_info *info; int i, c; id o; c = [_resultSetProperties count]; row = [NSMutableDictionary dictionaryWithCapacity: c]; // We decode all column values we got in our result set for (i = 0; i < c; i++) { info = [[_row_buffer objectAtIndex: i] pointerValue]; //NSLog(@"========== NEW COLUMN =============="); //NSLog(@"Read type %d, width %d at %d", info->type, info->width, info->value); o = nil; // On Oracle, if we've read a lenght of 0, it means that we got a NULL. if (info->type != SQLT_CLOB && info->width == 0) { o = [NSNull null]; } else { switch (info->type) { case SQLT_CHR: case SQLT_STR: o = AUTORELEASE([[NSString alloc] initWithBytes: info->value length: info->width encoding: NSUTF8StringEncoding]); break; case SQLT_CLOB: { ub4 len; len = 0; status = OCILobGetLength(_oci_ctx, _oci_err, info->value, &len); // We might get a OCI_INVALID_HANDLE if we try to read a NULL CLOB. // This would be avoided if folks using CLOB would use Oracle's empty_clob() // function but instead of relying on this, we check for invalid handles. if (status != OCI_INVALID_HANDLE && status != OCI_SUCCESS) { checkerr(_oci_err, status); NSLog(@"Attempted to read a NULL CLOB"); o = [NSString string]; } else { // We alloc twice the size of the LOB length. OCILobGetLength() returns us the LOB length in UTF-16 characters. o = calloc(len*2, 1); OCILobRead(_oci_ctx, _oci_err, info->value, &len, 1, o, len*2, (dvoid *)0, (sb4 (*)(dvoid *, CONST dvoid *, ub4, ub1))0, (ub2)OCI_UTF16ID, (ub1)SQLCS_IMPLICIT); o = AUTORELEASE([[NSString alloc] initWithBytesNoCopy: o length: len*2 encoding: NSUTF16StringEncoding freeWhenDone: YES]); } } break; case SQLT_DAT: { signed char *buf; buf = (signed char*)info->value; o = [NSCalendarDate dateWithYear: (buf[0]-100)*100+buf[1]-100 month: buf[2] day: buf[3] hour: buf[4]-1 minute: buf[5]-1 second: buf[6]-1 timeZone: [NSTimeZone timeZoneWithAbbreviation:@"GMT"]]; } break; case SQLT_INT: case SQLT_NUM: switch (info->width) { case 1: o = [NSNumber numberWithChar: *(char*)(info->value)]; break; case 2: o = [NSNumber numberWithShort: *(short*)(info->value)]; break; case 8: o = [NSNumber numberWithLongLong: *(long long*)(info->value)]; break; case 4: default: o = [NSNumber numberWithInt: *(int*)(info->value)]; break; } break; case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: { // FIXME implement //o = [NSDate date]; } break; default: NSLog(@"Unknown type! %d", info->type); } } if (!o) o = [NSNull null]; [row setObject: o forKey: [[_resultSetProperties objectAtIndex: i] name]]; } return row; } return nil; } // // TODO later // #if 0 - (NSDictionary *) primaryKeyForNewRowWithEntity: (EOEntity *) theEntity { } #endif // // TODO later // #if 0 - (BOOL) readTypesForEntity: (EOEntity *) theEntity { return NO; } #endif // // TODO later // #if 0 - (BOOL) readTypeForAttribute: (EOAttribute *) theAttribute { return NO; } #endif // // // - (OCIEnv *) environment { return _oci_env; } // // // - (OCISvcCtx *) serviceContext { return _oci_ctx; } @end SOPE/sope-gdl1/Oracle8/OracleValues.m0000644000000000000000000000400515004363604016155 0ustar rootroot/* ** OracleValues.m ** ** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "OracleValues.h" // // // @implementation NSNumber (OracleExtensions) - (NSString *) stringValueForOracleType: (ub2) theType attribute: (EOAttribute *) theAttribute { #if GNUSTEP_BASE_LIBRARY /* on gstep-base -stringValue of bool's return YES or NO, which seems to be different on Cocoa and liBFoundation. */ if (theType == SQLT_INT) { static Class BoolClass = Nil; if (BoolClass == Nil) BoolClass = NSClassFromString(@"NSBoolNumber"); if ([self isKindOfClass: BoolClass]) return [self boolValue] ? @"1" : @"0"; } #endif return [self stringValue]; } @end // // // @implementation NSString (OracleExtensions) - (NSString *) stringValueForOracleType: (ub2) theType attribute: (EOAttribute *) theAttribute { NSString *value; if (theType == SQLT_CHR || theType == SQLT_STR || theType == SQLT_CLOB || theType == SQLT_VCS || theType == SQLT_LVC) value = [NSString stringWithFormat: @"'%@'", [self stringByReplacingString: @"'" withString: @"''"]]; else value = self; return value; } @end SOPE/sope-gdl1/Oracle8/OracleAdaptorContext.h0000644000000000000000000000227515004363604017657 0ustar rootroot/* ** OracleAdaptorContext.h ** ** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _OracleAdaptorContext_H #define _OracleAdaptorContext_H #import #import @interface OracleAdaptorContext : EOAdaptorContext { @private BOOL _autocommit; } - (BOOL) autoCommit; - (void) setAutoCommit: (BOOL) theBOOL; @end #endif SOPE/sope-gdl1/Oracle8/err.m0000644000000000000000000000375715004363604014375 0ustar rootroot/* ** err.m ** ** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ** ** Author: Ludovic Marcotte ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "err.h" #include void checkerr(OCIError *errhp, sword status) { text errbuf[512]; sb4 errcode; if (status == OCI_SUCCESS) return; switch (status) { case OCI_SUCCESS_WITH_INFO: NSLog(@"Error - OCI_SUCCESS_WITH_INFO\n"); OCIErrorGet ((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), (ub4) OCI_HTYPE_ERROR); NSLog(@"Error - %s\n", errbuf); break; case OCI_NEED_DATA: NSLog(@"Error - OCI_NEED_DATA\n"); break; case OCI_NO_DATA: NSLog(@"Error - OCI_NO_DATA\n"); break; case OCI_ERROR: OCIErrorGet ((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), (ub4) OCI_HTYPE_ERROR); NSLog(@"Error - %s\n", errbuf); break; case OCI_INVALID_HANDLE: NSLog(@"Error - OCI_INVALID_HANDLE\n"); break; case OCI_STILL_EXECUTING: NSLog(@"Error - OCI_STILL_EXECUTING\n"); break; case OCI_CONTINUE: NSLog(@"Error - OCI_CONTINUE\n"); break; default: NSLog(@"Error - %d\n", status); break; } } SOPE/sope-gdl1/SQLite3/0000755000000000000000000000000015004363604013342 5ustar rootrootSOPE/sope-gdl1/SQLite3/SQLiteExpression.h0000644000000000000000000000304715004363604016740 0ustar rootroot/* SQLiteExpression.h Copyright (C) 1999-2005 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___SQLite3_SQLExpression_H___ #define ___SQLite3_SQLExpression_H___ #include @class NSString, NSArray; @class EOSQLQualifier, EOAdaptorChannel; @interface SQLiteExpression : EOSQLExpression + (Class)selectExpressionClass; @end @interface SQLiteSelectSQLExpression : EOSelectSQLExpression { BOOL lock; } - (id)selectExpressionForAttributes:(NSArray *)attributes lock:(BOOL)flag qualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder channel:(EOAdaptorChannel *)channel; - (NSString *)fromClause; @end #endif /* ___SQLite3_SQLExpression_H___ */ SOPE/sope-gdl1/SQLite3/NSData+SQLiteVal.m0000644000000000000000000000522315004363604016434 0ustar rootroot/* NSData+SQLiteVal.m Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SQLiteValues.h" #include "SQLiteChannel.h" #import #include "common.h" @implementation NSData(SQLiteValues) - (id)initWithSQLiteInt:(int)_value { return [self initWithBytes:&_value length:sizeof(int)]; } - (id)initWithSQLiteDouble:(double)_value { return [self initWithBytes:&_value length:sizeof(double)]; } - (id)initWithSQLiteText:(const unsigned char *)_value { return [self initWithBytes:_value length:strlen((char *)_value)]; } - (id)initWithSQLiteData:(const void *)_value length:(int)_length { return [self initWithBytes:_value length:_length]; } - (NSString *)stringValueForSQLite3Type:(NSString *)_type attribute:(EOAttribute *)_attribute { // TODO: UNICODE // TODO: this method looks slow static NSStringEncoding enc = 0; NSString *str, *t; unsigned len; unichar c1; if ((len = [self length]) == 0) return @""; if (enc == 0) { enc = [NSString defaultCStringEncoding]; NSLog(@"Note: SQLite adaptor using '%@' encoding for data=>string " @"conversion.", [NSString localizedNameOfStringEncoding:enc]); } str = [[NSString alloc] initWithData:self encoding:enc]; if (((len = [_type length]) == 0) || (len != 4 && len != 5 && len != 7)) return [str autorelease]; c1 = [_type characterAtIndex:0]; switch (c1) { case 'c': case 'C': case 'v': case 'V': case 'm': case 'M': case 't': case 'T': t = [_type lowercaseString]; if ([t hasPrefix:@"char"] || [t hasPrefix:@"varchar"] || [t hasPrefix:@"money"] || [t hasPrefix:@"text"]) { t = [[str stringValueForSQLite3Type:_type attribute:_attribute] retain]; [str release]; return [t autorelease]; } } return [str autorelease];; } @end /* NSData(SQLiteValues) */ SOPE/sope-gdl1/SQLite3/SQLiteAdaptor.h0000644000000000000000000000353615004363604016176 0ustar rootroot/* SQLiteAdaptor.h Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___SQLite_Adaptor_H___ #define ___SQLite_Adaptor_H___ /* The SQLite adaptor. The connection dictionary of this adaptor understands these keys: databaseName The adaptor is based on libsqlite. */ #import #import #import @class NSString, NSMutableDictionary; @interface SQLiteAdaptor : EOAdaptor { } - (id)initWithName:(NSString *)_name; // connection management - (NSString *)databaseName; - (NSString *)newKeyExpression; // sequence for primary key generation - (NSString *)primaryKeySequenceName; // value formatting - (id)formatValue:(id)value forAttribute:(EOAttribute *)attribute; // attribute typing - (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr; // classes used - (Class)adaptorContextClass; // SQLiteContext - (Class)adaptorChannelClass; // SQLiteChannel - (Class)expressionClass; // SQLiteExpression @end #endif SOPE/sope-gdl1/SQLite3/NSNumber+SQLiteVal.m0000644000000000000000000000572615004363604017023 0ustar rootroot/* SQLiteAdaptor.h Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #include "SQLiteChannel.h" #include "common.h" @implementation NSNumber(SQLiteValues) - (id)initWithSQLiteInt:(int)_value { return [self initWithInt:_value]; } - (id)initWithSQLiteDouble:(double)_value { return [self initWithDouble:_value]; } - (id)initWithSQLiteText:(const unsigned char *)_value { return index((char *)_value, '.') != NULL ? [self initWithDouble:atof((char *)_value)] : [self initWithInt:atoi((char *)_value)]; } - (id)initWithSQLiteData:(const void *)_value length:(int)_length { switch (_length) { case 1: return [self initWithUnsignedChar:*(char *)_value]; case 2: return [self initWithShort:*(short *)_value]; case 4: return [self initWithInt:*(int *)_value]; case 8: return [self initWithDouble:*(double *)_value]; } [self release]; return nil; } - (NSString *)stringValueForSQLite3Type:(NSString *)_type attribute:(EOAttribute *)_attribute { // TODO: can we avoid the lowercaseString? unsigned len; unichar c1; if ((len = [_type length]) == 0) return [self stringValue]; if (len < 4) return [self stringValue]; c1 = [_type characterAtIndex:0]; switch (c1) { case 'b': case 'B': if (![[_type lowercaseString] hasPrefix:@"bool"]) break; return [self boolValue] ? @"true" : @"false"; case 'm': case 'M': { if (![[_type lowercaseString] hasPrefix:@"money"]) break; return [@"$" stringByAppendingString:[self stringValue]]; } case 'c': case 'C': case 't': case 'T': case 'v': case 'V': { static NSMutableString *ms = nil; // reuse mstring, THREAD _type = [_type lowercaseString]; if (!([_type hasPrefix:@"char"] || [_type hasPrefix:@"varchar"] || [_type hasPrefix:@"text"])) break; // TODO: can we get this faster?! if (ms == nil) ms = [[NSMutableString alloc] initWithCapacity:256]; [ms setString:@"'"]; [ms appendString:[self stringValue]]; [ms appendString:@"'"]; return [[ms copy] autorelease]; } } return [self stringValue]; } @end /* NSNumber(SQLiteValues) */ SOPE/sope-gdl1/SQLite3/gdltest.m0000644000000000000000000001234515004363604015173 0ustar rootroot/* gdltest.m Copyright (C) 1999-2005 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #import #include static void fetchExprInChannel(NSString *expr, EOAdaptorChannel *ch) { NSArray *attrs; NSDictionary *record; if (![ch evaluateExpression:expr]) { NSLog(@"ERROR: failed to evaluate: %@", expr); return; } attrs = [ch describeResults]; NSLog(@"results: %@", attrs); while ((record = [ch fetchAttributes:attrs withZone:nil]) != nil) NSLog(@"fetched %@", record); } static void fetchSomePersonRecord(EOEntity *e, EOAdaptorChannel *ch) { EOSQLQualifier *q; NSArray *attrs; attrs = [e attributes]; q = [[EOSQLQualifier alloc] initWithEntity:e qualifierFormat:@"%A='helge'", @"login"]; [q autorelease]; if ([ch selectAttributes:attrs describedByQualifier:q fetchOrder:nil lock:NO]) { NSDictionary *record; record = [ch fetchAttributes:attrs withZone:nil]; } else NSLog(@"Could not select .."); } static void fetchSomeTeamRecords(EOEntity *e, EOAdaptorChannel *ch) { EOSQLQualifier *q; NSArray *attrs; q = [e qualifier]; attrs = [e attributes]; if ([ch selectAttributes:attrs describedByQualifier:q fetchOrder:nil lock:NO]) { NSDictionary *record; while ((record = [ch fetchAttributes:attrs withZone:NULL]) != nil) { NSLog(@"fetched %@ birthday %@", [record valueForKey:@"description"], [record valueForKey:@"companyId"]); } } else NSLog(@"Could not select team records .."); } static void runtestInOpenChannel(EOAdaptorChannel *ch) { NSAutoreleasePool *pool = [NSAutoreleasePool new]; EOEntity *e; EOSQLQualifier *q; NSArray *attrs; EOAdaptorContext *ctx; EOModel *m; NSString *expr; ctx = [ch adaptorContext]; m = [[ctx adaptor] model]; expr = [[NSUserDefaults standardUserDefaults] stringForKey:@"sql"]; NSLog(@"channel is open"); if (![ctx beginTransaction]) { NSLog(@"ERROR: could not begin transaction ..."); return; } NSLog(@"began tx .."); /* do something */ pool = [[NSAutoreleasePool alloc] init]; #if 1 if (expr) fetchExprInChannel(expr, ch); #endif /* fetch some MyEntity records */ e = [m entityNamed:@"MyEntity"]; NSLog(@"entity: %@", e); if (e == nil) exit(1); q = [e qualifier]; attrs = [e attributes]; // NSLog(@"ATTRS: %@", attrs); if ([ch selectAttributes:attrs describedByQualifier:q fetchOrder:nil lock:NO]) { NSDictionary *record; while ((record = [ch fetchAttributes:attrs withZone:nil]) != nil) NSLog(@"fetched record: %@", record); } else NSLog(@"Could not select .."); /* some OGo fetches */ if ((e = [m entityNamed:@"Team"]) != nil) fetchSomeTeamRecords(e, ch); if ((e = [m entityNamed:@"Person"]) != nil) fetchSomePersonRecord(e, ch); /* tear down */ [pool release]; NSLog(@"committing tx .."); if ([ctx commitTransaction]) NSLog(@" could commit."); else NSLog(@" commit failed."); } static void runtest(void) { EOModel *m = nil; EOAdaptor *a; EOAdaptorContext *ctx; EOAdaptorChannel *ch; NSDictionary *conDict; NS_DURING { conDict = [NSDictionary dictionaryWithContentsOfFile:@"condict.plist"]; NSLog(@"condict is %@", conDict); if ((a = [EOAdaptor adaptorWithName:@"SQLite3"]) == nil) { NSLog(@"found no SQLite3 adaptor .."); exit(1); } NSLog(@"got adaptor %@", a); [a setConnectionDictionary:conDict]; NSLog(@"got adaptor with condict %@", a); ctx = [a createAdaptorContext]; ch = [ctx createAdaptorChannel]; #if 1 m = AUTORELEASE([[EOModel alloc] initWithContentsOfFile:@"test.eomodel"]); if (m) { [a setModel:m]; [a setConnectionDictionary:conDict]; } #endif NSLog(@"opening channel .."); [ch setDebugEnabled:YES]; if ([ch openChannel]) { runtestInOpenChannel(ch); NSLog(@"closing channel .."); [ch closeChannel]; } } NS_HANDLER { fprintf(stderr, "exception: %s\n", [[localException description] cString]); abort(); } NS_ENDHANDLER; } int main(int argc, char **argv, char **env) { NSAutoreleasePool *pool; pool = [[NSAutoreleasePool alloc] init]; [NSProcessInfo initializeWithArguments:argv count:argc environment:env]; runtest(); [pool release]; return 0; } SOPE/sope-gdl1/SQLite3/GNUmakefile0000644000000000000000000000340715004363604015420 0ustar rootroot# # GNUmakefile # # Copyright (C) 2005 Helge Hess # # Author: Helge Hess (helge.hess@opengroupware.org) # # This file is part of the SQLite Adaptor Library # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library 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 # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with this library; see the file COPYING.LIB. # If not, write to the Free Software Foundation, # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. include ../../config.make include $(GNUSTEP_MAKEFILES)/common.make include ../Version include ./Version BUNDLE_NAME = SQLite3 SQLite3_PCH_FILE = common.h SQLite3_OBJC_FILES = \ SQLiteExpression.m \ SQLiteAdaptor.m \ SQLiteContext.m \ SQLiteChannel.m \ SQLiteChannel+Model.m \ SQLiteException.m \ SQLiteValues.m \ NSString+SQLite.m \ EOAttribute+SQLite.m \ NSString+SQLiteVal.m \ NSData+SQLiteVal.m \ NSCalendarDate+SQLiteVal.m \ NSNumber+SQLiteVal.m \ SQLite3_PRINCIPAL_CLASS = SQLiteAdaptor BUNDLE_INSTALL = SQLite3 # Use .gdladaptor as the bundle extension BUNDLE_EXTENSION = .gdladaptor SQLite3_RESOURCE_FILES += Version # tool TOOL_NAME = gdltest gdltest_OBJC_FILES = gdltest.m -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/bundle.make ifeq ($(test),yes) include $(GNUSTEP_MAKEFILES)/tool.make endif -include GNUmakefile.postamble SOPE/sope-gdl1/SQLite3/ChangeLog0000644000000000000000000000453715004363604015125 0ustar rootroot2006-10-29 Marcus Mueller * SQLite3.xcodeproj: link against the system version of sqlite3 rather than a custom version in /usr/local. 2006-07-04 Helge Hess * use %p for pointer formats, fixed gcc 4.1 warnings (v4.5.21) 2005-08-16 Helge Hess * GNUmakefile.preamble: added OSX framework compilation (v4.5.20) 2005-08-08 Helge Hess * GNUmakefile.preamble: fixed pathes for inline-compilation (v4.5.19) 2005-07-27 Helge Hess * fixed gcc 4.0 warnings (char signedness) (v4.5.18) 2005-04-21 Helge Hess * v4.5.17 * NSString+SQLiteVal.m: fixed a gcc 3.4.3 warning * SQLiteChannel.m: changed for -describeResults: API 2005-04-12 Helge Hess * SQLiteChannel.m: bumped max connection count from 15 to 150 (v4.5.16) 2005-04-11 Helge Hess * SQLiteChannel.h, SQLiteAdaptor.m: removed unused ivars (v4.5.15) 2005-02-24 Helge Hess * NSString+SQLiteVal.m, NSCalendarDate+SQLiteVal.m: improved SQL value generation (v4.5.14) * v4.5.13 * NSString+SQLiteVal.m: fixed a warning on MacOSX * NSCalendarDate+SQLiteVal.m: added some support for creating NSCalendarDate's from SQLite base types * SQLiteValues.m: fixed some MacOSX compile warning * GNUmakefile.preamble: added missing bundle dependency on GDLAccess 2005-02-21 Marcus Mueller * v4.5.12 * common.h: added #include of for definitions of required macros * SQLite3.xcode: added * SQLite3-Info.plist: added 2005-02-21 Helge Hess * v4.5.11 * SQLiteChannel.m: fixed an issue with fetching empty tables * SQLiteChannel.m: properly generate the trailing ';' for SQL expressions * SQLiteAdaptor.m: added special url=>condict handling (the whole URL path is taken as the database name) 2005-02-20 Helge Hess * SQLiteChannel.m: implemented -describeResults (v4.5.10) * most SQL operations based on models are implemented now (v4.5.9) * made gdltest work again * added work on the SQLite3 adaptor to SOPE 4.5 repository * removed some PostgreSQL stuff * created ChangeLog SOPE/sope-gdl1/SQLite3/common.h0000644000000000000000000000233515004363604015006 0ustar rootroot/* common.h Copyright (C) 1999-2005 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the SQLite3 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___SQLite3_common_H___ #define ___SQLite3_common_H___ #import #include #include #include #import #include #include #endif /* ___SQLite3_common_H___ */ SOPE/sope-gdl1/SQLite3/SQLiteValues.m0000644000000000000000000000754415004363604016053 0ustar rootroot/* SQLiteValues.m Copyright (C) 1999-2005 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "SQLiteValues.h" #import "common.h" @implementation SQLiteDataTypeMappingException - (id)initWithObject:(id)_obj forAttribute:(EOAttribute *)_attr andSQLite3Type:(NSString *)_dt inChannel:(SQLiteChannel *)_channel; { NSDictionary *ui; NSString *typeName = nil; NSString *r; typeName = _dt; if (typeName == nil) typeName = [NSString stringWithFormat:@"Oid[%i]", _dt]; r = [NSString stringWithFormat: @"mapping between %@ and " @"SQLite type %@ is not supported", [_obj description], NSStringFromClass([_obj class]), typeName]; ui = [NSDictionary dictionaryWithObjectsAndKeys: _attr, @"attribute", _channel, @"channel", _obj, @"object", nil]; return [self initWithName:@"DataTypeMappingNotSupported" reason:r userInfo:ui]; } @end /* SQLiteDataTypeMappingException */ @implementation NSNull(SQLiteValues) - (NSString *)stringValueForSQLite3Type:(NSString *)_type attribute:(EOAttribute *)_attribute { return @"null"; } @end /* NSNull(SQLiteValues) */ @implementation NSObject(SQLiteValues) - (id)initWithSQLiteInt:(int)_value { if ([self respondsToSelector:@selector(initWithInt:)]) return [(NSNumber *)self initWithInt:_value]; if ([self respondsToSelector:@selector(initWithDouble:)]) return [(NSNumber *)self initWithDouble:_value]; if ([self respondsToSelector:@selector(initWithString:)]) { NSString *s; char buf[256]; sprintf(buf, "%i", _value); s = [[NSString alloc] initWithCString:buf]; self = [(NSString *)self initWithString:s]; [s release]; return self; } [self release]; return nil; } - (id)initWithSQLiteDouble:(double)_value { if ([self respondsToSelector:@selector(initWithDouble:)]) return [(NSNumber *)self initWithDouble:_value]; [self release]; return nil; } - (id)initWithSQLiteText:(const unsigned char *)_value { if ([self respondsToSelector:@selector(initWithString:)]) { NSString *s; s = [[NSString alloc] initWithUTF8String:(char *)_value]; self = [(NSString *)self initWithString:s]; [s release]; return self; } [self release]; return nil; } - (id)initWithSQLiteData:(const void *)_data length:(int)_length { if ([self respondsToSelector:@selector(initWithBytes:length:)]) return [(NSData *)self initWithBytes:_data length:_length]; if ([self respondsToSelector:@selector(initWithData:)]) { NSData *d; d = [[NSData alloc] initWithBytes:_data length:_length]; self = [(NSData *)self initWithData:d]; [d release]; return self; } [self release]; return nil; } @end /* NSObject(SQLiteValues) */ void __link_SQLiteValues() { // used to force linking of object file __link_SQLiteValues(); } SOPE/sope-gdl1/SQLite3/NSCalendarDate+SQLiteVal.m0000644000000000000000000001445515004363604020101 0ustar rootroot/* NSCalendarDate+SQLiteVal.m Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #include "SQLiteChannel.h" #include "common.h" #if COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY @interface NSCalendarDate(UsedPrivates) - (id)initWithTimeIntervalSince1970:(NSTimeInterval)_tv; @end #endif static NSString *SQLITE3_DATETIME_FORMAT = @"%b %d %Y %I:%M:%S:000%p"; @implementation NSCalendarDate(SQLiteValues) /* Format: '2001-07-26 14:00:00+02' '2001-07-26 14:00:00+09:30' 0123456789012345678901234 Matthew: "07/25/2003 06:00:00 CDT". */ static Class NSCalDateClass = Nil; static NSTimeZone *DefServerTimezone = nil; static NSTimeZone *gmt = nil; static NSTimeZone *gmt01 = nil; static NSTimeZone *gmt02 = nil; - (id)initWithSQLiteData:(const void *)_value length:(int)_length { static char buf[28]; // reused buffer, THREAD const char *_cstr = _value; char *p; NSTimeZone *attrTZ; NSCalendarDate *date; int year, month, day, hour, min, sec, tzOffset; if (_length == 0) return nil; if (_length != 22 && _length != 25) { NSLog(@"ERROR(%s): unexpected date string '%s', returning now" @" (expected format: '2001-07-26 14:00:00+02')", __PRETTY_FUNCTION__, _cstr); return [NSCalendarDate date]; } strncpy(buf, _cstr, 25); buf[25] = '\0'; /* perform on reverse, so that we don't overwrite with null-terminators */ if (_length == 22) { p = &(buf[19]); tzOffset = atoi(p) * 60; } else if (_length >= 25) { int mins; p = &(buf[23]); mins = atoi(p); buf[22] = '\0'; // the ':' p = &(buf[19]); tzOffset = atoi(p) * 60; tzOffset = tzOffset > 0 ? (tzOffset + mins) : (tzOffset - mins); } p = &(buf[17]); buf[19] = '\0'; sec = atoi(p); p = &(buf[14]); buf[16] = '\0'; min = atoi(p); p = &(buf[11]); buf[13] = '\0'; hour = atoi(p); p = &(buf[8]); buf[10] = '\0'; day = atoi(p); p = &(buf[5]); buf[7] = '\0'; month = atoi(p); p = &(buf[0]); buf[4] = '\0'; year = atoi(p); /* TODO: cache all timezones (just 26 ;-) */ switch (tzOffset) { case 0: if (gmt == nil) { gmt = [[NSTimeZone timeZoneForSecondsFromGMT:0] retain]; NSAssert(gmt, @"could not create GMT timezone?!"); } attrTZ = gmt; break; case 60: if (gmt01 == nil) { gmt01 = [[NSTimeZone timeZoneForSecondsFromGMT:3600] retain]; NSAssert(gmt01, @"could not create GMT+01 timezone?!"); } attrTZ = gmt01; break; case 120: if (gmt02 == nil) { gmt02 = [[NSTimeZone timeZoneForSecondsFromGMT:7200] retain]; NSAssert(gmt02, @"could not create GMT+02 timezone?!"); } attrTZ = gmt02; break; default: { /* cache the first, "alternative" timezone */ static int firstTZOffset = 0; // can use 0 since GMT is a separate case static NSTimeZone *firstTZ = nil; if (firstTZOffset == 0) { firstTZOffset = tzOffset; firstTZ = [[NSTimeZone timeZoneForSecondsFromGMT:(tzOffset*60)] retain]; } attrTZ = (firstTZOffset == tzOffset) ? firstTZ : [NSTimeZone timeZoneForSecondsFromGMT:(tzOffset * 60)]; break; } } if (NSCalDateClass == Nil) NSCalDateClass = [NSCalendarDate class]; date = [NSCalDateClass dateWithYear:year month:month day:day hour:hour minute:min second:sec timeZone:attrTZ]; if (date == nil) { NSLog(@"ERROR(%s): could not construct date from string '%s': " @"year=%i,month=%i,day=%i,hour=%i,minute=%i,second=%i, tz=%@", __PRETTY_FUNCTION__, _cstr, year, month, day, hour, min, sec, attrTZ); } return date; } - (id)initWithSQLiteDouble:(double)_value { return [self initWithTimeIntervalSince1970:_value]; } - (id)initWithSQLiteInt:(int)_value { return [self initWithSQLiteDouble:_value]; } - (id)initWithSQLiteText:(const unsigned char *)_value { return [self initWithSQLiteData:_value length:strlen((char *)_value)]; } /* generating value */ - (NSString *)stringValueForSQLite3Type:(NSString *)_type attribute:(EOAttribute *)_attribute { #if 0 NSString *format; #endif EOQuotedExpression *expr; NSTimeZone *serverTimeZone; NSString *format; NSString *val; unsigned len; unichar c1; if ((len = [_type length]) == 0) c1 = 0; else c1 = [_type characterAtIndex:0]; if (c1 == 'i' || c1 == 'I') { // INTEGER char buf[64]; sprintf(buf, "%d", ((unsigned int)[self timeIntervalSince1970])); return [NSString stringWithCString:buf]; } if (c1 == 'r' || c1 == 'R') { // REAL char buf[64]; // TODO: check format sprintf(buf, "%f", [self timeIntervalSince1970]); return [NSString stringWithCString:buf]; } if ((serverTimeZone = [_attribute serverTimeZone]) == nil ) { if (DefServerTimezone == nil) { DefServerTimezone = [[NSTimeZone localTimeZone] retain]; NSLog(@"Note: SQLite adaptor using timezone '%@' as default", DefServerTimezone); } serverTimeZone = DefServerTimezone; } #if 0 format = [_attribute calendarFormat]; #else /* hm, why is that? */ format = @"%Y-%m-%d %H:%M:%S%z"; #endif if (format == nil) format = SQLITE3_DATETIME_FORMAT; [self setTimeZone:serverTimeZone]; val = [self descriptionWithCalendarFormat:format]; expr = [[EOQuotedExpression alloc] initWithExpression:val quote:@"\'" escape:@"\\'"]; val = [[expr expressionValueForContext:nil] retain]; [expr release]; return [val autorelease]; } @end /* NSCalendarDate(SQLiteValues) */ SOPE/sope-gdl1/SQLite3/EOAttribute+SQLite.h0000644000000000000000000000253715004363604017046 0ustar rootroot/* EOAttribute+SQLite.h Copyright (C) 2003-2004 Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___SQLite_EOAttribute_H___ #define ___SQLite_EOAttribute_H___ #import #include @class NSString; @interface EOAttribute(SQLiteAttributeAdditions) - (void)loadValueClassAndTypeUsingSQLiteType:(int)_type size:(int)_size modification:(int)_modification binary:(BOOL)_isBinary; - (void)loadValueClassForExternalSQLiteType:(NSString *)_type; @end #endif /* ___SQLite_EOAttribute_H___ */ SOPE/sope-gdl1/SQLite3/SQLiteChannel.h0000644000000000000000000000346415004363604016154 0ustar rootroot/* SQLiteChannel.h Copyright (C) 2003-2005 Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___SQLite_Channel_H___ #define ___SQLite_Channel_H___ #include @class NSArray, NSString, NSMutableDictionary; @interface SQLiteChannel : EOAdaptorChannel { // connection is valid after an openChannel call void *_connection; // valid during -evaluateExpression: void *statement; BOOL hasPendingRow; BOOL isDone; void *results; // turns on/off channel debugging BOOL isDebuggingEnabled; NSMutableDictionary *_attributesForTableName; NSMutableDictionary *_primaryKeysNamesForTableName; } - (void)setDebugEnabled:(BOOL)_flag; - (BOOL)isDebugEnabled; @end @interface NSObject(Sybase10ChannelDelegate) - (NSArray*)sqlite3Channel:(SQLiteChannel *)channel willFetchAttributes:(NSArray *)attributes; - (BOOL)sqlite3Channel:(SQLiteChannel *)channel willReturnRow:(NSDictionary *)row; @end #endif /* ___SQLite_Channel_H___ */ SOPE/sope-gdl1/SQLite3/fhs.make0000644000000000000000000000122515004363604014761 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) FHS_LIB_DIR=$(CONFIGURE_FHS_INSTALL_LIBDIR) FHS_DB_DIR=$(FHS_LIB_DIR)sope-$(SOPE_MAJOR_VERSION).$(SOPE_MINOR_VERSION)/dbadaptors/ fhs-db-dirs :: $(MKDIRS) $(FHS_DB_DIR) move-bundles-to-fhs :: fhs-db-dirs @echo "moving bundles $(BUNDLE_INSTALL_DIR) to $(FHS_DB_DIR) .." for i in $(BUNDLE_NAME); do \ j="$(FHS_DB_DIR)/$${i}$(BUNDLE_EXTENSION)"; \ if test -d $$j; then rm -r $$j; fi; \ mv "$(BUNDLE_INSTALL_DIR)/$${i}$(BUNDLE_EXTENSION)" $$j; \ done move-to-fhs :: move-bundles-to-fhs after-install :: move-to-fhs endif SOPE/sope-gdl1/SQLite3/COPYING.LIB0000644000000000000000000006126115004363604015010 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 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. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-gdl1/SQLite3/README0000644000000000000000000000720515004363604014226 0ustar rootroot# SQLite3 Adaptor Note: this is far from being complete! The adaptor is currently a fork of the PostgreSQL adaptor. TODO ==== - check EOAttribute+SQLite: -loadValueClassAndTypeUsingSQLiteType:... - SQLiteChannel.m: -primaryFetchAttributes => check field name processing - rewrite for exception less operation - implement more methods in SQLiteChannel+Model (hard with SQLite though) Basics ====== Open a Shell: sqlite3 OGo > insert schema > select * from date_x; Configure the Adaptor (below does not work yet for SQLite3!) Defaults write ogo-webui-1.0a LSAdaptor SQLite3 Defaults write ogo-webui-1.0a LSConnectionDictionary \ '{ databaseName = OGo; }' Defaults write ogo-webui-1.0a PKeyGeneratorDictionary \ "{ newKeyExpression=\"select nextval(\\'key_generator\\');\" }" SQLiteDebugEnabled Setup gdltest Database ====================== sqlite3 Test.sqldb sqlite> CREATE TABLE my_table ( pkey INT PRIMARY KEY ); Sequential execution ==================== http://www.hwaci.com/sw/sqlite/c_interface.html ---snip--- typedef struct sqlite_vm sqlite_vm; int sqlite_compile( sqlite *db, /* The open database */ const char *zSql, /* SQL statement to be compiled */ const char **pzTail, /* OUT: uncompiled tail of zSql */ sqlite_vm **ppVm, /* OUT: the virtual machine to execute zSql */ char **pzErrmsg /* OUT: Error message. */ ); int sqlite_step( sqlite_vm *pVm, /* The virtual machine to execute */ int *pN, /* OUT: Number of columns in result */ const char ***pazValue, /* OUT: Column data */ const char ***pazColName /* OUT: Column names and datatypes */ ); int sqlite_finalize( sqlite_vm *pVm, /* The virtual machine to be finalized */ char **pzErrMsg /* OUT: Error message */ ); ---snap--- Error-Codes =========== ---snip--- #define SQLITE_OK 0 /* Successful result */ #define SQLITE_ERROR 1 /* SQL error or missing database */ #define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */ #define SQLITE_PERM 3 /* Access permission denied */ #define SQLITE_ABORT 4 /* Callback routine requested an abort */ #define SQLITE_BUSY 5 /* The database file is locked */ #define SQLITE_LOCKED 6 /* A table in the database is locked */ #define SQLITE_NOMEM 7 /* A malloc() failed */ #define SQLITE_READONLY 8 /* Attempt to write a readonly database */ #define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite_interrupt() */ #define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ #define SQLITE_CORRUPT 11 /* The database disk image is malformed */ #define SQLITE_NOTFOUND 12 /* (Internal Only) Table or record not found */ #define SQLITE_FULL 13 /* Insertion failed because database is full */ #define SQLITE_CANTOPEN 14 /* Unable to open the database file */ #define SQLITE_PROTOCOL 15 /* Database lock protocol error */ #define SQLITE_EMPTY 16 /* (Internal Only) Database table is empty */ #define SQLITE_SCHEMA 17 /* The database schema changed */ #define SQLITE_TOOBIG 18 /* Too much data for one row of a table */ #define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */ #define SQLITE_MISMATCH 20 /* Data type mismatch */ #define SQLITE_MISUSE 21 /* Library used incorrectly */ #define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ #define SQLITE_AUTH 23 /* Authorization denied */ #define SQLITE_ROW 100 /* sqlite_step() has another row ready */ #define SQLITE_DONE 101 /* sqlite_step() has finished executing */ ---snap--- SOPE/sope-gdl1/SQLite3/SQLiteChannel+Model.h0000644000000000000000000000231115004363604017176 0ustar rootroot/* SQLiteChannel+Model.h Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___SQLite_ModelFetching_H___ #define ___SQLite_ModelFetching_H___ #import "SQLiteChannel.h" @class NSArray; @class EOModel; @interface SQLiteChannel(ModelFetching) - (EOModel *)describeModelWithTableNames:(NSArray *)_tableNames; - (NSArray *)describeTableNames; @end #endif SOPE/sope-gdl1/SQLite3/condict.plist0000644000000000000000000000004315004363604016037 0ustar rootroot{ databaseName = "Test.sqldb"; } SOPE/sope-gdl1/SQLite3/SQLiteContext.h0000644000000000000000000000225415004363604016224 0ustar rootroot/* SQLiteContext.h Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___SQLite_Context_H___ #define ___SQLite_Context_H___ #import @interface SQLiteContext : EOAdaptorContext - (BOOL)primaryBeginTransaction; - (BOOL)primaryCommitTransaction; - (BOOL)primaryRollbackTransaction; @end #endif SOPE/sope-gdl1/SQLite3/EOAttribute+SQLite.m0000644000000000000000000001414715004363604017053 0ustar rootroot/* EOAttribute+SQLite.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #import "EOAttribute+SQLite.h" static NSString *SQLITE3_DATETIME_FORMAT = @"%b %d %Y %I:%M:%S:000%p"; static NSString *SQLITE3_TIMESTAMP_FORMAT = @"%Y-%m-%d %H:%M:%S%z"; @implementation EOAttribute(SQLiteAttributeAdditions) - (void)loadValueClassAndTypeUsingSQLiteType:(int)_type size:(int)_size modification:(int)_modification binary:(BOOL)_isBinary { /* This method makes no sense with SQLite? */ if (_isBinary) [self setValueClassName:@"NSData"]; #if 0 switch (_type) { case BOOLOID: [self setExternalType:@"bool"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"i"]; return; case NAMEOID: [self setExternalType:@"name"]; [self setValueClassName:@"NSString"]; return; case TEXTOID: [self setExternalType:@"textoid"]; [self setValueClassName:@"NSString"]; return; case INT2OID: [self setExternalType:@"int2"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; return; case INT4OID: [self setExternalType:@"int4"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; return; case INT8OID: [self setExternalType:@"int8"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; return; case CHAROID: [self setExternalType:@"char"]; [self setValueClassName:@"NSString"]; break; case VARCHAROID: [self setExternalType:@"varchar"]; [self setValueClassName:@"NSString"]; break; case NUMERICOID: [self setExternalType:@"numeric"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; break; case FLOAT4OID: [self setExternalType:@"float4"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"f"]; break; case FLOAT8OID: [self setExternalType:@"float8"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"f"]; break; case DATEOID: [self setExternalType:@"datetime"]; [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:SQLITE3_DATETIME_FORMAT]; break; case TIMEOID: [self setExternalType:@"time"]; [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:SQLITE3_DATETIME_FORMAT]; break; case TIMESTAMPOID: [self setExternalType:@"timestamp"]; [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:SQLITE3_DATETIME_FORMAT]; break; case TIMESTAMPTZOID: [self setExternalType:@"timestamptz"]; [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:SQLITE3_DATETIME_FORMAT]; break; case BITOID: [self setExternalType:@"bit"]; break; default: NSLog(@"What is SQLITE3 Oid %i ???", _type); break; } #endif } - (void)loadValueClassForExternalSQLiteType:(NSString *)_type { if ([_type isEqualToString:@"bool"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"i"]; } else if ([_type isEqualToString:@"int2"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"i"]; } else if ([_type isEqualToString:@"int4"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"i"]; } else if ([_type isEqualToString:@"float4"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"f"]; } else if ([_type isEqualToString:@"float8"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; } else if ([_type isEqualToString:@"decimal"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; } else if ([_type isEqualToString:@"numeric"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; } else if ([_type isEqualToString:@"name"]) { [self setExternalType:@"name"]; [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"varchar"]) { [self setExternalType:@"varchar"]; [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"char"]) { [self setExternalType:@"char"]; [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"timestamp"]) { [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:SQLITE3_TIMESTAMP_FORMAT]; } else if ([_type isEqualToString:@"timestamptz"]) { [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:SQLITE3_TIMESTAMP_FORMAT]; } else if ([_type isEqualToString:@"datetime"]) { [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:SQLITE3_DATETIME_FORMAT]; } else if ([_type isEqualToString:@"date"]) { [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"time"]) { [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"text"]) { [self setValueClassName:@"NSString"]; } else { NSLog(@"invalid argument %@", _type); [NSException raise:@"InvalidArgumentException" format:@"invalid SQLite type %@ passed to %s", _type, __PRETTY_FUNCTION__]; } } @end /* EOAttribute(SQLite) */ void __link_EOAttributeSQLite() { // used to force linking of object file __link_EOAttributeSQLite(); } SOPE/sope-gdl1/SQLite3/SQLiteException.m0000644000000000000000000000324115004363604016540 0ustar rootroot/* SQLiteException.m Copyright (C) 2003-2005 Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #import "SQLiteException.h" #include "common.h" @implementation SQLiteException + (void)raiseWithFormat:(NSString *)_format, ... { NSString *tmp = nil; va_list ap; va_start(ap, _format); tmp = [[NSString allocWithZone:[self zone]] initWithFormat:_format arguments:ap]; va_end(ap); AUTORELEASE(tmp); [[[self alloc] initWithName:NSStringFromClass([self class]) reason:tmp userInfo:nil] raise]; } @end @implementation SQLiteCouldNotOpenChannelException @end @implementation SQLiteCouldNotConnectException @end @implementation SQLiteCouldNotBindException @end void __link_SQLiteException() { // used to force linking of object file __link_SQLiteException(); } SOPE/sope-gdl1/SQLite3/SQLiteChannel.m0000644000000000000000000004301515004363604016155 0ustar rootroot/* SQLiteChannel.m Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "SQLiteChannel.h" #include "SQLiteAdaptor.h" #include "SQLiteException.h" #include "NSString+SQLite.h" #include "SQLiteValues.h" #include "EOAttribute+SQLite.h" #include "common.h" #ifndef MIN # define MIN(x, y) ((x > y) ? y : x) #endif #define MAX_CHAR_BUF 16384 @implementation SQLiteChannel static EONull *null = nil; + (void)initialize { if (null == NULL) null = [[EONull null] retain]; } - (id)initWithAdaptorContext:(EOAdaptorContext*)_adaptorContext { if ((self = [super initWithAdaptorContext:_adaptorContext])) { [self setDebugEnabled:[[NSUserDefaults standardUserDefaults] boolForKey:@"SQLiteDebugEnabled"]]; self->_attributesForTableName = [[NSMutableDictionary alloc] initWithCapacity:16]; self->_primaryKeysNamesForTableName = [[NSMutableDictionary alloc] initWithCapacity:16]; } return self; } - (void)_adaptorWillFinalize:(id)_adaptor { } - (void)dealloc { if ([self isOpen]) [self closeChannel]; [self->_attributesForTableName release]; [self->_primaryKeysNamesForTableName release]; [super dealloc]; } /* NSCopying methods */ - (id)copyWithZone:(NSZone *)zone { return [self retain]; } // debugging - (void)setDebugEnabled:(BOOL)_flag { self->isDebuggingEnabled = _flag; } - (BOOL)isDebugEnabled { return self->isDebuggingEnabled; } - (void)receivedMessage:(NSString *)_message { NSLog(@"%@: message %@.", _message); } /* open/close */ static int openConnectionCount = 0; - (BOOL)isOpen { return (self->_connection != NULL) ? YES : NO; } - (int)maxOpenConnectionCount { static int MaxOpenConnectionCount = -1; if (MaxOpenConnectionCount != -1) return MaxOpenConnectionCount; MaxOpenConnectionCount = [[NSUserDefaults standardUserDefaults] integerForKey:@"SQLiteMaxOpenConnectionCount"]; if (MaxOpenConnectionCount == 0) MaxOpenConnectionCount = 150; return MaxOpenConnectionCount; } - (BOOL)openChannel { const char *cDBName; SQLiteAdaptor *adaptor; int rc; if (self->_connection) { NSLog(@"%s: Connection already open !!!", __PRETTY_FUNCTION__); return NO; } adaptor = (SQLiteAdaptor *)[adaptorContext adaptor]; if (![super openChannel]) return NO; if (openConnectionCount > [self maxOpenConnectionCount]) { [SQLiteCouldNotOpenChannelException raise:@"NoMoreConnections" format:@"cannot open a additional connection !"]; return NO; } cDBName = [[adaptor databaseName] UTF8String]; rc = sqlite3_open(cDBName, (void *)&(self->_connection)); if (rc != SQLITE_OK) { // could not login .. // Note: connection *is* set! (might be required to deallocate) NSLog(@"WARNING: could not open SQLite connection to database '%@': %s", [adaptor databaseName], sqlite3_errmsg(self->_connection)); sqlite3_close(self->_connection); return NO; } if (isDebuggingEnabled) NSLog(@"SQLite connection established 0x%p", self->_connection); #if 0 NSLog(@"---------- %s: %@ opens channel count[%d]", __PRETTY_FUNCTION__, self, openConnectionCount); #endif openConnectionCount++; #if LIB_FOUNDATION_BOEHM_GC [GarbageCollector registerForFinalizationObserver:self selector:@selector(_adaptorWillFinalize:) object:[[self adaptorContext] adaptor]]; #endif if (isDebuggingEnabled) { NSLog(@"SQLite channel 0x%p opened (connection=0x%p,%s)", self, self->_connection, cDBName); } return YES; } - (void)primaryCloseChannel { if (self->statement != NULL) { sqlite3_finalize(self->statement); self->statement = NULL; } if (self->_connection != NULL) { sqlite3_close(self->_connection); #if 0 NSLog(@"---------- %s: %@ close channel count[%d]", __PRETTY_FUNCTION__, self, openConnectionCount); #endif openConnectionCount--; if (isDebuggingEnabled) { fprintf(stderr, "SQLite connection dropped 0x%p (channel=0x%p)\n", self->_connection, self); } self->_connection = NULL; } } - (void)closeChannel { [super closeChannel]; [self primaryCloseChannel]; } /* fetching rows */ - (NSException *)_makeSQLiteStep { NSString *r; const char *em; int rc; rc = sqlite3_step(self->statement); #if 0 NSLog(@"STEP: %i (row=%i, done=%i, mis=%i)", rc, SQLITE_ROW, SQLITE_DONE, SQLITE_MISUSE); #endif if (rc == SQLITE_ROW) { self->hasPendingRow = YES; self->isDone = NO; return nil /* no error */; } if (rc == SQLITE_DONE) { self->hasPendingRow = NO; self->isDone = YES; return nil /* no error */; } if (rc == SQLITE_ERROR) r = [NSString stringWithUTF8String:sqlite3_errmsg(self->_connection)]; else if (rc == SQLITE_MISUSE) r = @"The SQLite step function was called in an incorrect way"; else if (rc == SQLITE_BUSY) r = @"The SQLite is busy."; else r = [NSString stringWithFormat:@"Unexpected SQLite error: %i", rc]; if ((em = sqlite3_errmsg(self->_connection)) != NULL) r = [r stringByAppendingFormat:@": %s", em]; return [SQLiteException exceptionWithName:@"FetchFailed" reason:r userInfo:nil]; } - (void)cancelFetch { if (self->statement != NULL) { sqlite3_finalize(self->statement); self->statement = NULL; } self->isDone = NO; self->hasPendingRow = NO; [super cancelFetch]; } - (NSArray *)describeResults:(BOOL)_beautifyNames { // TODO: make exception-less method int cnt, fieldCount; NSMutableArray *result = nil; NSMutableDictionary *usedNames = nil; NSNumber *yesObj; yesObj = [NSNumber numberWithBool:YES]; if (![self isFetchInProgress]) { [SQLiteException raise:@"NoFetchInProgress" format:@"No fetch in progress (channel=%@)", self]; } /* we need to fetch a row to get the info */ if (!self->hasPendingRow) { NSException *error; if ((error = [self _makeSQLiteStep]) != nil) { [self cancelFetch]; [error raise]; // raise error, TODO: make exception-less method return nil; } } if (!self->hasPendingRow) /* no rows available */ return nil; fieldCount = sqlite3_column_count(self->statement); /* old code below */ result = [[NSMutableArray alloc] initWithCapacity:fieldCount]; usedNames = [[NSMutableDictionary alloc] initWithCapacity:fieldCount]; for (cnt = 0; cnt < fieldCount; cnt++) { EOAttribute *attribute = nil; NSString *columnName = nil; NSString *attrName = nil; columnName = [NSString stringWithCString: sqlite3_column_name(self->statement, cnt)]; attrName = _beautifyNames ? [columnName _sqlite3ModelMakeInstanceVarName] : columnName; if ([[usedNames objectForKey:attrName] boolValue]) { int cnt2 = 0; char buf[64]; NSString *newAttrName = nil; for (cnt2 = 2; cnt2 < 100; cnt2++) { NSString *s; sprintf(buf, "%i", cnt2); // TODO: unicode s = [[NSString alloc] initWithCString:buf]; newAttrName = [attrName stringByAppendingString:s]; [s release]; if (![[usedNames objectForKey:newAttrName] boolValue]) { attrName = newAttrName; break; } } } [usedNames setObject:yesObj forKey:attrName]; attribute = [[EOAttribute alloc] init]; [attribute setName:attrName]; [attribute setColumnName:columnName]; switch (sqlite3_column_type(self->statement, cnt)) { case SQLITE_INTEGER: [attribute setExternalType:@"INTEGER"]; [attribute setValueClassName:@"NSNumber"]; [attribute setValueType:@"d"]; break; case SQLITE_FLOAT: [attribute setExternalType:@"REAL"]; [attribute setValueClassName:@"NSNumber"]; [attribute setValueType:@"f"]; break; case SQLITE_TEXT: [attribute setExternalType:@"TEXT"]; [attribute setValueClassName:@"NSString"]; break; case SQLITE_BLOB: [attribute setExternalType:@"BLOB"]; [attribute setValueClassName:@"NSData"]; break; case SQLITE_NULL: NSLog(@"WARNING(%s): got SQLite NULL type at column %i, can't derive " @"type information.", __PRETTY_FUNCTION__, cnt); [attribute setExternalType:@"NULL"]; [attribute setValueClassName:@"NSNull"]; break; default: NSLog(@"ERROR(%s): unexpected SQLite type at column %i", __PRETTY_FUNCTION__, cnt); break; } [result addObject:attribute]; [attribute release]; } [usedNames release]; usedNames = nil; return [result autorelease]; } - (BOOL)isColumnNullInCurrentRow:(int)_column { /* Note: NULL in SQLite is represented as empty strings ..., don't know what to do about that? At least Sybase 10 doesn't support empty strings strings as well and converts them to a single space. So maybe it is reasonable to map empty strings to NSNull? Or is this column-type SQLITE_NULL? If so, thats rather weird, since the type query does not take a row. */ return NO; } - (NSMutableDictionary *)primaryFetchAttributes:(NSArray *)_attributes withZone:(NSZone *)_zone { /* Note: we expect that the attributes match the generated SQL. This is because auto-generated SQL can contain SQL table prefixes (like alias.column-name which cannot be detected using the attributes schema) */ // TODO: add a primaryFetchAttributesX method? NSMutableDictionary *row = nil; NSException *error; unsigned attrCount = [_attributes count]; unsigned cnt; if (self->statement == NULL) { NSLog(@"ERROR: no fetch in progress?"); [self cancelFetch]; return nil; } if (!self->hasPendingRow && !self->isDone) { if ((error = [self _makeSQLiteStep]) != nil) { [self cancelFetch]; [error raise]; // raise error, TODO: make exception-less method return nil; } } if (self->isDone) { /* step was fine, but we are at the end */ [self cancelFetch]; return nil; } self->hasPendingRow = NO; /* consume the row */ /* build row */ row = [NSMutableDictionary dictionaryWithCapacity:attrCount]; for (cnt = 0; cnt < attrCount; cnt++) { EOAttribute *attribute; NSString *attrName; id value = nil; attribute = [_attributes objectAtIndex:cnt]; attrName = [attribute name]; if ([self isColumnNullInCurrentRow:cnt]) { value = [null retain]; } else { Class valueClass; valueClass = NSClassFromString([attribute valueClassName]); if (valueClass == Nil) { NSLog(@"ERROR(%s): %@: got no value class for column:\n" @" attribute=%@\n type=%@", __PRETTY_FUNCTION__, self, attrName, [attribute externalType]); value = null; continue; } switch (sqlite3_column_type(self->statement, cnt)) { case SQLITE_INTEGER: value = [[valueClass alloc] initWithSQLiteInt:sqlite3_column_int(self->statement, cnt)]; break; case SQLITE_FLOAT: value = [[valueClass alloc] initWithSQLiteDouble: sqlite3_column_double(self->statement, cnt)]; break; case SQLITE_TEXT: value = [[valueClass alloc] initWithSQLiteText: sqlite3_column_text(self->statement, cnt)]; break; case SQLITE_BLOB: value = [[valueClass alloc] initWithSQLiteData: sqlite3_column_blob(self->statement, cnt) length:sqlite3_column_bytes(self->statement, cnt)]; break; case SQLITE_NULL: value = [null retain]; break; default: NSLog(@"ERROR(%s): unexpected SQLite type at column %i", __PRETTY_FUNCTION__, cnt); continue; } if (value == nil) { NSLog(@"ERROR(%s): %@: got no value for column:\n" @" attribute=%@\n valueClass=%@\n type=%@", __PRETTY_FUNCTION__, self, attrName, NSStringFromClass(valueClass), [attribute externalType]); continue; } } if (value != nil) { [row setObject:value forKey:attrName]; [value release]; } } return row; } /* sending SQL to server */ - (NSException *)evaluateExpressionX:(NSString *)_expression { NSMutableString *sql; NSException *error; BOOL result; const char *s; const char *tails = NULL; int rc; *(&result) = YES; if (_expression == nil) { [NSException raise:@"InvalidArgumentException" format:@"parameter for evaluateExpression: " @"must not be null (channel=%@)", self]; } sql = [[_expression mutableCopy] autorelease]; [sql appendString:@";"]; /* ask delegate */ if (delegateRespondsTo.willEvaluateExpression) { EODelegateResponse response; response = [delegate adaptorChannel:self willEvaluateExpression:sql]; if (response == EODelegateRejects) { return [NSException exceptionWithName:@"EODelegateRejects" reason:@"delegate rejected insert" userInfo:nil]; } if (response == EODelegateOverrides) return nil; } /* check some preconditions */ if (![self isOpen]) { return [SQLiteException exceptionWithName:@"ChannelNotOpenException" reason:@"SQLite connection is not open" userInfo:nil]; } if (self->statement != NULL) { return [SQLiteException exceptionWithName:@"CommandInProgressException" reason:@"an evaluation is in progress" userInfo:nil]; return NO; } if ([self isFetchInProgress]) { NSLog(@"WARNING: a fetch is still in progress: %@", self); [self cancelFetch]; } if (isDebuggingEnabled) NSLog(@"%@ SQL: %@", self, sql); /* reset environment */ self->isFetchInProgress = NO; self->isDone = NO; self->hasPendingRow = NO; s = [sql UTF8String]; rc = sqlite3_prepare(self->_connection, s, strlen(s), (void *)&(self->statement), &tails); if (rc != SQLITE_OK) { NSString *r; [self cancelFetch]; // TODO: improve error r = [NSString stringWithFormat:@"could not parse SQL statement: %s", sqlite3_errmsg(self->_connection)]; return [SQLiteException exceptionWithName:@"ExecutionFailed" reason:r userInfo:nil]; } /* step to first row */ if ([sql hasPrefix:@"SELECT"] || [sql hasPrefix:@"select"]) { self->isFetchInProgress = YES; NSAssert(self->statement, @"missing statement"); } else { if ((error = [self _makeSQLiteStep]) != nil) { [self cancelFetch]; return error; } self->isFetchInProgress = self->hasPendingRow; if (!self->isFetchInProgress) { sqlite3_finalize(self->statement); self->statement = NULL; } } /* only on empty results? */ if (delegateRespondsTo.didEvaluateExpression) [delegate adaptorChannel:self didEvaluateExpression:sql]; return nil /* everything is OK */; } - (BOOL)evaluateExpression:(NSString *)_sql { NSException *e; NSString *n; if ((e = [self evaluateExpressionX:_sql]) == nil) return YES; /* for compatibility with non-X methods, translate some errors to a bool */ n = [e name]; if ([n isEqualToString:@"EOEvaluationError"]) return NO; if ([n isEqualToString:@"EODelegateRejects"]) return NO; [e raise]; return NO; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:64]; [ms appendFormat:@"<%@[0x%p] connection=0x%p", NSStringFromClass([self class]), self, self->_connection]; [ms appendString:@">"]; return ms; } @end /* SQLiteChannel */ @implementation SQLiteChannel(PrimaryKeyGeneration) - (NSDictionary *)primaryKeyForNewRowWithEntity:(EOEntity *)_entity { NSArray *pkeys; SQLiteAdaptor *adaptor; NSString *seqName, *seq; NSDictionary *pkey; pkeys = [_entity primaryKeyAttributeNames]; adaptor = (id)[[self adaptorContext] adaptor]; seqName = [adaptor primaryKeySequenceName]; pkey = nil; seq = nil; seq = ([seqName length] > 0) ? [NSString stringWithFormat:@"SELECT NEXTVAL ('%@')", seqName] : (id)[adaptor newKeyExpression]; NS_DURING { if ([self evaluateExpression:seq]) { id key = nil; NSLog(@"ERROR: new key creation is not implemented in SQLite yet!"); if ([self isFetchInProgress]) { NSLog(@"Primary key eval returned results .."); } // TODO NSLog(@"%s: PKEY GEN NOT IMPLEMENTED!", __PRETTY_FUNCTION__); [self cancelFetch]; if (key != nil) { pkey = [NSDictionary dictionaryWithObject:key forKey:[pkeys objectAtIndex:0]]; } } } NS_HANDLER { pkey = nil; } NS_ENDHANDLER; return pkey; } @end /* SQLiteChannel(PrimaryKeyGeneration) */ void __link_SQLiteChannel() { // used to force linking of object file __link_SQLiteChannel(); } SOPE/sope-gdl1/SQLite3/SQLiteExpression.m0000644000000000000000000000537615004363604016754 0ustar rootroot/* SQLiteExpression.m Copyright (C) 2003-2005 Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "SQLiteExpression.h" @implementation SQLiteExpression + (Class)selectExpressionClass { return [SQLiteSelectSQLExpression class]; } @end /* SQLiteExpression */ @implementation SQLiteSelectSQLExpression - (id)selectExpressionForAttributes:(NSArray *)attributes lock:(BOOL)flag qualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder channel:(EOAdaptorChannel *)channel { lock = flag; [super selectExpressionForAttributes:attributes lock:flag qualifier:qualifier fetchOrder:fetchOrder channel:channel]; return self; } - (NSString *)fromClause { NSMutableString *fromClause; NSEnumerator *enumerator; BOOL first = YES; id key; fromClause = [NSMutableString stringWithCString:" "]; enumerator = [fromListEntities objectEnumerator]; // Compute the FROM list from all the aliases found in // entitiesAndPropertiesAliases dictionary. Note that this dictionary // contains entities and relationships. The last ones are there for // flattened attributes over reflexive relationships. while((key = [enumerator nextObject])) { if(first) first = NO; else [fromClause appendString:@", "]; [fromClause appendFormat:@"%@ %@", [key isKindOfClass:[EORelationship class]] ? [[key destinationEntity] externalName] // flattened attribute : [key externalName], // EOEntity [entitiesAndPropertiesAliases objectForKey:key]]; #if 0 if (lock) [fromClause appendString:@" HOLDLOCK"]; #endif } return fromClause; } @end /* SQLiteSelectSQLExpression */ void __link_SQLiteExpression() { // used to force linking of object file __link_SQLiteExpression(); } SOPE/sope-gdl1/SQLite3/SQLiteContext.m0000644000000000000000000000422315004363604016227 0ustar rootroot/* SQLiteContext.m Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SQLiteContext.h" #include "SQLiteChannel.h" #include "common.h" @implementation SQLiteContext - (void)channelDidInit:_channel { if ([channels count] > 0) { [NSException raise:@"TooManyOpenChannelsException" format:@"SQLite3 only supports one channel per context"]; } [super channelDidInit:_channel]; } - (BOOL)primaryBeginTransaction { BOOL result; result = [[[channels lastObject] nonretainedObjectValue] evaluateExpression:@"BEGIN TRANSACTION"]; return result; } - (BOOL)primaryCommitTransaction { BOOL result; result = [[[channels lastObject] nonretainedObjectValue] evaluateExpression:@"COMMIT TRANSACTION"]; return result; } - (BOOL)primaryRollbackTransaction { BOOL result; result = [[[channels lastObject] nonretainedObjectValue] evaluateExpression:@"ROLLBACK TRANSACTION"]; return result; } - (BOOL)canNestTransactions { return NO; } // NSCopying methods - (id)copyWithZone:(NSZone *)zone { return [self retain]; } @end /* SQLiteContext */ void __link_SQLiteContext() { // used to force linking of object file __link_SQLiteContext(); } SOPE/sope-gdl1/SQLite3/Version0000644000000000000000000000011615004363604014710 0ustar rootroot# Version file SUBMINOR_VERSION:=21 # v4.5.17 requires libGDLAccess v4.5.50 SOPE/sope-gdl1/SQLite3/SQLite3-Info.plist0000644000000000000000000000126715004363604016542 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable SQLite3 CFBundleIdentifier org.OpenGroupware.SOPE.sope-gdl1.SQLite3 CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleSignature ???? CFBundleVersion 4.5.21 NSPrincipalClass SQLite3Adaptor SOPE/sope-gdl1/SQLite3/SQLiteValues.h0000644000000000000000000000425615004363604016043 0ustar rootroot/* SQLiteValues.h Copyright (C) 1999-2005 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___SQLite_Values_H___ #define ___SQLite_Values_H___ #import #import #import #import #import #import "SQLiteException.h" @class EOAttribute; @class SQLiteChannel; @interface SQLiteDataTypeMappingException : SQLiteException - (id)initWithObject:(id)_obj forAttribute:(EOAttribute *)_attr andSQLite3Type:(NSString *)_dt inChannel:(SQLiteChannel *)_channel; @end @protocol SQLiteValues - (NSString *)stringValueForSQLite3Type:(NSString *)_type attribute:(EOAttribute *)_attribute; @end @interface NSObject(SQLiteValues) - (id)initWithSQLiteInt:(int)_value; - (id)initWithSQLiteText:(const unsigned char *)_value; - (id)initWithSQLiteDouble:(double)_value; - (id)initWithSQLiteData:(const void *)_data length:(int)_length; @end @interface NSString(SQLiteValues) < SQLiteValues > @end @interface NSNumber(SQLiteValues) < SQLiteValues > @end @interface NSData(SQLiteValues) < SQLiteValues > @end @interface NSCalendarDate(SQLiteValues) < SQLiteValues > @end @interface EONull(SQLiteValues) - (NSString *)stringValueForSQLite3Type:(NSString *)_type attribute:(EOAttribute *)_attribute; @end #endif /* ___SQLite_Values_H___ */ SOPE/sope-gdl1/SQLite3/test.eomodel0000644000000000000000000000131615004363604015670 0ustar rootroot{ EOModelVersion = 1; adaptorClassName = SQLiteAdaptor; adaptorName = SQLite3; entities = ( { /* CREATE TABLE my_table ( pkey INT PRIMARY KEY ); */ name = MyEntity; externalName = my_table; className = EOGenericRecord; primaryKeyAttributes = ( pkey ); attributesUsedForLocking = ( pkey ); classProperties = ( pkey ); attributes = ( { valueClassName = NSNumber; columnName = pkey; name = pkey; valueType = i; externalType = INT; // t_id }, ); } ); } SOPE/sope-gdl1/SQLite3/SQLiteAdaptor.m0000644000000000000000000000777515004363604016214 0ustar rootroot/* SQLiteAdaptor.m Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SQLiteAdaptor.h" #include "SQLiteContext.h" #include "SQLiteChannel.h" #include "SQLiteExpression.h" #include "SQLiteValues.h" #include "common.h" @implementation SQLiteAdaptor - (NSDictionary *)connectionDictionaryForNSURL:(NSURL *)_url { /* "Database URLs" We use the schema: SQLite3://localhost/dbpath/foldername */ NSMutableDictionary *md; NSString *p; if ((p = [_url path]) == nil) return nil; p = [p stringByDeletingLastPathComponent]; if ([p length] == 0) p = [_url path]; md = [NSMutableDictionary dictionaryWithCapacity:8]; [md setObject:p forKey:@"databaseName"]; return md; } - (id)initWithName:(NSString *)_name { if ((self = [super initWithName:_name])) { } return self; } /* NSCopying methods */ - (id)copyWithZone:(NSZone *)_zone { return [self retain]; } // connections - (NSString *)serverName { return @"localhost"; } - (NSString *)loginName { return @"no-login-required"; } - (NSString *)loginPassword { return @"no-pwd-required"; } - (NSString *)databaseName { return [[[[self connectionDictionary] objectForKey:@"databaseName"] copy] autorelease]; } - (NSString *)port { return @"no-port-required"; } - (NSString *)options { return [[[[self connectionDictionary] objectForKey:@"options"] copy] autorelease]; } /* sequence for primary key generation */ - (NSString *)primaryKeySequenceName { NSString *seqName; seqName = [[self pkeyGeneratorDictionary] objectForKey:@"primaryKeySequenceName"]; return [[seqName copy] autorelease]; } - (NSString *)newKeyExpression { NSString *newKeyExpr; newKeyExpr = [[self pkeyGeneratorDictionary] objectForKey:@"newKeyExpression"]; return [[newKeyExpr copy] autorelease]; } // formatting - (NSString *)charConvertExpressionForAttributeNamed:(NSString *)_attrName { return _attrName; } - (id)formatValue:(id)value forAttribute:(EOAttribute *)attribute { NSString *result; result = [value stringValueForSQLite3Type:[attribute externalType] attribute:attribute]; //NSLog(@"formatting value %@ result %@", value, result); //NSLog(@" value class %@ attr %@ attr type %@", // [value class], attribute, [attribute externalType]); return result; } - (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr { return YES; } /* types */ - (BOOL)isValidQualifierType:(NSString *)_typeName { return YES; } /* adaptor info */ - (Class)adaptorContextClass { return [SQLiteContext class]; } - (Class)adaptorChannelClass { return [SQLiteChannel class]; } - (Class)expressionClass { return [SQLiteExpression class]; } @end /* SQLiteAdaptor */ void __linkSQLiteAdaptor(void) { extern void __link_EOAttributeSQLite(); extern void __link_NSStringSQLite(); extern void __link_SQLiteChannelModel(); extern void __link_SQLiteValues(); ; [SQLiteChannel class]; [SQLiteContext class]; [SQLiteException class]; [SQLiteExpression class]; __link_EOAttributeSQLite(); __link_NSStringSQLite(); //__link_SQLiteChannelModel(); __link_SQLiteValues(); __linkSQLiteAdaptor(); } SOPE/sope-gdl1/SQLite3/NSString+SQLiteVal.m0000644000000000000000000000602615004363604017033 0ustar rootroot/* SQLiteAdaptor.h Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SQLiteChannel.h" #include #import #include "common.h" @implementation NSString(SQLiteValues) static Class EOExprClass = Nil; - (id)initWithSQLiteInt:(int)_value { char buf[256]; sprintf(buf, "%i", _value); return [self initWithCString:buf]; } - (id)initWithSQLiteDouble:(double)_value { char buf[256]; sprintf(buf, "%g", _value); return [self initWithCString:buf]; } - (id)initWithSQLiteText:(const unsigned char *)_value { return [self initWithUTF8String:(char *)_value]; } - (id)initWithSQLiteData:(const void *)_value length:(int)_length { NSData *d; d = [[NSData alloc] initWithBytes:_value length:_length]; self = [self initWithData:d encoding:NSUTF8StringEncoding]; [d release]; return self; } /* generate SQL value */ - (NSString *)stringValueForSQLite3Type:(NSString *)_type attribute:(EOAttribute *)_attribute { // TODO: all this looks slow ... unsigned len; unichar c1; if ((len = [_type length]) == 0) return self; c1 = [_type characterAtIndex:0]; switch (c1) { case 'c': case 'C': // char case 'v': case 'V': // varchar case 't': case 'T': { // text NSString *s; id expr; if (len < 4) return self; _type = [_type lowercaseString]; if (!([_type hasPrefix:@"char"] || [_type hasPrefix:@"varchar"] || [_type hasPrefix:@"text"])) break; /* TODO: creates too many autoreleased strings :-( */ expr = [self stringByReplacingString:@"\\" withString:@"\\\\"]; if (EOExprClass == Nil) EOExprClass = [EOQuotedExpression class]; expr = [[EOExprClass alloc] initWithExpression:expr quote:@"'" escape:@"\\'"]; s = [[(EOQuotedExpression *)expr expressionValueForContext:nil] retain]; [expr release]; return [s autorelease]; } case 'i': case 'I': { // int char buf[128]; sprintf(buf, "%i", [self intValue]); return [NSString stringWithCString:buf]; } default: NSLog(@"WARNING(%s): return string as is for type %@", __PRETTY_FUNCTION__, _type); break; } return self; } @end /* NSString(SQLiteValues) */ SOPE/sope-gdl1/SQLite3/SQLiteChannel+Model.m0000644000000000000000000002520015004363604017205 0ustar rootroot/* SQLiteChannel+Model.m Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SQLiteChannel.h" #include "NSString+SQLite.h" #include "EOAttribute+SQLite.h" #include "common.h" @interface EORelationship(FixMe) - (void)addJoin:(id)_join; @end @implementation SQLiteChannel(ModelFetching) - (NSArray *)_attributesForTableName:(NSString *)_tableName { NSMutableArray *attributes; NSString *sqlExpr; NSArray *resultDescription; NSDictionary *row; if ([_tableName length] == 0) return nil; attributes = [self->_attributesForTableName objectForKey:_tableName]; if (attributes == nil) { #if 1 // TODO: we would need to parse the SQL field of 'sqlite_master'? NSLog(@"ERROR(%s): operation not supported on SQLite!", __PRETTY_FUNCTION__); return nil; #else sqlExpr = [NSString stringWithFormat:sqlExpr, _tableName]; #endif if (![self evaluateExpression:sqlExpr]) { fprintf(stderr, "Couldn`t evaluate column-describe '%s' on table '%s'\n", [sqlExpr cString], [_tableName cString]); return nil; } resultDescription = [self describeResults]; attributes = [NSMutableArray arrayWithCapacity:16]; while ((row = [self fetchAttributes:resultDescription withZone:NULL])) { EOAttribute *attribute; NSString *columnName = nil; NSString *externalType = nil; NSString *attrName = nil; columnName = [[row objectForKey:@"attname"] stringValue]; attrName = [columnName _sqlite3ModelMakeInstanceVarName]; externalType = [[row objectForKey:@"typname"] stringValue]; attribute = [[EOAttribute alloc] init]; [attribute setColumnName:columnName]; [attribute setName:attrName]; [attribute setExternalType:externalType]; [attribute loadValueClassForExternalSQLiteType:externalType]; [attributes addObject:attribute]; [attribute release]; } [self->_attributesForTableName setObject:attributes forKey:_tableName]; //NSLog(@"got attrs: %@", attributes); } return attributes; } - (NSArray *)_primaryKeysNamesForTableName:(NSString *)_tableName { //NSArray *pkNameForTableName = nil; if ([_tableName length] == 0) return nil; NSLog(@"ERROR(%s): operation not supported on SQLite!", __PRETTY_FUNCTION__); return nil; } - (NSArray *)_foreignKeysForTableName:(NSString *)_tableName { return nil; } - (EOModel *)describeModelWithTableNames:(NSArray *)_tableNames { // TODO: is this correct for SQLite?! NSMutableArray *buildRelShips; EOModel *model; int cnt, tc; buildRelShips = [NSMutableArray arrayWithCapacity:64]; model = [[[EOModel alloc] init] autorelease]; for (cnt = 0, tc = [_tableNames count]; cnt < tc; cnt++) { NSMutableDictionary *relNamesUsed; NSMutableArray *classProperties, *primaryKeyAttributes; NSString *tableName; NSArray *attributes, *pkeys, *fkeys; EOEntity *entity; int cnt2, ac, fkc; relNamesUsed = [NSMutableDictionary dictionaryWithCapacity:16]; classProperties = [NSMutableArray arrayWithCapacity:16]; primaryKeyAttributes = [NSMutableArray arrayWithCapacity:2]; tableName = [_tableNames objectAtIndex:cnt]; attributes = [self _attributesForTableName:tableName]; pkeys = [self _primaryKeysNamesForTableName:tableName]; fkeys = [self _foreignKeysForTableName:tableName]; entity = [[[EOEntity alloc] init] autorelease]; ac = [attributes count]; fkc = [fkeys count]; [entity setName:[tableName _sqlite3ModelMakeClassName]]; [entity setClassName: [@"EO" stringByAppendingString: [tableName _sqlite3ModelMakeClassName]]]; [entity setExternalName:tableName]; [classProperties addObjectsFromArray:[entity classProperties]]; [primaryKeyAttributes addObjectsFromArray:[entity primaryKeyAttributes]]; [model addEntity:entity]; for (cnt2 = 0; cnt2 < ac; cnt2++) { EOAttribute *attribute = [attributes objectAtIndex:cnt2]; NSString *columnName = [attribute columnName]; [entity addAttribute:attribute]; [classProperties addObject:attribute]; if ([pkeys containsObject:columnName]) [primaryKeyAttributes addObject:attribute]; } [entity setClassProperties:classProperties]; [entity setPrimaryKeyAttributes:primaryKeyAttributes]; for (cnt2 = 0; cnt2 < fkc; cnt2++) { NSDictionary *fkey; NSMutableArray *classProperties; NSString *sa, *da, *dt; EORelationship *rel; EOJoin *join; // TODO: fix me, EOJoin is deprecated NSString *relName; fkey = [fkeys objectAtIndex:cnt2]; classProperties = [NSMutableArray arrayWithCapacity:8]; sa = [fkey objectForKey:@"sourceAttr"]; da = [fkey objectForKey:@"targetAttr"]; dt = [fkey objectForKey:@"targetTable"]; rel = [[[EORelationship alloc] init] autorelease]; // TODO: fix me join = [[[NSClassFromString(@"EOJoin") alloc] init] autorelease]; if ([pkeys containsObject:sa]) { relName = [@"to" stringByAppendingString: [dt _sqlite3ModelMakeClassName]]; } else { relName = [@"to" stringByAppendingString: [[sa _sqlite3ModelMakeInstanceVarName] _sqlite3StringWithCapitalizedFirstChar]]; if ([relName hasSuffix:@"Id"]) { int cLength = [relName cStringLength]; relName = [relName substringToIndex:cLength - 2]; } } if ([relNamesUsed objectForKey:relName]) { int useCount = [[relNamesUsed objectForKey:relName] intValue]; [relNamesUsed setObject:[NSNumber numberWithInt:(useCount++)] forKey:relName]; relName = [NSString stringWithFormat:@"%s%d", [relName cString], useCount]; } else [relNamesUsed setObject:[NSNumber numberWithInt:0] forKey:relName]; [rel setName:relName]; //[rel setDestinationEntity:(EOEntity *)[dt _sqlite3ModelMakeClassName]]; [rel setToMany:NO]; // TODO: EOJoin is removed, fix this ... [(id)join setSourceAttribute: (EOAttribute *)[sa _sqlite3ModelMakeInstanceVarName]]; [(id)join setDestinationAttribute: (EOAttribute *)[da _sqlite3ModelMakeInstanceVarName]]; [rel addJoin:join]; [entity addRelationship:rel]; [classProperties addObjectsFromArray:[entity classProperties]]; [classProperties addObject:rel]; [entity setClassProperties:classProperties]; [buildRelShips addObject:rel]; } [entity setAttributesUsedForLocking:[entity attributes]]; } [buildRelShips makeObjectsPerformSelector: @selector(replaceStringsWithObjects)]; /* // make reverse relations { int cnt, rc = [buildRelShips count]; for (cnt = 0; cnt < rc; cnt++) { EORelationship *rel = [buildRelShips objectAtIndex:cnt]; NSMutableArray *classProperties = [NSMutableArray new]; EORelationship *reverse = [rel reversedRelationShip]; EOEntity *entity = [rel destinationEntity]; NSArray *pkeys = [entity primaryKeyAttributes]; BOOL isToMany = [reverse isToMany]; EOAttribute *sa = [[[reverse joins] lastObject] sourceAttribute]; NSString *relName = nil; if ([pkeys containsObject:sa] || isToMany) relName = [@"to" stringByAppendingString: [(EOEntity *)[reverse destinationEntity] name]]; else { relName = [@"to" stringByAppendingString: [[[sa name] _sqlite3ModelMakeInstanceVarName] _sqlite3StringWithCapitalizedFirstChar]]; if ([relName hasSuffix:@"Id"]) { int cLength = [relName cStringLength]; relName = [relName substringToIndex:cLength - 2]; } } if ([entity relationshipNamed:relName]) { int cnt = 1; NSString *numName; numName = [NSString stringWithFormat:@"%s%d", [relName cString], cnt]; while ([entity relationshipNamed:numName]) { cnt++; numName = [NSString stringWithFormat:@"%s%d", [relName cString], cnt]; } relName = numName; } [reverse setName:relName]; [entity addRelationship:reverse]; [classProperties addObjectsFromArray:[entity classProperties]]; [classProperties addObject:reverse]; [entity setClassProperties:classProperties]; } } */ [model setAdaptorName:@"SQLite"]; [model setAdaptorClassName:@"SQLiteAdaptor"]; [model setConnectionDictionary: [[adaptorContext adaptor] connectionDictionary]]; return model; } - (NSArray *)describeTableNames { NSMutableArray *tableNames = nil; NSArray *resultDescription = nil; NSString *attributeName = nil; NSDictionary *row = nil; NSString *selectExpression = nil; selectExpression = @"SELECT name FROM sqlite_master WHERE type='table'"; if (![self evaluateExpression:selectExpression]) { fprintf(stderr, "Could not evaluate table-describe expression '%s'\n", [selectExpression cString]); return nil; } resultDescription = [self describeResults]; attributeName = [(EOAttribute *)[resultDescription objectAtIndex:0] name]; tableNames = [NSMutableArray arrayWithCapacity:16]; while ((row = [self fetchAttributes:resultDescription withZone:NULL])!=nil) [tableNames addObject:[row objectForKey:attributeName]]; return tableNames; } @end /* SQLiteChannel(ModelFetching) */ void __link_SQLiteChannelModel() { // used to force linking of object file __link_SQLiteChannelModel(); } SOPE/sope-gdl1/SQLite3/NSString+SQLite.h0000644000000000000000000000245115004363604016361 0ustar rootroot/* NSString+SQLite.h Copyright (C) 1999-2005 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___SQLite_NSString_H___ #define ___SQLite_NSString_H___ #import @interface NSString(SQLiteMiscStrings) - (NSString *)_sqlite3ModelMakeInstanceVarName; - (NSString *)_sqlite3ModelMakeClassName; - (NSString *)_sqlite3StringWithCapitalizedFirstChar; - (NSString *)_sqlite3StripEndSpaces; @end #endif /* ___SQLite_NSString_H___ */ SOPE/sope-gdl1/SQLite3/NSString+SQLite.m0000644000000000000000000001070015004363604016362 0ustar rootroot/* NSString+SQLite.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: NSString+SQLite.m,v 1.1 2004/06/14 14:27:44 helge Exp $ #if LIB_FOUNDATION_BOEHM_GC # include #endif #import #include "common.h" #import "NSString+SQLite.h" @implementation NSString(SQLiteMiscStrings) - (NSString *)_sqlite3ModelMakeInstanceVarName { if ([self length] == 0) return @""; else { unsigned clen = 0; char *s = NULL; int cnt, cnt2; clen = [self cStringLength]; s = malloc(clen + 10); [self getCString:s maxLength:clen]; for (cnt = cnt2 = 0; cnt < clen; cnt++, cnt2++) { if ((s[cnt] == '_') && (s[cnt + 1] != '\0')) { s[cnt2] = toupper(s[cnt + 1]); cnt++; } else if ((s[cnt] == '2') && (s[cnt + 1] != '\0')) { s[cnt2] = s[cnt]; cnt++; cnt2++; s[cnt2] = toupper(s[cnt]); } else s[cnt2] = tolower(s[cnt]); } s[cnt2] = '\0'; return [[[NSString alloc] initWithCStringNoCopy:s length:strlen(s) freeWhenDone:YES] autorelease]; } } - (NSString *)_sqlite3ModelMakeClassName { if ([self length] == 0) return @""; else { unsigned clen = 0; char *s = NULL; int cnt, cnt2; clen = [self cStringLength]; s = malloc(clen + 10); [self getCString:s maxLength:clen]; for (cnt = cnt2 = 0; cnt < clen; cnt++, cnt2++) { if ((s[cnt] == '_') && (s[cnt + 1] != '\0')) { s[cnt2] = toupper(s[cnt + 1]); cnt++; } else if ((s[cnt] == '2') && (s[cnt + 1] != '\0')) { s[cnt2] = s[cnt]; cnt++; cnt2++; s[cnt2] = toupper(s[cnt]); } else s[cnt2] = tolower(s[cnt]); } s[cnt2] = '\0'; s[0] = toupper(s[0]); return [[[NSString alloc] initWithCStringNoCopy:s length:strlen(s) freeWhenDone:YES] autorelease]; } } - (NSString *)_sqlite3StringWithCapitalizedFirstChar { NSCharacterSet *upperSet = [NSCharacterSet uppercaseLetterCharacterSet]; if ([self length] == 0) return @""; else if ([upperSet characterIsMember:[self characterAtIndex:0]]) return [[self copy] autorelease]; else { NSMutableString *str = [NSMutableString stringWithCapacity:[self length]]; [str appendString:[[self substringToIndex:1] uppercaseString]]; [str appendString:[self substringFromIndex:1]]; return [[str copy] autorelease]; } } - (NSString *)_sqlite3StripEndSpaces { if ([self isNotEmpty]) { NSCharacterSet *spaceSet; NSMutableString *str; unichar (*charAtIndex)(id, SEL, int); NSRange range; spaceSet = [NSCharacterSet whitespaceCharacterSet]; str = [NSMutableString stringWithCapacity:[self length]]; charAtIndex = (unichar (*)(id, SEL, int)) [self methodForSelector:@selector(characterAtIndex:)]; range.length = 0; for (range.location = ([self length] - 1); range.location >= 0; range.location++, range.length++) { unichar c; c = (unichar)(int)charAtIndex(self, @selector(characterAtIndex:), range.location); if (![spaceSet characterIsMember:c]) break; } if (range.length > 0) { [str appendString:self]; [str deleteCharactersInRange:range]; return AUTORELEASE([str copy]); } } return AUTORELEASE([self copy]); } @end void __link_NSStringSQLite() { // used to force linking of object file __link_NSStringSQLite(); } SOPE/sope-gdl1/SQLite3/SQLiteException.h0000644000000000000000000000262715004363604016542 0ustar rootroot/* SQLiteException.h Copyright (C) 1999-2005 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the SQLite Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___SQLite_Exception_H___ #define ___SQLite_Exception_H___ #import @interface SQLiteException : NSException { } + (void)raiseWithFormat:(NSString *)_format, ...; @end @interface SQLiteCouldNotOpenChannelException : SQLiteException { } @end @interface SQLiteCouldNotConnectException : SQLiteCouldNotOpenChannelException { } @end @interface SQLiteCouldNotBindException : SQLiteException { } @end #endif /* ___SQLite_Exception_H___ */ SOPE/sope-gdl1/SQLite3/GNUmakefile.preamble0000644000000000000000000000373515004363604017212 0ustar rootroot# # GNUmakefile # # Copyright (C) 2003-2005 Helge Hess # # Author: Helge Hess (helge.hess@opengroupware.org) # # This file is part of the SQLite3 Adaptor Library # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library 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 # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with this library; see the file COPYING.LIB. # If not, write to the Free Software Foundation, # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. SOPE_ROOT=../.. ifeq ($(frameworks),yes) BUNDLE_INSTALL_DIR := $(FRAMEWORK_INSTALL_DIR)/GDLAccess.framework/Resources/GDLAdaptors/ else BUNDLE_INSTALL_DIR = $(SOPE_DBADAPTORS)/ endif # SQLite3 config SQLite3_BUNDLE_LIBS += -lsqlite3 # set compile flags and go ADDITIONAL_INCLUDE_DIRS += \ -I../GDLAccess -I.. ADDITIONAL_INCLUDE_DIRS += \ -I.. -I../.. \ -I$(SOPE_ROOT)/sope-core/ \ -I$(SOPE_ROOT)/sope-core/NGExtensions # dependencies ifneq ($(frameworks),yes) SQLite3_BUNDLE_LIBS += -lGDLAccess -lEOControl gdltest_TOOL_LIBS += -lGDLAccess -lEOControl else SQLite3_BUNDLE_LIBS += -framework GDLAccess -framework EOControl gdltest_TOOL_LIBS += -framework GDLAccess -framework EOControl endif # library/framework search pathes DEP_DIRS = \ ../GDLAccess \ $(SOPE_ROOT)/sope-core/EOControl ifneq ($(frameworks),yes) ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),\ -L$(GNUSTEP_BUILD_DIR)/$(dir)/$(GNUSTEP_OBJ_DIR_NAME)) else ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir)) endif SYSTEM_LIB_DIR += $(CONFIGURE_SYSTEM_LIB_DIR) SOPE/sope-gdl1/GNUmakefile0000644000000000000000000000110415004363604014164 0ustar rootroot# GNUstep makefile include ../config.make include $(GNUSTEP_MAKEFILES)/common.make PACKAGE_NAME=sope-gdl1 VERSION=4.7.0 SUBPROJECTS += GDLAccess ifeq ($(HAS_LIBRARY_pq),yes) SUBPROJECTS += PostgreSQL endif ifeq ($(HAS_LIBRARY_sqlite3),yes) SUBPROJECTS += SQLite3 endif ifeq ($(HAS_LIBRARY_mysqlclient),yes) SUBPROJECTS += MySQL endif ifeq ($(HAS_LIBRARY_oracle),yes) SUBPROJECTS += Oracle endif -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/aggregate.make -include GNUmakefile.postamble # package macosx-pkg :: all ../maintenance/make-osxpkg.sh sope-gdl1 SOPE/sope-gdl1/PostgreSQL/0000755000000000000000000000000015004363604014121 5ustar rootrootSOPE/sope-gdl1/PostgreSQL/pgconfig.h0000644000000000000000000000310615004363604016066 0ustar rootroot/* PostgreSQL72Channel.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2006 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PG_MAJOR_VERSION /* PostgreSQL 7.4 and up do not have those versioning checks */ #define NG_HAS_NOTICE_PROCESSOR 1 #define NG_HAS_BINARY_TUPLES 1 #define NG_HAS_FMOD 1 #define NG_SET_CLIENT_ENCODING 1 #else /* PG_MAJOR_VERSION processing */ #if PG_MAJOR_VERSION >= 6 && PG_MINOR_VERSION > 3 # define NG_HAS_NOTICE_PROCESSOR 1 # define NG_HAS_BINARY_TUPLES 1 # define NG_HAS_FMOD 1 #endif #if PG_MAJOR_VERSION >= 7 && PG_MINOR_VERSION > 3 # define NG_SET_CLIENT_ENCODING 1 #endif #endif /* PG_MAJOR_VERSION processing */ SOPE/sope-gdl1/PostgreSQL/PostgreSQL-Info.plist0000644000000000000000000000110215004363604020064 0ustar rootroot CFBundleExecutable PostgreSQL CFBundleIdentifier org.OpenGroupware.SOPE.sope-gdl1.PostgreSQL CFBundlePackageType BNDL CFBundleSignature ???? CFBundleVersion 4.5.48 NSPrincipalClass PostgreSQL72Adaptor SOPE/sope-gdl1/PostgreSQL/NSString+PostgreSQL72.h0000644000000000000000000000242015004363604020147 0ustar rootroot/* NSString+PostgreSQL72.h Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___PostgreSQL72_NSString_H___ #define ___PostgreSQL72_NSString_H___ #import @interface NSString(PostgreSQL72MiscStrings) - (NSString *)_pgModelMakeInstanceVarName; - (NSString *)_pgModelMakeClassName; - (NSString *)_pgStringWithCapitalizedFirstChar; - (NSString *)_pgStripEndSpaces; @end #endif SOPE/sope-gdl1/PostgreSQL/gdltest.m0000644000000000000000000001212315004363604015744 0ustar rootroot/* gdltest.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2005 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #import #include int main(int argc, char **argv, char **env) { EOModel *m = nil; EOAdaptor *a; EOAdaptorContext *ctx; EOAdaptorChannel *ch; NSDictionary *conDict; NSString *expr; [NSProcessInfo initializeWithArguments:argv count:argc environment:env]; NS_DURING { conDict = [NSDictionary dictionaryWithContentsOfFile:@"condict.plist"]; NSLog(@"condict is %@", conDict); if ((a = [EOAdaptor adaptorWithName:@"PostgreSQL"]) == nil) { NSLog(@"found no PostgreSQL adaptor .."); exit(1); } NSLog(@"got adaptor %@", a); [a setConnectionDictionary:conDict]; NSLog(@"got adaptor with condict %@", a); ctx = [a createAdaptorContext]; ch = [ctx createAdaptorChannel]; #if 1 m = AUTORELEASE([[EOModel alloc] initWithContentsOfFile:@"test.eomodel"]); if (m) { [a setModel:m]; [a setConnectionDictionary:conDict]; } #endif expr = [[NSUserDefaults standardUserDefaults] stringForKey:@"sql"]; NSLog(@"opening channel .."); [ch setDebugEnabled:YES]; if ([ch openChannel]) { NSLog(@"channel is open"); if ([ctx beginTransaction]) { NSLog(@"began tx .."); /* do something */ { NSAutoreleasePool *pool = [NSAutoreleasePool new]; EOEntity *e; EOSQLQualifier *q; NSArray *attrs; #if 1 /* fetch some expr */ if (expr) { if ([ch evaluateExpression:expr]) { NSDictionary *record; attrs = [ch describeResults]; NSLog(@"results: %@", attrs); while ((record = [ch fetchAttributes:attrs withZone:nil])) NSLog(@"fetched %@", record); } } #endif /* fetch some doof records */ e = [m entityNamed:@"Doof"]; NSLog(@"entity: %@", e); if (e == nil) exit(1); q = [e qualifier]; attrs = [e attributes]; if ([ch selectAttributes:attrs describedByQualifier:q fetchOrder:nil lock:NO]) { NSDictionary *record; while ((record = [ch fetchAttributes:attrs withZone:nil])) { NSLog(@"fetched %@ birthday %@", [record valueForKey:@"pkey"], [record valueForKey:@"companyId"]); } } else NSLog(@"Could not select .."); /* fetch some team records */ if ((e = [m entityNamed:@"Team"])) { q = [e qualifier]; attrs = [e attributes]; if ([ch selectAttributes:attrs describedByQualifier:q fetchOrder:nil lock:NO]) { NSDictionary *record; while ((record = [ch fetchAttributes:attrs withZone:nil])) { NSLog(@"fetched %@ birthday %@", [record valueForKey:@"description"], [record valueForKey:@"companyId"]); } } else NSLog(@"Could not select .."); } /* do some update */ if ((e = [m entityNamed:@"Person"])) { attrs = [e attributes]; q = [[EOSQLQualifier alloc] initWithEntity:e qualifierFormat:@"%A='helge'", @"login"]; AUTORELEASE(q); if ([ch selectAttributes:attrs describedByQualifier:q fetchOrder:nil lock:NO]) { NSDictionary *record; record = [ch fetchAttributes:attrs withZone:nil]; } else NSLog(@"Could not select .."); } RELEASE(pool); } NSLog(@"committing tx .."); if ([ctx commitTransaction]) NSLog(@" could commit."); else NSLog(@" commit failed."); } NSLog(@"closing channel .."); [ch closeChannel]; } } NS_HANDLER { fprintf(stderr, "exception: %s\n", [[localException description] cString]); abort(); } NS_ENDHANDLER; return 0; } SOPE/sope-gdl1/PostgreSQL/GNUmakefile0000644000000000000000000000365715004363604016206 0ustar rootroot# # GNUmakefile # # Copyright (C) 2004-2007 SKYRIX Software AG # # Author: Helge Hess (helge.hess@skyrix.com) # # This file is part of the PostgreSQL Adaptor Library # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library 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 # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with this library; see the file COPYING.LIB. # If not, write to the Free Software Foundation, # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. include ../../config.make include $(GNUSTEP_MAKEFILES)/common.make include ../Version include ./Version BUNDLE_NAME = PostgreSQL PostgreSQL_PCH_FILE = common.h PostgreSQL_OBJC_FILES = \ PGConnection.m \ PGResultSet.m \ PostgreSQL72Expression.m \ PostgreSQL72Adaptor.m \ PostgreSQL72Context.m \ PostgreSQL72Channel.m \ PostgreSQL72Channel+Model.m \ PostgreSQL72Exception.m \ NSString+PostgreSQL72.m \ EOAttribute+PostgreSQL72.m \ NSString+PGVal.m \ NSData+PGVal.m \ NSCalendarDate+PGVal.m \ NSNumber+PGVal.m \ EOKeyGlobalID+PGVal.m \ NSNull+PGVal.m \ NSNumber+ExprValue.m \ PostgreSQL72DataTypeMappingException.m PostgreSQL_PRINCIPAL_CLASS = PostgreSQL72Adaptor BUNDLE_INSTALL = PostgreSQL # Use .gdladaptor as the bundle extension BUNDLE_EXTENSION = .gdladaptor PostgreSQL_RESOURCE_FILES += Version # tool TOOL_NAME = gdltest gdltest_OBJC_FILES = gdltest.m -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/bundle.make #include $(GNUSTEP_MAKEFILES)/tool.make -include GNUmakefile.postamble SOPE/sope-gdl1/PostgreSQL/PostgreSQL72Values.h0000644000000000000000000000461715004363604017636 0ustar rootroot/* PostgreSQL72Values.h Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___PostgreSQL72_Values_H___ #define ___PostgreSQL72_Values_H___ #import #import #import #import #import #import "PostgreSQL72Exception.h" @class EOAttribute; @class PostgreSQL72Channel; @interface PostgreSQL72DataTypeMappingException : PostgreSQL72Exception /* - (id)initWithObject:(id)_obj forAttribute:(EOAttribute *)_attr andPostgreSQLType:(NSString *)_dt inChannel:(PostgreSQL72Channel *)_channel; */ @end @protocol PostgreSQL72Values + (id)valueFromCString:(const char *)_cstr length:(int)_length postgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute adaptorChannel:(PostgreSQL72Channel *)_channel; + (id)valueFromBytes:(const void *)_bytes length:(int)_length postgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute adaptorChannel:(PostgreSQL72Channel *)_channel; - (NSString *)stringValueForPostgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute; @end @interface NSString(PostgreSQL72Values) < PostgreSQL72Values > @end @interface NSNumber(PostgreSQL72Values) < PostgreSQL72Values > @end @interface NSData(PostgreSQL72Values) < PostgreSQL72Values > @end @interface NSCalendarDate(PostgreSQL72Values) < PostgreSQL72Values > @end @interface EONull(PostgreSQL72Values) - (NSString *)stringValueForPostgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute; @end #endif SOPE/sope-gdl1/PostgreSQL/ChangeLog0000644000000000000000000002744615004363604015710 0ustar rootroot2008-07-02 Adam Williams * NSString+PGVal.m: quote single quote in expressions with double quote (was backslash) (v4.7.54) 2008-02-09 Helge Hess * NSCalendarDate+PGVal.m: rewrote date parsing to use strsep(), now works with date strings containing milliseconds (which we ignore) (v4.7.53) * v4.7.52 * NSString+PostgreSQL72.m: properly use -length, not -cStringLength * PostgreSQL72Channel+Model.m, PGResultSet.m: use -UTF8String instead of -cString 2007-09-27 Helge Hess * PostgreSQL72Context.m: changed to use -evaluateExpressionX: for transaction queries, log error exceptions (v4.7.51) 2007-06-09 Helge Hess * added NSNumber+ExprValue.m which returns 0/1 for bool values on GNUstep-Base (v4.7.50) 2007-03-22 Helge Hess * EOAttribute+PostgreSQL72.m: removed sql3types.h from inclusion (which was not available on Ubuntu/PG 8.1.4), hopefully it still compiles with all relevant PG versions (v4.5.49) 2006-09-30 Helge Hess * v4.5.48 * always use UTF-8 as the transport encoding (was Latin1 before), enforce that by setting the connection client encoding (when possible) * added category to convert EOKeyGlobalIDs to SQL (required by OGo trunk) * moved NSNull/pgval category to own file * moved PostgreSQL version detection to pgconfig.h file, properly detect new PostgreSQL versions by a missing PG_MAJOR_VERSION define (and enable NG_SET_CLIENT_ENCODING etc in this case) 2006-07-04 Helge Hess * fixed some 64bit issues (v4.5.47) * use %p for pointer formats, fixed gcc 4.1 warnings (v4.5.46) 2005-08-16 Helge Hess * GNUmakefile.preamble: added OSX framework compilation (v4.5.45) 2005-08-08 Helge Hess * removed CVS Id fields (v4.5.44) 2005-08-08 Sebastian Ley * GNUmakefile.preamble: use 'pg_config' tool to determine PostgreSQL include/lib locations (v4.5.43) 2005-07-27 Helge Hess * v4.5.42 * PostgreSQL72Channel+Model.m: fixed an EOJoin related gcc 4.0 warning * NSCalendarDate+PGVal.m: fixed gcc 4.0 signed-warnings 2005-04-21 Helge Hess * PostgreSQL72Channel.m: changed for -describeResults: API (v4.5.41) 2005-01-14 Helge Hess * EOAttribute+PostgreSQL72.m: map PG oid's to NSStrings (avoids issues when fetching from core PG tables) (v4.5.40) 2005-01-06 Helge Hess * NSCalendarDate+PGVal.m: fixed a warning on Xcode (v4.5.39) 2004-12-14 Marcus Mueller * PostgreSQL.xcode: minor fixes and updated 2004-11-04 Helge Hess * use Version file for install directory location 2004-09-22 Marcus Mueller * PostgreSQL.xcode: new Xcode project. This requires you have a recent PostgreSQL installed in /usr/local/pgsql. * PostgreSQL-Info.plist: new bundle info for Xcode * PostgreSQL72-Info.plist: removed old bundle info 2004-09-11 Marcus Mueller * GNUmakefile.preamble: minor changes for inline compilation with GNUSTEP_BUILD_DIR set elsewhere (v1.1.38) 2004-09-06 Helge Hess * EOAttribute+PostgreSQL72.m: use same exception handling on all Foundations (v1.1.37) 2004-08-29 Helge Hess * added hack to install the project in FHS locations - the DB adaptor will be installed in FHS_INSTALL_ROOT if specified (eg make FHS_INSTALL_ROOT=/usr/local) (v1.1.36) 2004-08-27 Helge Hess * GNUmakefile*: renamed bundle to PostgreSQL, now installs in Library/GDLAdaptors-1.1/ (v1.1.35) 2004-08-21 Helge Hess * renamed from (misleading name) PostgreSQL72 to PostgreSQL * fixed for SOPE 3.3 directory layout (v1.0.34) 2004-08-20 Helge Hess * moved from ThirdParty to SOPE/sope-gdl1 (v1.0.33) 2004-07-06 Helge Hess * PostgreSQL72Channel.m: ensure that the port is passed to the connection as a string object (v1.0.32) 2004-06-29 Helge Hess * GNUmakefile.preamble: added include path to SOPE/skyrix-core for "inline" compilation (v1.0.31) 2004-06-28 Helge Hess * PostgreSQL72Channel.m: do not raise errors in handler methods, but return them for processing by the new X methods (v1.0.30) * PostgreSQL72Channel.m: implement a specific -evaluateExpressionX:, use that in -primaryKeyForNewRowWithEntity: (v1.0.29) 2004-06-22 Helge Hess * v1.0.28 * PostgreSQL72Adaptor.m: some code cleanups * PostgreSQL72Channel+Model.m: fixed a gstep-base warning * NSNumber+PGVal.m ([NSNumber -stringValueForPostgreSQLType:attribute:]): fixed rendering of bool numbers for gstep-base (-stringValue of bool numbers return 'YES'/'NO' on gstep-base while 1 or 0 on Cocoa and libFoundation) 2004-06-21 Helge Hess * EOAttribute+PostgreSQL72.m: added "cardinal_number", "character_data" as known types (v1.0.27) * PostgreSQL72Channel+Model.m: code cleanups (v1.0.26) 2004-06-16 Helge Hess * NSString+PGVal.m, PGConnection.m: fixed some gcc 3.4 warnings (v1.0.25) 2004-06-16 Helge Hess * v1.0.24 * PostgreSQL72Channel: rewrote to use PGResultSet. Removed processing of oid-status which apparently was completely broken before! * PGConnection.m: added new PGResultSet object 2004-06-15 Helge Hess * v1.0.23 * PostgreSQL72Channel+Model.m: added -describeDatabaseNames and -describeUserNames methods * PostgreSQL72Adaptor.m: minor code cleanups * v1.0.22 * various files: fixed warnings on MacOSX with gstep-make * PostgreSQL72Channel.h: rewritten to use PGConnection object * started PGConnection object to remove low-level libpq things from the channel (which can then concentrate on implementing the API) 2004-06-06 Helge Hess * fixed some MacOSX compilation warnings (v1.0.21) 2004-05-04 Helge Hess * GNUmakefile.preamble (PostgreSQL72_BUNDLE_LIBS): added missing libs for current Panther PostgreSQL compilation (v1.0.20) 2004-03-01 Helge Hess * GNUmakefile.preamble: fixed makefile for "inline" compilation (v1.0.19) 2004-02-12 Helge Hess * v1.0.18 * EOAttribute+PostgreSQL72.m: fixed exception for MacOSX * GNUmakefile.preamble: added yet another special case to locate the PostgreSQL header files ... 2004-02-10 Helge Hess * PostgreSQL72Channel.m: only set client encoding when being compiled with PostgreSQL 7.3+ (seems to have problems with umlauts on Debian 7.2) (v1.0.17) 2004-02-08 Helge Hess * PostgreSQL72Channel.m: explicitly set connection encoding to Latin1 to avoid problems with databases created as Unicode (v1.0.16) 2004-01-07 Helge Hess * PostgreSQL72Exception.m: minor cleanup, include stdarg.h for varargs processing (might fix compilation on Solaris) (v1.0.15) 2004-01-07 Helge Hess * PostgreSQL72Channel.m: do cache attribute name field indices during invocations, minor performance optimization to fetch method (which requires that the attributes argument is constant!) (v1.0.14) * PostgreSQL72Channel.m: raise default value for max-connection count to 50, various cleanups and minor fixes (v1.0.13) 2003-12-26 Helge Hess * NSData+PGVal.m ([NSData -stringValueForPostgreSQLType:attribute:]): fixed a bug in the data=>string conversion. Types like "VARCHAR(4000)" where not properly converted, eg a long obj_property value (v1.0.12) 2003-12-13 Helge Hess * GNUmakefile.preamble: fixed include flags, so that GDLAccess must not be installed prior compiling the adaptor (v1.0.11) 2003-12-11 Helge Hess * GNUmakefile (BUNDLE_INSTALL_DIR): install into GNUSTEP_INSTALLATION_DIR instead of GNUSTEP_SYSTEM_ROOT (v1.0.10) 2003-09-03 Helge Hess * GNUmakefile.preamble: added /usr/include/postgresql as an include search path - this is the position of the headers under Debian (v1.0.9) 2003-07-30 Helge Hess * NSCalendarDate+PGVal.m: added support for 4 digit timezone offsets (eg +09:30) when parsing PG date values (v1.0.8) 2003-07-28 Helge Hess * NSCalendarDate+PGVal.m: fixed two more bugs introduced in 1.0.5 ... (v1.0.7) 2003-07-28 Bjoern Stierand * NSCalendarDate+PGVal.m: fixed release bug introduced in 1.0.5, wrong variable was returned leading to a memory error (v1.0.6) 2003-07-27 Helge Hess * PostgreSQL72Values.m: split up into separate files, added several performance optimizations to base value creation code (v1.0.5) 2003-07-23 Helge Hess * more fixes to the include pathes, do not include using but always using (v1.0.4) 2003-07-21 Helge Hess * some include cleanups for FreeBSD (reported by Mirko Viviani), fixed some warnings (v1.0.3) Wed May 14 11:27:21 2003 Jan Reichmann * PostgreSQL72Values.m: use lowercase type to determine sql type (bug 126) (v1.0.2) 2003-05-07 Helge Hess * v1.0.1 * PostgreSQL72Channel.m: small cleanups, speed improvement on attrname creation (used no autorelease pools ...) * GNUmakefile (PostgreSQL72_RESOURCE_FILES): added a Version file Mon May 5 16:27:40 2003 Jan Reichmann * PostgreSQL72Values.m: implement valueFromCString, valueFromBytes, stringValueForPostgreSQLType for NSData+PostgreSQL72Values (bug 126) Mon Dec 23 18:20:13 2002 Helge Hess * ported to MacOSX 10.2.3 (do not use * EOAttribute+PostgreSQL72.m: add timestamptz type Tue Nov 5 10:02:45 2002 Jan Reichmann * PostgreSQLChannel.m: add PGMaxOpenConnectionCount - Default to set the max number of open postgres connections Fri Oct 18 19:15:15 2002 Jan Reichmann * EOAttribute+PostgreSQL72.m: add postgres types Thu Aug 22 11:08:35 2002 Jan Reichmann * PostgreSQL72Channel.m, PostgreSQL72Values.m: -fixed bug (attributes with the same name were not fetched (both attrs. where set to the first attr.-value) -fixed escape-bug Thu Jun 13 14:57:10 2002 Jan41 Reichmann * PostgreSQL72Values.m: remove Logs Tue Jun 11 14:43:14 2002 Jan41 Reichmann * PostgreSQL72Context.m: remove abort() :( Mon Mar 18 12:53:42 CET 2002 Jan41 Reichmann * PostgreSQLValues.m, *Channel.*: add caches for attributes/ add get primary key infos Mon Mar 11 12:02:24 2002 Jan41 Reichmann * PostgreSQLValues.m: fixed CAL-FORMAT Entry Thu Aug 16 14:13:10 2001 Martin Hoerning * PostgreSQLChannel.m: fixed RETAIN-BUGS, removed LOGS Fri Jul 27 17:32:17 2001 Jan Reichmann * EOAttribute+PostgreSQL.m: fixed timezone bugs Thu Jul 5 14:08:11 2001 Helge Hess * reactivated for SkyDev41 Tue Feb 2 09:01:10 1999 Helge Hess * created ChangeLog SOPE/sope-gdl1/PostgreSQL/common.h0000644000000000000000000000250115004363604015560 0ustar rootroot/* common.h Copyright (C) 2000-2004 SKYRIX Software AG and Helge Hess Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___PostgreSQL_common_H___ #define ___PostgreSQL_common_H___ #include #include #include #if !LIB_FOUNDATION_LIBRARY # include # include #endif #include #endif /* ___PostgreSQL_common_H___ */ SOPE/sope-gdl1/PostgreSQL/PostgreSQL72Channel.m0000644000000000000000000005431315004363604017752 0ustar rootroot/* PostgreSQL72Channel.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2008 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #import "common.h" #import "PostgreSQL72Channel.h" #import "PostgreSQL72Adaptor.h" #import "PostgreSQL72Exception.h" #import "NSString+PostgreSQL72.h" #import "PostgreSQL72Values.h" #import "EOAttribute+PostgreSQL72.h" #include "PGConnection.h" #include "pgconfig.h" #import #ifndef MIN # define MIN(x, y) ((x > y) ? y : x) #endif // TODO: what does this do? #define MAX_CHAR_BUF 16384 @interface PostgreSQL72Channel(Privates) - (void)_resetEvaluationState; @end @implementation PostgreSQL72Channel #if NG_SET_CLIENT_ENCODING static NSString *PGClientEncoding = @"UTF8"; #endif static int MaxOpenConnectionCount = -1; static BOOL debugOn = NO; static NSNull *null = nil; static NSNumber *yesObj = nil; static Class StringClass = Nil; static Class MDictClass = Nil; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; if (null == nil) null = [[NSNull null] retain]; if (yesObj == nil) yesObj = [[NSNumber numberWithBool:YES] retain]; StringClass = [NSString class]; MDictClass = [NSMutableDictionary class]; MaxOpenConnectionCount = [ud integerForKey:@"PGMaxOpenConnectionCount"]; if (MaxOpenConnectionCount < 2) MaxOpenConnectionCount = 50; debugOn = [ud boolForKey:@"PGDebugEnabled"]; } - (id)initWithAdaptorContext:(EOAdaptorContext*)_adaptorContext { if ((self = [super initWithAdaptorContext:_adaptorContext])) { [self setDebugEnabled:debugOn]; self->_attributesForTableName = [[MDictClass alloc] initWithCapacity:16]; self->_primaryKeysNamesForTableName = [[MDictClass alloc] initWithCapacity:16]; } return self; } /* collection */ - (void)dealloc { [self _resetEvaluationState]; if ([self isOpen]) [self closeChannel]; [self->_attributesForTableName release]; [self->_primaryKeysNamesForTableName release]; [super dealloc]; } /* NSCopying methods */ - (id)copyWithZone:(NSZone *)zone { return [self retain]; } /* debugging */ - (void)setDebugEnabled:(BOOL)_flag { self->isDebuggingEnabled = _flag; } - (BOOL)isDebugEnabled { return self->isDebuggingEnabled; } - (void)receivedMessage:(NSString *)_message { [self logWithFormat: @"message: %@", _message]; } static void _pgMessageProcessor(void *_channel, const char *_msg) __attribute__((unused)); static void _pgMessageProcessor(void *_channel, const char *_msg) { [(id)_channel receivedMessage: _msg ? [StringClass stringWithUTF8String:_msg] : nil]; } /* cleanup */ - (void)_resetResults { [self->resultSet clear]; [self->resultSet release]; self->resultSet = nil; } /* open/close */ static int openConnectionCount = 0; - (BOOL)isOpen { return [self->connection isValid]; } - (BOOL)openChannel { PostgreSQL72Adaptor *adaptor; if ([self->connection isValid]) { NSLog(@"%s: Connection already open !!!", __PRETTY_FUNCTION__); return NO; } adaptor = (PostgreSQL72Adaptor *)[adaptorContext adaptor]; if (![super openChannel]) return NO; #if HEAVY_DEBUG NSLog(@"+++++++++ %s: openConnectionCount %d", __PRETTY_FUNCTION__, openConnectionCount); #endif if (openConnectionCount > MaxOpenConnectionCount) { [PostgreSQL72CouldNotOpenChannelException raise:@"NoMoreConnections" format: @"cannot open a additional connection !"]; return NO; } self->connection = [[PGConnection alloc] initWithHostName:[adaptor serverName] port:[(id)[adaptor port] stringValue] options:[adaptor options] tty:[adaptor tty] database:[adaptor databaseName] login:[adaptor loginName] password:[adaptor loginPassword]]; if (![self->connection isValid]) { // could not login .. NSLog(@"WARNING: could not open pgsql channel to %@@%@ host %@:%@", [adaptor loginName], [adaptor databaseName], [adaptor serverName], [adaptor port]); return NO; } /* PQstatus */ if (![self->connection isConnectionOK]) { NSLog(@"could not open channel to %@@%@", [adaptor databaseName], [adaptor serverName]); [self->connection finish]; [self->connection release]; self->connection = nil; return NO; } /* set message callback */ [self->connection setNoticeProcessor:_pgMessageProcessor context:self]; /* set client encoding */ #if NG_SET_CLIENT_ENCODING if (![self->connection setClientEncoding:PGClientEncoding]) { NSLog(@"WARNING: could not set client encoding to: '%@'", PGClientEncoding); } #endif /* log */ if (isDebuggingEnabled) NSLog(@"PostgreSQL72 connection established: %@", self->connection); #if HEAVY_DEBUG NSLog(@"---------- %s: %@ opens channel count[%d]", __PRETTY_FUNCTION__, self, openConnectionCount); #endif openConnectionCount++; if (isDebuggingEnabled) { NSLog(@"PostgreSQL72 channel 0x%p opened (connection=%@, count=%d)", self, self->connection, openConnectionCount); } return YES; } - (void)primaryCloseChannel { self->tupleCount = 0; self->fieldCount = 0; self->containsBinaryData = NO; if (self->fieldInfo) { free(self->fieldInfo); self->fieldInfo = NULL; } [self _resetResults]; [self->cmdStatus release]; self->cmdStatus = nil; [self->cmdTuples release]; self->cmdTuples = nil; if (self->connection) { [self->connection finish]; #if HEAVY_DEBUG NSLog(@"---------- %s: %@ close channel count[%d]", __PRETTY_FUNCTION__, self, openConnectionCount); #endif openConnectionCount--; if (isDebuggingEnabled) { NSLog(@"PostgreSQL72 connection dropped 0x%p (channel=0x%p, count=%d)", self->connection, self, openConnectionCount); } [self->connection release]; self->connection = nil; } } - (void)closeChannel { [super closeChannel]; [self primaryCloseChannel]; } /* fetching rows */ - (void)cancelFetch { if (![self isOpen]) { [PostgreSQL72Exception raise:@"ChannelNotOpenException" format:@"No fetch in progress, connection is not open" @" (channel=%@)", self]; } #if HEAVY_DEBUG NSLog(@"canceling fetch (%i tuples remaining).", (self->tupleCount - self->currentTuple)); #endif self->tupleCount = 0; self->currentTuple = 0; self->fieldCount = 0; self->containsBinaryData = NO; if (self->fieldInfo) { free(self->fieldInfo); self->fieldInfo = NULL; } [self _resetResults]; [self->cmdStatus release]; self->cmdStatus = nil; [self->cmdTuples release]; self->cmdTuples = nil; /* new caches which require a constant _attributes argument */ if (self->fieldIndices) free(self->fieldIndices); self->fieldIndices = NULL; if (self->fieldKeys) free(self->fieldKeys); self->fieldKeys = NULL; if (self->fieldValues) free(self->fieldValues); self->fieldValues = NULL; [super cancelFetch]; } - (NSArray *)describeResults:(BOOL)_beautifyNames { int cnt; NSMutableArray *result; NSMutableDictionary *usedNames; if (![self isFetchInProgress]) { [PostgreSQL72Exception raise:@"NoFetchInProgress" format:@"No fetch in progress (channel=%@)", self]; } result = [[NSMutableArray alloc] initWithCapacity:self->fieldCount]; usedNames = [[MDictClass alloc] initWithCapacity:self->fieldCount]; for (cnt = 0; cnt < self->fieldCount; cnt++) { EOAttribute *attribute = nil; NSString *columnName; NSString *attrName; columnName = [[StringClass alloc] initWithUTF8String:self->fieldInfo[cnt].name]; attrName = _beautifyNames ? [columnName _pgModelMakeInstanceVarName] : columnName; if ([[usedNames objectForKey:attrName] boolValue]) { // TODO: move name generation code to different method! int cnt2 = 0; char buf[64]; NSString *newAttrName = nil; for (cnt2 = 2; cnt2 < 100; cnt2++) { NSString *s; sprintf(buf, "%i", cnt2); s = [[StringClass alloc] initWithUTF8String:buf]; newAttrName = [attrName stringByAppendingString:s]; [s release]; s= nil; if (![[usedNames objectForKey:newAttrName] boolValue]) { attrName = newAttrName; break; } } } [usedNames setObject:yesObj forKey:attrName]; attribute = [[EOAttribute alloc] init]; [attribute setName:attrName]; [attribute setColumnName:columnName]; //NSLog(@"column: %@", columnName); [attribute loadValueClassAndTypeUsingPostgreSQLType: self->fieldInfo[cnt].type size:self->fieldInfo[cnt].size modification:self->fieldInfo[cnt].modification binary:self->containsBinaryData]; [result addObject:attribute]; [columnName release]; columnName = nil; [attribute release]; attribute = nil; } [usedNames release]; usedNames = nil; return [result autorelease]; } - (void)_fillFieldNamesForAttributes:(NSArray *)_attributes count:(unsigned)attrCount { // Note: this optimization requires that the "_attributes" array does // note change between invocations! // TODO: should add a sanity check for that! NSMutableArray *fieldNames; unsigned nFields, i; unsigned cnt; if (self->fieldIndices) return; self->fieldIndices = calloc(attrCount + 2, sizeof(int)); // TODO: we could probably cache the field-name array for much more speed ! fieldNames = [[NSMutableArray alloc] initWithCapacity:32]; nFields = [self->resultSet fieldCount]; for (i = 0; i < nFields; i++) [fieldNames addObject:[self->resultSet fieldNameAtIndex:i]]; for (cnt = 0; cnt < attrCount; cnt++) { EOAttribute *attribute; #ifndef GDL_USE_PQFNUMBER_INDEX NSUInteger res; #endif attribute = [_attributes objectAtIndex:cnt]; #if GDL_USE_PQFNUMBER_INDEX self->fieldIndices[cnt] = [self->resultSet indexOfFieldNamed:[attribute columnName]]; if (self->fieldIndices[cnt] == -1) { [PostgreSQL72Exception raiseWithFormat: @"attribute %@ not covered by query", attribute]; } #else res = [fieldNames indexOfObject:[attribute columnName]]; if (res == NSNotFound) { [PostgreSQL72Exception raiseWithFormat: @"attribute %@ not covered by query", attribute]; } self->fieldIndices[cnt] = (int)res; #endif [fieldNames replaceObjectAtIndex:self->fieldIndices[cnt] withObject:null]; } [fieldNames release]; fieldNames = nil; } - (NSMutableDictionary *)primaryFetchAttributes:(NSArray *)_attributes withZone:(NSZone *)_zone { NSMutableDictionary *row; unsigned attrCount; int *indices; unsigned cnt, fieldDictCount; if (self->currentTuple == self->tupleCount) { if (self->resultSet != nil) [self cancelFetch]; return nil; } attrCount = [_attributes count]; [self _fillFieldNamesForAttributes:_attributes count:attrCount]; indices = self->fieldIndices; if (self->fieldKeys == NULL) self->fieldKeys = calloc(attrCount + 1, sizeof(NSString *)); if (self->fieldValues == NULL) self->fieldValues = calloc(attrCount + 1, sizeof(id)); fieldDictCount = 0; for (cnt = 0; cnt < attrCount; cnt++) { EOAttribute *attribute; NSString *attrName; id value = nil; Class valueClass = Nil; const char *pvalue; int vallen; attribute = [_attributes objectAtIndex:cnt]; attrName = [attribute name]; if ([self->resultSet isNullTuple:self->currentTuple atIndex:indices[cnt]]){ self->fieldKeys[fieldDictCount] = attrName; self->fieldValues[fieldDictCount] = null; fieldDictCount++; continue; } valueClass = NSClassFromString([attribute valueClassName]); if (valueClass == Nil) { NSLog(@"ERROR(%s): %@: got no value class for column:\n" @" attribute=%@\n type=%@", __PRETTY_FUNCTION__, self, attrName, [attribute externalType]); continue; } pvalue = [self->resultSet rawValueOfTuple:self->currentTuple atIndex:indices[cnt]]; vallen = [self->resultSet lengthOfTuple:self->currentTuple atIndex:indices[cnt]]; if (self->containsBinaryData) { // pvalue is stored in internal representation value = [valueClass valueFromBytes:pvalue length:vallen postgreSQLType:[attribute externalType] attribute:attribute adaptorChannel:self]; } else { // pvalue is ascii string value = [valueClass valueFromCString:pvalue length:vallen postgreSQLType:[attribute externalType] attribute:attribute adaptorChannel:self]; } if (value == nil) { NSLog(@"ERROR(%s): %@: got no value for column: attribute=%@\n valueClass=%@\n type=%@", __PRETTY_FUNCTION__, self, attrName, NSStringFromClass(valueClass), [attribute externalType]); continue; } /* add to dictionary */ self->fieldKeys[fieldDictCount] = attrName; self->fieldValues[fieldDictCount] = value; fieldDictCount++; } self->currentTuple++; // TODO: we would need to have a copy on write dict here, ideally with // the keys being reused for each fetch-loop row = [[MDictClass alloc] initWithObjects:self->fieldValues forKeys:self->fieldKeys count:fieldDictCount]; return [row autorelease]; } /* sending sql to server */ - (void)_resetEvaluationState { self->isFetchInProgress = NO; self->tupleCount = 0; self->fieldCount = 0; self->currentTuple = 0; self->containsBinaryData = NO; if (self->fieldInfo) { free(self->fieldInfo); self->fieldInfo = NULL; } /* new caches which require a constant _attributes argument */ if (self->fieldIndices) free(self->fieldIndices); self->fieldIndices = NULL; if (self->fieldKeys) free(self->fieldKeys); self->fieldKeys = NULL; if (self->fieldValues) free(self->fieldValues); self->fieldValues = NULL; } - (NSException *)_processEvaluationTuplesOKForExpression:(NSString *)_sql { int i; self->isFetchInProgress = YES; self->tupleCount = [self->resultSet tupleCount]; self->fieldCount = [self->resultSet fieldCount]; self->containsBinaryData = [self->resultSet containsBinaryTuples]; self->fieldInfo = calloc(self->fieldCount + 1, sizeof(PostgreSQL72FieldInfo)); for (i = 0; i < self->fieldCount; i++) { self->fieldInfo[i].name = PQfname(self->resultSet->results, i); self->fieldInfo[i].type = PQftype(self->resultSet->results, i); self->fieldInfo[i].size = [self->resultSet fieldSizeAtIndex:i]; self->fieldInfo[i].modification = [self->resultSet modifierAtIndex:i]; } self->cmdStatus = [[self->resultSet commandStatus] copy]; self->cmdTuples = [[self->resultSet commandTuples] copy]; if (delegateRespondsTo.didEvaluateExpression) [delegate adaptorChannel:self didEvaluateExpression:_sql]; #if HEAVY_DEBUG NSLog(@"tuples %i fields %i status %@", self->tupleCount, self->fieldCount, self->cmdStatus); #endif return nil; } - (NSException *)_handleBadResponseError { NSString *s; [self _resetResults]; s = [NSString stringWithFormat:@"bad pgsql response (channel=%@): %@", self, [self->connection errorMessage]]; return [PostgreSQL72Exception exceptionWithName:@"PostgreSQL72BadResponse" reason:s userInfo:nil]; } - (NSException *)_handleNonFatalEvaluationError { NSString *s; [self _resetResults]; s = [NSString stringWithFormat:@"pgsql error (channel=%@): %@", self, [self->connection errorMessage]]; return [PostgreSQL72Exception exceptionWithName:@"PostgreSQL72Error" reason:s userInfo:nil]; } - (NSException *)_handleFatalEvaluationError { NSString *s; [self _resetResults]; s = [NSString stringWithFormat:@"fatal pgsql error (channel=%@): %@", self, [self->connection errorMessage]]; return [PostgreSQL72Exception exceptionWithName:@"PostgreSQL72FatalError" reason:s userInfo:nil]; } - (NSException *)evaluateExpressionX:(NSString *)_expression { BOOL result; *(&result) = YES; if (_expression == nil) { return [NSException exceptionWithName:NSInvalidArgumentException reason:@"parameter for evaluateExpression: " @"must not be null" userInfo:nil]; } *(&_expression) = [[_expression mutableCopy] autorelease]; if (delegateRespondsTo.willEvaluateExpression) { EODelegateResponse response; response = [delegate adaptorChannel:self willEvaluateExpression: (NSMutableString *)_expression]; if (response == EODelegateRejects) { return [NSException exceptionWithName:@"EODelegateRejects" reason:@"delegate rejected insert" userInfo:nil]; } if (response == EODelegateOverrides) return nil; } if (![self isOpen]) { return [PostgreSQL72Exception exceptionWithName:@"ChannelNotOpenException" reason: @"PostgreSQL72 connection is not open" userInfo:nil]; } if (self->resultSet != nil) { return [PostgreSQL72Exception exceptionWithName: @"CommandInProgressException" reason:@"an evaluation is in progress" userInfo:nil]; } if (isDebuggingEnabled) NSLog(@"PG0x%p SQL: %@", self, _expression); [self _resetEvaluationState]; self->resultSet = [[self->connection execute:_expression] retain]; if (self->resultSet == nil) { return [self _handleFatalEvaluationError]; } /* process results */ switch (PQresultStatus(self->resultSet->results)) { case PGRES_EMPTY_QUERY: case PGRES_COMMAND_OK: [self _resetResults]; if (delegateRespondsTo.didEvaluateExpression) [delegate adaptorChannel:self didEvaluateExpression:_expression]; return nil; case PGRES_TUPLES_OK: return [self _processEvaluationTuplesOKForExpression:_expression]; case PGRES_COPY_OUT: case PGRES_COPY_IN: [self _resetResults]; return [PostgreSQL72Exception exceptionWithName:@"UnsupportedOperation" reason:@"copy(out|in) not supported" userInfo:nil]; case PGRES_BAD_RESPONSE: return [self _handleBadResponseError]; case PGRES_NONFATAL_ERROR: return [self _handleNonFatalEvaluationError]; case PGRES_FATAL_ERROR: return [self _handleFatalEvaluationError]; default: return [NSException exceptionWithName:@"PostgreSQLEvalFailed" reason:@"generic reason" userInfo:nil]; } } - (BOOL)evaluateExpression:(NSString *)_sql { NSException *e; NSString *n; if ((e = [self evaluateExpressionX:_sql]) == nil) return YES; /* for compatibility with non-X methods, translate some errors to a bool */ n = [e name]; if ([n isEqualToString:@"EOEvaluationError"]) return NO; if ([n isEqualToString:@"EODelegateRejects"]) return NO; [e raise]; return NO; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if (self->connection) [ms appendFormat:@" connection=%@", self->connection]; else [ms appendString:@" not-connected"]; [ms appendString:@">"]; return ms; } @end /* PostgreSQL72Channel */ @implementation PostgreSQL72Channel(PrimaryKeyGeneration) - (NSDictionary *)primaryKeyForNewRowWithEntity:(EOEntity *)_entity { NSArray *pkeys; PostgreSQL72Adaptor *adaptor; NSString *seqName, *seq; NSDictionary *pkey; pkeys = [_entity primaryKeyAttributeNames]; adaptor = (id)[[self adaptorContext] adaptor]; seqName = [adaptor primaryKeySequenceName]; pkey = nil; seq = nil; seq = [seqName length] > 0 ? [StringClass stringWithFormat:@"SELECT NEXTVAL ('%@')", seqName] : (id)[adaptor newKeyExpression]; // TODO: since we use evaluateExpressionX, we should not see exceptions? NS_DURING { if ([self evaluateExpressionX:seq] == nil) { id key = nil; if (self->tupleCount > 0) { if ([self->resultSet isNullTuple:0 atIndex:0]) key = [null retain]; else { const char *pvalue; if (self->containsBinaryData) { #if COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY NSLog(@"%s: binary data not implemented!", __PRETTY_FUNCTION__); #else [self notImplemented:_cmd]; #endif } pvalue = [self->resultSet rawValueOfTuple:0 atIndex:0]; if (pvalue) key = [[NSNumber alloc] initWithInt:atoi(pvalue)]; } } [self cancelFetch]; if (key) { pkey = [NSDictionary dictionaryWithObject:key forKey:[pkeys objectAtIndex:0]]; [key release]; key = nil; } } } NS_HANDLER pkey = nil; NS_ENDHANDLER; return pkey; } @end /* PostgreSQL72Channel(PrimaryKeyGeneration) */ void __link_PostgreSQL72Channel() { // used to force linking of object file __link_PostgreSQL72Channel(); } SOPE/sope-gdl1/PostgreSQL/PostgreSQL72Context.h0000644000000000000000000000233515004363604020016 0ustar rootroot/* PostgreSQL72Context.h Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___PostgreSQL72_Context_H___ #define ___PostgreSQL72_Context_H___ #import @interface PostgreSQL72Context : EOAdaptorContext - (BOOL)primaryBeginTransaction; - (BOOL)primaryCommitTransaction; - (BOOL)primaryRollbackTransaction; @end #endif SOPE/sope-gdl1/PostgreSQL/NSCalendarDate+PGVal.m0000644000000000000000000001454015004363604020020 0ustar rootroot/* NSCalendarDate+PGVal.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2008 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #include "PostgreSQL72Channel.h" #include "common.h" // Sybase Date: Oct 21 1997 9:52:26:000PM static NSString *PGSQL_DATETIME_FORMAT = @"%b %d %Y %I:%M:%S:000%p"; @implementation NSCalendarDate(PostgreSQL72Values) /* Format: '2001-07-26 14:00:00+02' (len 22) '2001-07-26 14:00:00+09:30' (len 25) '2008-01-31 14:00:57.249+01' (len 26) 0123456789012345678901234 Matthew: "07/25/2003 06:00:00 CDT". */ static Class NSCalDateClass = Nil; static NSTimeZone *DefServerTimezone = nil; static NSTimeZone *gmt = nil; static NSTimeZone *gmt01 = nil; static NSTimeZone *gmt02 = nil; + (id)valueFromCString:(const char *)_cstr length:(int)_length postgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute adaptorChannel:(PostgreSQL72Channel *)_channel { char buf[28]; char *p; NSTimeZone *attrTZ; NSCalendarDate *date; int year, month, day, hour, min, sec, tzOffset = 0; char *tok; if (_length == 0) return nil; if (_length != 22 && _length != 25 && _length != 26) { // TODO: add support for "2001-07-26 14:00:00" (len=19) // TBD: add support for "2008-01-31 14:00:57.249+01" (len=26) NSLog(@"ERROR(%s): unexpected string '%s' for date type '%@', returning " @"now (expected format: '2001-07-26 14:00:00+02')", __PRETTY_FUNCTION__, _cstr, _type); return [NSCalendarDate date]; } strncpy(buf, _cstr, 26); buf[26] = '\0'; tok = buf; year = atoi(strsep(&tok, "-")); month = atoi(strsep(&tok, "-")); day = atoi(strsep(&tok, " ")); hour = atoi(strsep(&tok, ":")); min = atoi(strsep(&tok, ":")); tzOffset = 0; if (tok != NULL && (p = strchr(tok, '+')) != NULL) tzOffset = +1; else if (tok != NULL && (p = strchr(tok, '-')) != NULL) tzOffset = -1; else tzOffset = 0; // TBD: warn? if (tzOffset != 0) { int tzHours, tzMins = 0; p++; // skip +/- tzHours = atoi(strsep(&p, ":")); if (p != NULL) tzMins = atoi(p); tzMins = tzHours * 60 + tzMins; tzOffset = tzOffset < 0 ? -tzMins : tzMins; } /* extract seconds */ sec = atoi(strsep(&tok, ":+.")); #if HEAVY_DEBUG NSLog(@"DATE: %s => %04i-%02i-%02i %02i:%02i:%02i", buf, year, month, day, hour, min, sec); #endif #if HEAVY_DEBUG NSLog(@"DATE: %s => OFFSET %i", _cstr, tzOffset); #endif /* TODO: cache all timezones (just 26 ;-) */ switch (tzOffset) { case 0: if (gmt == nil) { gmt = [[NSTimeZone timeZoneForSecondsFromGMT:0] retain]; NSAssert(gmt, @"could not create GMT timezone?!"); } attrTZ = gmt; break; case 60: if (gmt01 == nil) { gmt01 = [[NSTimeZone timeZoneForSecondsFromGMT:3600] retain]; NSAssert(gmt01, @"could not create GMT+01 timezone?!"); } attrTZ = gmt01; break; case 120: if (gmt02 == nil) { gmt02 = [[NSTimeZone timeZoneForSecondsFromGMT:7200] retain]; NSAssert(gmt02, @"could not create GMT+02 timezone?!"); } attrTZ = gmt02; break; default: { /* cache the first, "alternative" timezone */ static int firstTZOffset = 0; // can use 0 since GMT is a separate case static NSTimeZone *firstTZ = nil; if (firstTZOffset == 0) { firstTZOffset = tzOffset; firstTZ = [[NSTimeZone timeZoneForSecondsFromGMT:(tzOffset*60)] retain]; } attrTZ = (firstTZOffset == tzOffset) ? firstTZ : [NSTimeZone timeZoneForSecondsFromGMT:(tzOffset * 60)]; break; } } if (NSCalDateClass == Nil) NSCalDateClass = [NSCalendarDate class]; date = [NSCalDateClass dateWithYear:year month:month day:day hour:hour minute:min second:sec timeZone:attrTZ]; if (date == nil) { NSLog(@"ERROR(%s): could not construct date from string '%s': " @"year=%i,month=%i,day=%i,hour=%i,minute=%i,second=%i, tz=%@", __PRETTY_FUNCTION__, _cstr, year, month, day, hour, min, sec, attrTZ); } return date; } + (id)valueFromBytes:(const void *)_bytes length:(int)_length postgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute adaptorChannel:(PostgreSQL72Channel *)_channel { #if COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY NSLog(@"%s: not implemented!", __PRETTY_FUNCTION__); return nil; #else return [self notImplemented:_cmd]; #endif } - (NSString *)stringValueForPostgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute { #if 0 NSString *format; #endif EOQuotedExpression *expr; NSTimeZone *serverTimeZone; NSString *format; NSString *val; if ((serverTimeZone = [_attribute serverTimeZone]) == nil ) { if (DefServerTimezone == nil) { DefServerTimezone = [[NSTimeZone localTimeZone] retain]; NSLog(@"Note: PostgreSQL72 adaptor using timezone '%@' as default", DefServerTimezone); } serverTimeZone = DefServerTimezone; } #if 0 format = [_attribute calendarFormat]; #else /* hm, why is that? */ format = @"%Y-%m-%d %H:%M:%S%z"; #endif if (format == nil) format = PGSQL_DATETIME_FORMAT; [self setTimeZone:serverTimeZone]; val = [self descriptionWithCalendarFormat:format]; expr = [[EOQuotedExpression alloc] initWithExpression:val quote:@"\'" escape:@"\\'"]; val = [[expr expressionValueForContext:nil] retain]; [expr release]; return [val autorelease]; } @end /* NSCalendarDate(PostgreSQL72Values) */ SOPE/sope-gdl1/PostgreSQL/PGConnection.m0000644000000000000000000001311015004363604016621 0ustar rootroot/* PGConnection.m Copyright (C) 2004-2006 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "PGConnection.h" #include "common.h" #include #include "pgconfig.h" @implementation PGConnection static BOOL debugOn = NO; - (id)initWithHostName:(NSString *)_host port:(NSString *)_port options:(NSString *)_options tty:(NSString *)_tty database:(NSString *)_dbname login:(NSString *)_login password:(NSString *)_pwd { if ((self = [self init])) { NSException *error; error = [self connectWithHostName:_host port:_port options:_options tty:_tty database:_dbname login:_login password:_pwd]; if (error != nil) { if (debugOn) NSLog(@"%s: could not connect: %@", __PRETTY_FUNCTION__, error); [self release]; return nil; } } return self; } - (void)dealloc { [self finish]; [super dealloc]; } /* support */ - (const char *)_cstrFromString:(NSString *)_s { // TODO: fix API, check what the API string encoding is return [_s UTF8String]; } - (NSString *)_stringFromCString:(const char *)_cstr { return [NSString stringWithUTF8String:_cstr]; } /* accessors */ - (BOOL)isValid { return self->_connection != NULL ? YES : NO; } /* errors */ - (NSException *)_makeConnectException:(const char *)_func { return [NSException exceptionWithName:@"PGConnectFailed" reason:[NSString stringWithCString:_func] userInfo:nil]; } /* connect operations */ - (void)_disconnect { if (self->_connection != NULL) [self finish]; } - (NSException *)startConnectWithInfo:(NSString *)_conninfo { [self _disconnect]; self->_connection = PQconnectStart([self _cstrFromString:_conninfo]); if (self->_connection == NULL) return [self _makeConnectException:__PRETTY_FUNCTION__]; return nil; } // TODO: add method for polling connect status - (NSException *)connectWithInfo:(NSString *)_conninfo { [self _disconnect]; self->_connection = PQconnectdb([self _cstrFromString:_conninfo]); if (self->_connection == NULL) return [self _makeConnectException:__PRETTY_FUNCTION__]; [self execute: @"SET standard_conforming_strings TO 'on'"]; return nil; } - (NSException *)connectWithHostName:(NSString *)_host port:(NSString *)_port options:(NSString *)_options tty:(NSString *)_tty database:(NSString *)_dbname login:(NSString *)_login password:(NSString *)_pwd { [self _disconnect]; self->_connection = PQsetdbLogin([self _cstrFromString:_host], [self _cstrFromString:_port], [self _cstrFromString:_options], [self _cstrFromString:_tty], [self _cstrFromString:_dbname], [self _cstrFromString:_login], [self _cstrFromString:_pwd]); if (self->_connection == NULL) return [self _makeConnectException:__PRETTY_FUNCTION__]; /* The PG adaptor always produce conform strings. We set this parameter to make sure the "\" character is never interpreted as an escape character, unless otherwise specified (by using E'...'). */ [self execute: @"SET standard_conforming_strings TO 'on'"]; return nil; } - (void)finish { if (self->_connection != NULL) { PQfinish(self->_connection); self->_connection = NULL; } } - (BOOL)isConnectionOK { if (![self isValid]) return NO; return PQstatus(self->_connection) == CONNECTION_OK ? YES : NO; } /* message callbacks */ - (BOOL)setNoticeProcessor:(void *)_callback context:(void *)_ctx { #if NG_HAS_NOTICE_PROCESSOR PQsetNoticeProcessor(self->_connection, _callback, _ctx); return YES; // TODO: improve error handling #else return NO; #endif } /* settings */ - (BOOL)setClientEncoding:(NSString *)_encoding { return PQsetClientEncoding(self->_connection, [self _cstrFromString:_encoding]) == 0 ? YES : NO; } /* errors */ - (NSString *)errorMessage { if (![self isValid]) return nil; return [self _stringFromCString:PQerrorMessage(self->_connection)]; } /* queries */ - (void *)rawExecute:(NSString *)_sql { return PQexec(self->_connection, [self _cstrFromString:_sql]); } - (void)clearRawResults:(void *)_ptr { if (_ptr == NULL) return; PQclear(_ptr); } - (PGResultSet *)execute:(NSString *)_sql { void *handle; if ((handle = [self rawExecute:_sql]) == NULL) return nil; return [[[PGResultSet alloc] initWithConnection:self handle:handle] autorelease]; } /* debugging */ - (BOOL)isDebuggingEnabled { return debugOn; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]: ", self, NSStringFromClass([self class])]; if ([self isValid]) [ms appendFormat:@" connection=0x%p", self->_connection]; else [ms appendString:@" not-connected"]; [ms appendString:@">"]; return ms; } @end /* PGConnection */ SOPE/sope-gdl1/PostgreSQL/PostgreSQL72Adaptor.h0000644000000000000000000000433015004363604017761 0ustar rootroot/* PostgreSQL72Adaptor.h Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2004 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___PostgreSQL72_Adaptor_H___ #define ___PostgreSQL72_Adaptor_H___ /* The PostgreSQL72 adaptor. The connection dictionary of this adaptor understands these keys: hostName port options tty userName password databaseName The adaptor is based on libpq. */ #import #import #import @class NSString, NSMutableDictionary, NSArray; @interface PostgreSQL72Adaptor : EOAdaptor { } - (id)initWithName:(NSString *)_name; /* connection management */ - (NSString *)serverName; - (NSString *)loginName; - (NSString *)loginPassword; - (NSString *)databaseName; - (NSString *)port; - (NSString *)options; - (NSString *)tty; - (NSString *)newKeyExpression; /* sequence for primary key generation */ - (NSString *)primaryKeySequenceName; /* value formatting */ - (id)formatValue:(id)value forAttribute:(EOAttribute *)attribute; /* attribute typing */ - (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr; /* classes used */ - (Class)adaptorContextClass; // PostgreSQL72Context - (Class)adaptorChannelClass; // PostgreSQL72Channel - (Class)expressionClass; // PostgreSQL72Expression @end #endif SOPE/sope-gdl1/PostgreSQL/PostgreSQL72Adaptor.m0000644000000000000000000001103215004363604017763 0ustar rootroot/* PostgreSQL72Adaptor.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2004 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #include "PostgreSQL72Adaptor.h" #include "PostgreSQL72Context.h" #include "PostgreSQL72Channel.h" #include "PostgreSQL72Expression.h" #include "PostgreSQL72Values.h" #include "PGConnection.h" @implementation PostgreSQL72Adaptor static BOOL debugOn = NO; - (id)initWithName:(NSString *)_name { if ((self = [super initWithName:_name])) { } return self; } - (void)gcFinalize { } - (void)dealloc { // NSLog(@"%s", __PRETTY_FUNCTION__); [self gcFinalize]; [super dealloc]; } /* NSCopying methods */ - (id)copyWithZone:(NSZone *)_zone { return [self retain]; } /* connections */ - (NSString *)_copyOfConDictString:(NSString *)_key { return [[[[self connectionDictionary] objectForKey:_key] copy] autorelease]; } - (NSString *)serverName { NSString *serverName; serverName = [[self connectionDictionary] objectForKey:@"hostName"]; if (serverName == nil) { // lookup env-variable serverName = [[[NSProcessInfo processInfo] environment] objectForKey:@"PGHOST"]; } return [[serverName copy] autorelease]; } - (NSString *)loginName { return [self _copyOfConDictString:@"userName"]; } - (NSString *)loginPassword { return [self _copyOfConDictString:@"password"]; } - (NSString *)databaseName { return [self _copyOfConDictString:@"databaseName"]; } - (NSString *)port { return [self _copyOfConDictString:@"port"]; } - (NSString *)options { return [self _copyOfConDictString:@"options"]; } - (NSString *)tty { return [self _copyOfConDictString:@"tty"]; } /* sequence for primary key generation */ - (NSString *)primaryKeySequenceName { NSString *seqName; seqName = [[self pkeyGeneratorDictionary] objectForKey:@"primaryKeySequenceName"]; return [[seqName copy] autorelease]; } - (NSString *)newKeyExpression { NSString *newKeyExpr; newKeyExpr = [[self pkeyGeneratorDictionary] objectForKey:@"newKeyExpression"]; return [[newKeyExpr copy] autorelease]; } /* formatting */ - (NSString *)charConvertExpressionForAttributeNamed:(NSString *)_attrName { return _attrName; } - (id)formatValue:(id)value forAttribute:(EOAttribute *)attribute { /* This formats values into SQL constants, eg: @"blah" will be converted to 'blah' */ NSString *result; result = [value stringValueForPostgreSQLType:[attribute externalType] attribute:attribute]; if (debugOn) { NSLog(@"formatting value '%@'(%@) result '%@'", value, NSStringFromClass([value class]), result); NSLog(@" value class %@ attr %@ attr type %@", [value class], attribute, [attribute externalType]); } return result; } - (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr { return YES; } /* types */ - (BOOL)isValidQualifierType:(NSString *)_typeName { return YES; } /* adaptor info */ - (Class)adaptorContextClass { return [PostgreSQL72Context class]; } - (Class)adaptorChannelClass { return [PostgreSQL72Channel class]; } - (Class)expressionClass { return [PostgreSQL72Expression class]; } @end /* PostgreSQL72Adaptor */ void __linkPostgreSQL72Adaptor(void) { extern void __link_EOAttributePostgreSQL72(); extern void __link_NSStringPostgreSQL72(); extern void __link_PostgreSQL72ChannelModel(); extern void __link_PostgreSQL72Values(); ; [PostgreSQL72Channel class]; [PostgreSQL72Context class]; [PostgreSQL72Exception class]; [PostgreSQL72Expression class]; __link_EOAttributePostgreSQL72(); __link_NSStringPostgreSQL72(); //__link_PostgreSQL72ChannelModel(); __link_PostgreSQL72Values(); __linkPostgreSQL72Adaptor(); } SOPE/sope-gdl1/PostgreSQL/PostgreSQL72Channel.h0000644000000000000000000000451315004363604017742 0ustar rootroot/* PostgreSQL72Channel.h Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2004 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___PostgreSQL72_Channel_H___ #define ___PostgreSQL72_Channel_H___ #include #include @class NSArray, NSString, NSMutableDictionary; @class PGConnection, PGResultSet; typedef struct { const char *name; Oid type; int size; int modification; } PostgreSQL72FieldInfo; @interface PostgreSQL72Channel : EOAdaptorChannel { // connection is valid after an openChannel call PGConnection *connection; // valid during -evaluateExpression: PGResultSet *resultSet; int tupleCount; int fieldCount; BOOL containsBinaryData; PostgreSQL72FieldInfo *fieldInfo; NSString *cmdStatus; NSString *cmdTuples; int currentTuple; // turns on/off channel debugging BOOL isDebuggingEnabled; NSMutableDictionary *_attributesForTableName; NSMutableDictionary *_primaryKeysNamesForTableName; int *fieldIndices; NSString **fieldKeys; id *fieldValues; } - (void)setDebugEnabled:(BOOL)_flag; - (BOOL)isDebugEnabled; @end @interface NSObject(Sybase10ChannelDelegate) - (NSArray*)postgreSQLChannel:(PostgreSQL72Channel *)channel willFetchAttributes:(NSArray *)attributes; - (BOOL)postgreSQLChannel:(PostgreSQL72Channel *)channel willReturnRow:(NSDictionary *)row; @end #endif /* ___PostgreSQL72_Channel_H___ */ SOPE/sope-gdl1/PostgreSQL/COPYING0000644000000000000000000004307615004363604015166 0ustar rootroot GNU GENERAL PUBLIC LICENSE 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 Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy 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., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. SOPE/sope-gdl1/PostgreSQL/fhs.make0000644000000000000000000000122515004363604015540 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) FHS_LIB_DIR=$(CONFIGURE_FHS_INSTALL_LIBDIR) FHS_DB_DIR=$(FHS_LIB_DIR)sope-$(SOPE_MAJOR_VERSION).$(SOPE_MINOR_VERSION)/dbadaptors/ fhs-db-dirs :: $(MKDIRS) $(FHS_DB_DIR) move-bundles-to-fhs :: fhs-db-dirs @echo "moving bundles $(BUNDLE_INSTALL_DIR) to $(FHS_DB_DIR) .." for i in $(BUNDLE_NAME); do \ j="$(FHS_DB_DIR)/$${i}$(BUNDLE_EXTENSION)"; \ if test -d $$j; then rm -r $$j; fi; \ mv "$(BUNDLE_INSTALL_DIR)/$${i}$(BUNDLE_EXTENSION)" $$j; \ done move-to-fhs :: move-bundles-to-fhs after-install :: move-to-fhs endif SOPE/sope-gdl1/PostgreSQL/COPYING.LIB0000644000000000000000000006126115004363604015567 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 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. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-gdl1/PostgreSQL/README0000644000000000000000000000271515004363604015006 0ustar rootrootPostgreSQL Adaptor ================== Install PostgreSQL: cd /INTERNET/suse72/dvd/ cd ap3 rpm -Uvh postgresql.rpm cd ap2 rpm -Uvh postgresql-lib.rpm rpm -Uvh postgresql-server.rpm rpm -Uvh postgresql-devel.rpm Configure PostgreSQL: su - postgres vi .bashrc -> export PGDATA=/var/lib/pgsql/data source .bashrc initdb su - root /etc/rc.d/postgresql start su - postgres createdb OpenGroupware createuser ogo vi data/pg_hba.conf > add line: "host all 192.168.0.1 255.255.255.0 trust" PostgreSQL starten: /etc/rc.d/postgresql restart Configure the Adaptor PGDebugEnabled NOTES ===== Querying the tables of a database --------------------------------- SELECT relname FROM pg_class WHERE ( relkind = 'r') AND relname !~ '^pg_' AND relname !~ '^xinv[0-9]+' ORDER BY relname; und die infos dazu mit: SELECT a.attnum, a.attname, t.typname, a.attlen, a.attnotnull FROM pg_class c, pg_attribute a, pg_type t WHERE c.relname = 'TABELLENNAME_HERE' AND a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid ORDER BY attnum; Quering the databases of a server --------------------------------- SELECT * FROM pg_database You need a database to connect PostgreSQL using libpq, but 'template1' should always be available. Fetch DB-names and their DBA: SELECT DISTINCT dbs.datname, users.usename FROM pg_database dbs, pg_user users WHERE dbs.datdba=users.usesysid SOPE/sope-gdl1/PostgreSQL/PostgreSQL72Exception.m0000644000000000000000000000337115004363604020336 0ustar rootroot/* PostgreSQL72Exception.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "PostgreSQL72Exception.h" #include "common.h" #include @implementation PostgreSQL72Exception + (void)raiseWithFormat:(NSString *)_format, ... { NSString *tmp = nil; va_list ap; va_start(ap, _format); tmp = [[NSString alloc] initWithFormat:_format arguments:ap]; va_end(ap); [tmp autorelease]; [[[self alloc] initWithName:NSStringFromClass([self class]) reason:tmp userInfo:nil] raise]; } @end /* PostgreSQL72Exception */ @implementation PostgreSQL72CouldNotOpenChannelException @end @implementation PostgreSQL72CouldNotConnectException @end @implementation PostgreSQL72CouldNotBindException @end void __link_PostgreSQL72Exception() { // used to force linking of object file __link_PostgreSQL72Exception(); } SOPE/sope-gdl1/PostgreSQL/condict.plist0000644000000000000000000000021615004363604016620 0ustar rootroot{ hostName = "localhost"; userName = "helge"; password = "helgehelge"; databaseName = "hhtest1"; port = 5432; } SOPE/sope-gdl1/PostgreSQL/NSNumber+ExprValue.m0000644000000000000000000000273015004363604017701 0ustar rootroot/* NSNumber+ExprValue.m Copyright (C) 2007 Helge Hess Author: Helge Hess (helge@opengroupware.org) This file is part of the PostgreSQL Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if GNUSTEP_BASE_LIBRARY #include "common.h" @implementation NSNumber(ExprValue) - (NSString *)expressionValueForContext:(id)_context { /* on gstep-base -stringValue of bool's return YES or NO, which seems to be different on Cocoa and liBFoundation. */ static Class BoolClass = Nil; if (BoolClass == Nil) BoolClass = NSClassFromString(@"NSBoolNumber"); if ([self isKindOfClass:BoolClass]) return [self boolValue] ? @"1" : @"0"; return [self stringValue]; } @end /* NSNumber(ExprValue) */ #endif /* GNUSTEP_BASE_LIBRARY */ SOPE/sope-gdl1/PostgreSQL/NSString+PGVal.m0000644000000000000000000000773515004363604016767 0ustar rootroot/* NSString+PGVal.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2006 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "PostgreSQL72Channel.h" #include "common.h" @implementation NSString(PostgreSQL72Values) static Class NSStringClass = Nil; static id (*ctor)(id, SEL, const char *) = NULL; + (id)valueFromCString:(const char *)_cstr length:(int)_length postgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute adaptorChannel:(PostgreSQL72Channel *)_channel { // TODO: would be better if this would return a retained object to avoid // the dreaded autorelease pool if (_cstr == NULL) return nil; if (*_cstr == '\0') return @""; if (NSStringClass == Nil) NSStringClass = [NSString class]; if (ctor == NULL) { ctor = (void *) [NSStringClass methodForSelector:@selector(stringWithUTF8String:)]; } // TODO: cache IMP of selector return ctor != NULL ? ctor(NSStringClass, @selector(stringWithUTF8String:), _cstr) : [NSStringClass stringWithUTF8String:_cstr]; } + (id)valueFromBytes:(const void *)_bytes length:(int)_length postgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute adaptorChannel:(PostgreSQL72Channel *)_channel { #if COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY NSLog(@"%s: not implemented!", __PRETTY_FUNCTION__); return nil; #else return [self notImplemented:_cmd]; #endif } - (NSString *)stringValueForPostgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute { // TODO: all this looks slow ... NSUInteger len, i, strLen, destI; unichar c1; NSString *format, *result; BOOL escaped; unichar *sourceStr, *destStr; if ((len = [_type length]) == 0) return self; c1 = [_type characterAtIndex:0]; switch (c1) { case 'c': case 'C': case 'v': case 'V': case 't': case 'T': { if (len < 4) return self; _type = [_type lowercaseString]; // looks slow if (!([_type hasPrefix:@"char"] || [_type hasPrefix:@"varchar"] || [_type hasPrefix:@"text"])) break; escaped = NO; strLen = [self length]; sourceStr = malloc (sizeof (unichar) * strLen); [self getCharacters: sourceStr]; destStr = malloc (sizeof (unichar) * strLen * 2); destI = 0; for (i = 0; i < strLen; i++) switch (sourceStr[i]) { case '\\': escaped = YES; case '\'': destStr[destI] = sourceStr[i]; destI++; default: destStr[destI] = sourceStr[i]; destI++; } free (sourceStr); result = [[NSString alloc] initWithCharactersNoCopy: destStr length: destI freeWhenDone: YES]; [result autorelease]; if (escaped) format = @"E'%@'"; else format = @"'%@'"; return [NSString stringWithFormat: format, result]; } case 'm': case 'M': { if (len < 5) { if ([[_type lowercaseString] hasPrefix:@"money"]) return [@"$" stringByAppendingString:self]; } break; } } return self; } @end /* NSString(PostgreSQL72Values) */ SOPE/sope-gdl1/PostgreSQL/PGConnection.h0000644000000000000000000000612715004363604016626 0ustar rootroot/* PGConnection.h Copyright (C) 2004-2006 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___PostgreSQL72_PGConnection_H___ #define ___PostgreSQL72_PGConnection_H___ #import @class NSString, NSException; @class PGResultSet; @interface PGConnection : NSObject { @public void *_connection; } - (id)initWithHostName:(NSString *)_host port:(NSString *)_port options:(NSString *)_options tty:(NSString *)_tty database:(NSString *)_dbname login:(NSString *)_login password:(NSString *)_pwd; /* accessors */ - (BOOL)isValid; /* connect operations */ - (NSException *)startConnectWithInfo:(NSString *)_conninfo; // async - (NSException *)connectWithInfo:(NSString *)_conninfo; - (NSException *)connectWithHostName:(NSString *)_host port:(NSString *)_port options:(NSString *)_options tty:(NSString *)_tty database:(NSString *)_dbname login:(NSString *)_login password:(NSString *)_pwd; - (void)finish; - (BOOL)isConnectionOK; /* message callbacks */ - (BOOL)setNoticeProcessor:(void *)_callback context:(void *)_ctx; /* settings */ - (BOOL)setClientEncoding:(NSString *)_encoding; /* errors */ - (NSString *)errorMessage; /* queries */ - (void *)rawExecute:(NSString *)_sql; - (void)clearRawResults:(void *)_ptr; - (PGResultSet *)execute:(NSString *)_sql; /* support */ - (const char *)_cstrFromString:(NSString *)_s; - (NSString *)_stringFromCString:(const char *)_cstr; @end @interface PGResultSet : NSObject { @protected PGConnection *connection; @public void *results; } - (id)initWithConnection:(PGConnection *)_con handle:(void *)_handle; /* accessors */ - (BOOL)isValid; - (BOOL)containsBinaryTuples; - (NSString *)commandStatus; - (NSString *)commandTuples; /* fields */ - (unsigned)fieldCount; - (NSString *)fieldNameAtIndex:(unsigned int)_idx; - (int)indexOfFieldNamed:(NSString *)_name; - (int)fieldSizeAtIndex:(unsigned int)_idx; - (int)modifierAtIndex:(unsigned int)_idx; /* tuples */ - (unsigned int)tupleCount; - (BOOL)isNullTuple:(int)_tuple atIndex:(unsigned int)_idx; - (void *)rawValueOfTuple:(int)_tuple atIndex:(unsigned int)_idx; - (int)lengthOfTuple:(int)_tuple atIndex:(unsigned int)_idx; /* operations */ - (void)clear; @end #endif /* ___PostgreSQL72_PGConnection_H___ */ SOPE/sope-gdl1/PostgreSQL/PostgreSQL72Exception.h0000644000000000000000000000266515004363604020336 0ustar rootroot/* PostgreSQL72Exception.h Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___PostgreSQL72_Exception_H___ #define ___PostgreSQL72_Exception_H___ #import @interface PostgreSQL72Exception : NSException { } + (void)raiseWithFormat:(NSString *)_format, ...; @end @interface PostgreSQL72CouldNotOpenChannelException : PostgreSQL72Exception { } @end @interface PostgreSQL72CouldNotConnectException : PostgreSQL72CouldNotOpenChannelException { } @end @interface PostgreSQL72CouldNotBindException : PostgreSQL72Exception { } @end #endif SOPE/sope-gdl1/PostgreSQL/PostgreSQL72DataTypeMappingException.m0000644000000000000000000000507615004363604023312 0ustar rootroot/* PostgreSQL72Values.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "PostgreSQL72Values.h" #import "common.h" #if !LIB_FOUNDATION_LIBRARY @interface PostgreSQL72DataTypeMappingException(Privates) - (void)setName:(NSString *)_name; - (void)setUserInfo:(NSDictionary *)_ui; @end #endif @implementation PostgreSQL72DataTypeMappingException /* // Unused method: setReason method call is bad and has been removed // from NSException_misc.m because it uses IVARS. Exception reasons should be immutable. - (id)initWithObject:(id)_obj forAttribute:(EOAttribute *)_attr andPostgreSQLType:(NSString *)_dt inChannel:(PostgreSQL72Channel *)_channel; { NSString *typeName = nil; typeName = _dt; if (typeName == nil) typeName = [NSString stringWithFormat:@"Oid[%i]", (int)_dt]; // TODO: fix for Cocoa/gstep Foundation? [self setName:@"DataTypeMappingNotSupported"]; [self setReason:[NSString stringWithFormat: @"mapping between %@ and " @"postgres type %@ is not supported", [_obj description], NSStringFromClass([_obj class]), typeName]]; [self setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys: _attr, @"attribute", _channel, @"channel", _obj, @"object", nil]]; return self; } */ // END unused method (initWithObject) @end /* PostgreSQL72DataTypeMappingException */ void __link_PostgreSQL72Values() { // used to force linking of object file __link_PostgreSQL72Values(); } SOPE/sope-gdl1/PostgreSQL/PostgreSQL72Context.m0000644000000000000000000000523315004363604020023 0ustar rootroot/* PostgreSQL72Context.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2007 Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "PostgreSQL72Context.h" #import "PostgreSQL72Channel.h" #include "common.h" @implementation PostgreSQL72Context - (void)channelDidInit:_channel { if ([channels count] > 0) { [NSException raise:@"TooManyOpenChannelsException" format:@"SybaseAdaptor10 only supports one channel per context"]; } [super channelDidInit:_channel]; } - (BOOL)primaryBeginTransaction { NSException *error; error = [[[channels lastObject] nonretainedObjectValue] evaluateExpressionX:@"BEGIN TRANSACTION"]; if (error == nil) return YES; NSLog(@"%s: could not begin transaction: %@", __PRETTY_FUNCTION__, error); return NO; } - (BOOL)primaryCommitTransaction { NSException *error; error = [[[channels lastObject] nonretainedObjectValue] evaluateExpressionX:@"COMMIT TRANSACTION"]; if (error == nil) return YES; NSLog(@"%s: could not commit transaction: %@", __PRETTY_FUNCTION__, error); return NO; } - (BOOL)primaryRollbackTransaction { NSException *error; error = [[[channels lastObject] nonretainedObjectValue] evaluateExpressionX:@"ROLLBACK TRANSACTION"]; if (error == nil) return YES; NSLog(@"%s: could not rollback transaction: %@", __PRETTY_FUNCTION__, error); return NO; } - (BOOL)canNestTransactions { return NO; } /* NSCopying methods */ - (id)copyWithZone:(NSZone *)zone { // called when the object is used in some datastructures? return [self retain]; } @end /* PostgreSQL72Context */ void __link_PostgreSQL72Context() { // used to force linking of object file __link_PostgreSQL72Context(); } SOPE/sope-gdl1/PostgreSQL/EOAttribute+PostgreSQL72.h0000644000000000000000000000275215004363604020637 0ustar rootroot/* EOAttribute+PostgreSQL72.h Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2004 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___PostgreSQL72_EOAttribute_H___ #define ___PostgreSQL72_EOAttribute_H___ #import #include @class NSString; @interface EOAttribute(PostgreSQL72AttributeAdditions) - (void)loadValueClassAndTypeUsingPostgreSQLType:(Oid)_type size:(int)_size modification:(int)_modification binary:(BOOL)_isBinary; - (void)loadValueClassForExternalPostgreSQLType:(NSString *)_type; @end #endif /* ___PostgreSQL72_EOAttribute_H___ */ SOPE/sope-gdl1/PostgreSQL/PostgreSQL72Expression.m0000644000000000000000000000564315004363604020543 0ustar rootroot/* PostgreSQL72Expression.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2006 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge@opengroupware.org) This file is part of the PostgreSQL Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "PostgreSQL72Expression.h" #include "common.h" @implementation PostgreSQL72Expression + (Class)selectExpressionClass { return [PostgreSQL72SelectSQLExpression class]; } @end /* PostgreSQL72Expression */ @implementation PostgreSQL72SelectSQLExpression - (id)selectExpressionForAttributes:(NSArray *)attributes lock:(BOOL)flag qualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder channel:(EOAdaptorChannel *)channel { lock = flag; [super selectExpressionForAttributes:attributes lock:flag qualifier:qualifier fetchOrder:fetchOrder channel:channel]; return self; } - (NSString *)fromClause { NSMutableString *fromClause; NSEnumerator *enumerator; BOOL first = YES; id key; fromClause = [NSMutableString stringWithCapacity:64]; enumerator = [fromListEntities objectEnumerator]; [fromClause appendString:@" "]; // Compute the FROM list from all the aliases found in // entitiesAndPropertiesAliases dictionary. Note that this dictionary // contains entities and relationships. The last ones are there for // flattened attributes over reflexive relationships. while ((key = [enumerator nextObject]) != nil) { if(first) first = NO; else [fromClause appendString:@", "]; [fromClause appendString: [key isKindOfClass:[EORelationship class]] ? [[key destinationEntity] externalName] // flattened attribute : [key externalName]]; // EOEntity [fromClause appendString:@" "]; [fromClause appendString: [[entitiesAndPropertiesAliases objectForKey:key] stringValue]]; #if 0 if (lock) [fromClause appendString:@" HOLDLOCK"]; #endif } return fromClause; } @end void __link_PostgreSQL72Expression() { // used to force linking of object file __link_PostgreSQL72Expression(); } SOPE/sope-gdl1/PostgreSQL/NSString+PostgreSQL72.m0000644000000000000000000001064115004363604020160 0ustar rootroot/* NSString+PostgreSQL72.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2006 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if LIB_FOUNDATION_BOEHM_GC # include #endif #include "common.h" #import "NSString+PostgreSQL72.h" @implementation NSString(PostgreSQL72MiscStrings) - (NSString *)_pgModelMakeInstanceVarName { unsigned clen; unichar *us; int cnt, cnt2; if ([self length] == 0) return @""; // TODO: do use UTF-8 here clen = [self length]; us = malloc((clen + 10) * sizeof(unichar)); [self getCharacters:us]; us[clen] = 0; // Note: upper/lower detection is not strictly correct ... (no unicode) for (cnt = cnt2 = 0; cnt < clen; cnt++, cnt2++) { if ((us[cnt] == '_') && (us[cnt + 1] != '\0')) { us[cnt2] = toupper(us[cnt + 1]); cnt++; } else if ((us[cnt] == '2') && (us[cnt + 1] != '\0')) { us[cnt2] = us[cnt]; cnt++; cnt2++; us[cnt2] = toupper(us[cnt]); } else us[cnt2] = tolower(us[cnt]); } us[cnt2] = '\0'; return [NSString stringWithCharacters:us length:cnt2]; } - (NSString *)_pgModelMakeClassName { unsigned clen = 0; unichar *us; int cnt, cnt2; if ([self length] == 0) return @""; // TODO: use UTF-8 here clen = [self length]; us = malloc((clen + 10) * sizeof(unichar)); [self getCharacters:us]; us[clen] = 0; for (cnt = cnt2 = 0; cnt < clen; cnt++, cnt2++) { if ((us[cnt] == '_') && (us[cnt + 1] != '\0')) { us[cnt2] = toupper(us[cnt + 1]); cnt++; } else if ((us[cnt] == '2') && (us[cnt + 1] != '\0')) { us[cnt2] = us[cnt]; cnt++; cnt2++; us[cnt2] = toupper(us[cnt]); } else us[cnt2] = tolower(us[cnt]); } us[cnt2] = '\0'; us[0] = toupper(us[0]); return [NSString stringWithCharacters:us length:cnt2]; } static NSCharacterSet *upperSet = nil; static NSCharacterSet *spaceSet = nil; - (NSString *)_pgStringWithCapitalizedFirstChar { if (upperSet == nil) upperSet = [[NSCharacterSet uppercaseLetterCharacterSet] retain]; if ([self length] == 0) return @""; if ([upperSet characterIsMember:[self characterAtIndex:0]]) return [[self copy] autorelease]; { NSMutableString *str = [NSMutableString stringWithCapacity:[self length]]; [str appendString:[[self substringToIndex:1] uppercaseString]]; [str appendString:[self substringFromIndex:1]]; return [[str copy] autorelease]; } } - (NSString *)_pgStripEndSpaces { NSMutableString *str; unichar (*charAtIndex)(id, SEL, int); NSRange range; if ([self length] == 0) return @""; if (spaceSet == nil) spaceSet = [[NSCharacterSet whitespaceCharacterSet] retain]; str = [NSMutableString stringWithCapacity:[self length]]; charAtIndex = (unichar (*)(id, SEL, int)) [self methodForSelector:@selector(characterAtIndex:)]; range.length = 0; for (range.location = ([self length] - 1); ; range.location--, range.length++) { unichar c; c = charAtIndex(self, @selector(characterAtIndex:), range.location); if (![spaceSet characterIsMember:c]) break; if (range.location == 0) break; } if (range.length > 0) { [str appendString:self]; [str deleteCharactersInRange:range]; return AUTORELEASE([str copy]); } return AUTORELEASE([self copy]); } @end /* NSString(PostgreSQL72MiscStrings) */ void __link_NSStringPostgreSQL72() { // used to force linking of object file __link_NSStringPostgreSQL72(); } SOPE/sope-gdl1/PostgreSQL/Version0000644000000000000000000000011615004363604015467 0ustar rootroot# version file SUBMINOR_VERSION:=54 # v4.5.41 requires libGDLAccess v4.5.50 SOPE/sope-gdl1/PostgreSQL/PostgreSQL72Expression.h0000644000000000000000000000302615004363604020527 0ustar rootroot/* PostgreSQL72Expression.h Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___Postgre_SQLExpression_H___ #define ___Postgre_SQLExpression_H___ #include @class NSString, NSArray; @class EOSQLQualifier, EOAdaptorChannel; @interface PostgreSQL72Expression : EOSQLExpression + (Class)selectExpressionClass; @end @interface PostgreSQL72SelectSQLExpression : EOSelectSQLExpression { BOOL lock; } - (id)selectExpressionForAttributes:(NSArray *)attributes lock:(BOOL)flag qualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder channel:(EOAdaptorChannel *)channel; - (NSString *)fromClause; @end #endif SOPE/sope-gdl1/PostgreSQL/NSNull+PGVal.m0000644000000000000000000000234615004363604016424 0ustar rootroot/* NSNull+PGVal.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2006 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" @implementation NSNull(PostgreSQL72Values) - (NSString *)stringValueForPostgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute { return @"null"; } @end /* NSNull(PostgreSQL72Values) */ SOPE/sope-gdl1/PostgreSQL/NSNumber+PGVal.m0000644000000000000000000001175415004363604016745 0ustar rootroot/* NSString+PGVal.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2005 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #include "PostgreSQL72Channel.h" #include "common.h" @implementation NSNumber(PostgreSQL72Values) static BOOL debugOn = NO; static Class NSNumberClass = Nil; static NSNumber *yesNum = nil; static NSNumber *noNum = nil; + (id)valueFromCString:(const char *)_cstr length:(int)_length postgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute adaptorChannel:(PostgreSQL72Channel *)_channel { // TODO: can we avoid the lowercaseString? unsigned len; unichar c1; if ((len = [_type length]) == 0) return nil; if (NSNumberClass == Nil) NSNumberClass = [NSNumber class]; c1 = [_type characterAtIndex:0]; switch (c1) { case 'f': case 'F': { if (len < 5) break; if ([[_type lowercaseString] hasPrefix:@"float"]) return [NSNumberClass numberWithDouble:atof(_cstr)]; break; } case 's': case 'S': { if (len < 8) break; if ([[_type lowercaseString] hasPrefix:@"smallint"]) return [NSNumberClass numberWithShort:atoi(_cstr)]; break; } case 'i': case 'I': { if (len < 3) break; if ([[_type lowercaseString] hasPrefix:@"int"]) return [NSNumberClass numberWithInt:atoi(_cstr)]; } case 'b': case 'B': { if (len < 4) break; if (![[_type lowercaseString] hasPrefix:@"bool"]) break; if (yesNum == nil) yesNum = [[NSNumberClass numberWithBool:YES] retain]; if (noNum == nil) noNum = [[NSNumberClass numberWithBool:NO] retain]; if (_length == 0) return noNum; switch (*_cstr) { case 't': case 'T': case 'y': case 'Y': case '1': return yesNum; default: return noNum; } } } return nil; } + (id)valueFromBytes:(const void *)_bytes length:(int)_length postgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute adaptorChannel:(PostgreSQL72Channel *)_channel { #if COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY NSLog(@"%s: not implemented!", __PRETTY_FUNCTION__); return nil; #else return [self notImplemented:_cmd]; #endif } - (NSString *)stringValueForPostgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute { // TODO: can we avoid the lowercaseString? unsigned len; unichar c1; if (debugOn) NSLog(@"%s(type=%@,attr=%@)", __PRETTY_FUNCTION__, _type, _attribute); if ((len = [_type length]) == 0) { if (debugOn) NSLog(@" no type, return string"); return [self stringValue]; } if (len < 4) { /* apparently this is 'INT'? */ if (debugOn) NSLog(@" type len < 4 (%@), return string", _type); #if GNUSTEP_BASE_LIBRARY /* on gstep-base -stringValue of bool's return YES or NO, which seems to be different on Cocoa and liBFoundation. */ { static Class BoolClass = Nil; if (BoolClass == Nil) BoolClass = NSClassFromString(@"NSBoolNumber"); if ([self isKindOfClass:BoolClass]) return [self boolValue] ? @"1" : @"0"; } #endif return [self stringValue]; } c1 = [_type characterAtIndex:0]; if (debugOn) NSLog(@" typecode '%c' ...", c1); switch (c1) { case 'b': case 'B': if (![[_type lowercaseString] hasPrefix:@"bool"]) break; return [self boolValue] ? @"true" : @"false"; case 'm': case 'M': { if (![[_type lowercaseString] hasPrefix:@"money"]) break; return [@"$" stringByAppendingString:[self stringValue]]; } case 'c': case 'C': case 't': case 'T': case 'v': case 'V': { static NSMutableString *ms = nil; // reuse mstring, THREAD _type = [_type lowercaseString]; if (!([_type hasPrefix:@"char"] || [_type hasPrefix:@"varchar"] || [_type hasPrefix:@"text"])) break; // TODO: can we get this faster?! if (ms == nil) ms = [[NSMutableString alloc] initWithCapacity:256]; [ms setString:@"'"]; [ms appendString:[self stringValue]]; [ms appendString:@"'"]; return [[ms copy] autorelease]; } } return [self stringValue]; } @end /* NSNumber(PostgreSQL72Values) */ SOPE/sope-gdl1/PostgreSQL/PostgreSQL72Channel+Model.m0000644000000000000000000003075215004363604021007 0ustar rootroot/* PostgreSQL72Channel+Model.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2008 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "PostgreSQL72Channel.h" #include "NSString+PostgreSQL72.h" #include "EOAttribute+PostgreSQL72.h" #import "common.h" @interface EORelationship(FixMe) - (void)addJoin:(id)_join; @end @implementation PostgreSQL72Channel(ModelFetching) static BOOL debugOn = NO; - (NSArray *)_attributesForTableName:(NSString *)_tableName { NSMutableArray *attributes; NSString *sqlExpr; NSArray *resultDescription; NSDictionary *row; if (![_tableName length]) return nil; attributes = [self->_attributesForTableName objectForKey:_tableName]; if (attributes != nil) return attributes; sqlExpr = @"SELECT a.attnum, a.attname, t.typname, a.attlen, a.attnotnull " @"FROM pg_class c, pg_attribute a, pg_type t " @"WHERE c.relname='%@' AND a.attnum>0 AND a.attrelid=c.oid AND " @"a.atttypid=t.oid " @"ORDER BY attnum;"; sqlExpr = [NSString stringWithFormat:sqlExpr, _tableName]; if (![self evaluateExpression:sqlExpr]) { fprintf(stderr, "Could not evaluate column-describe '%s' on table '%s'\n", [sqlExpr UTF8String], [_tableName UTF8String]); return nil; } resultDescription = [self describeResults]; attributes = [NSMutableArray arrayWithCapacity:16]; while ((row = [self fetchAttributes:resultDescription withZone:NULL])) { EOAttribute *attribute; NSString *columnName, *externalType, *attrName; columnName = [[row objectForKey:@"attname"] stringValue]; attrName = [columnName _pgModelMakeInstanceVarName]; externalType = [[row objectForKey:@"typname"] stringValue]; attribute = [[EOAttribute alloc] init]; [attribute setColumnName:columnName]; [attribute setName:attrName]; [attribute setExternalType:externalType]; [attribute loadValueClassForExternalPostgreSQLType:externalType]; [attributes addObject:attribute]; [attribute release]; attribute = nil; } [self->_attributesForTableName setObject:attributes forKey:_tableName]; if (debugOn) NSLog(@"%s: got attrs: %@", __PRETTY_FUNCTION__, attributes); return attributes; } - (NSArray *)_primaryKeysNamesForTableName:(NSString *)_tableName { NSArray *pkNameForTableName = nil; NSMutableArray *primaryKeys = nil; NSString *selectExpression; NSArray *resultDescription = nil; NSString *columnNameKey = nil; NSDictionary *row = nil; if ([_tableName length] == 0) return nil; pkNameForTableName = [self->_primaryKeysNamesForTableName objectForKey:_tableName]; if (pkNameForTableName != nil) return pkNameForTableName; selectExpression = [NSString stringWithFormat: @"SELECT attname FROM pg_attribute WHERE " @"attrelid IN (SELECT a.indexrelid FROM " @"pg_index a, pg_class b WHERE " @"a.indexrelid = b.oid AND " @"b.relname in (SELECT indexname FROM " @"pg_indexes WHERE " @"tablename = '%@') " @"AND a.indisprimary)", _tableName]; if (![self evaluateExpression:selectExpression]) return nil; resultDescription = [self describeResults]; columnNameKey = [(EOAttribute *)[resultDescription objectAtIndex:0] name]; primaryKeys = [NSMutableArray arrayWithCapacity:4]; while ((row = [self fetchAttributes:resultDescription withZone:NULL])) [primaryKeys addObject:[row objectForKey:columnNameKey]]; pkNameForTableName = primaryKeys; [self->_primaryKeysNamesForTableName setObject:pkNameForTableName forKey:_tableName]; return pkNameForTableName; } - (NSArray *)_foreignKeysForTableName:(NSString *)_tableName { return nil; } - (EOModel *)describeModelWithTableNames:(NSArray *)_tableNames { NSMutableArray *buildRelShips = [NSMutableArray arrayWithCapacity:64]; EOModel *model = AUTORELEASE([EOModel new]); int cnt, tc = [_tableNames count]; for (cnt = 0; cnt < tc; cnt++) { NSMutableDictionary *relNamesUsed; NSMutableArray *classProperties; NSMutableArray *primaryKeyAttributes; NSString *tableName; NSArray *attributes; NSArray *pkeys; NSArray *fkeys; EOEntity *entity; int cnt2, ac, fkc; relNamesUsed = [NSMutableDictionary dictionaryWithCapacity:4]; classProperties = [NSMutableArray arrayWithCapacity:16]; primaryKeyAttributes = [NSMutableArray arrayWithCapacity:2]; tableName = [_tableNames objectAtIndex:cnt]; attributes = [self _attributesForTableName:tableName]; pkeys = [self _primaryKeysNamesForTableName:tableName]; fkeys = [self _foreignKeysForTableName:tableName]; entity = [[EOEntity new] autorelease]; ac = [attributes count]; fkc = [fkeys count]; [entity setName:[tableName _pgModelMakeClassName]]; [entity setClassName: [@"EO" stringByAppendingString: [tableName _pgModelMakeClassName]]]; [entity setExternalName:tableName]; [classProperties addObjectsFromArray:[entity classProperties]]; [primaryKeyAttributes addObjectsFromArray:[entity primaryKeyAttributes]]; [model addEntity:entity]; for (cnt2 = 0; cnt2 < ac; cnt2++) { EOAttribute *attribute = [attributes objectAtIndex:cnt2]; NSString *columnName = [attribute columnName]; attribute = [attributes objectAtIndex:cnt2]; columnName = [attribute columnName]; [entity addAttribute:attribute]; [classProperties addObject:attribute]; if ([pkeys containsObject:columnName]) [primaryKeyAttributes addObject:attribute]; } [entity setClassProperties:classProperties]; [entity setPrimaryKeyAttributes:primaryKeyAttributes]; for (cnt2 = 0; cnt2 < fkc; cnt2++) { NSDictionary *fkey; NSMutableArray *classProperties; NSString *sa, *da, *dt; EORelationship *rel; EOJoin *join; NSString *relName = nil; fkey = [fkeys objectAtIndex:cnt2]; classProperties = [NSMutableArray arrayWithCapacity:16]; sa = [fkey objectForKey:@"sourceAttr"]; da = [fkey objectForKey:@"targetAttr"]; dt = [fkey objectForKey:@"targetTable"]; rel = [[[EORelationship alloc] init] autorelease]; // TODO: do something about the join (just use rel?) join = [[[NSClassFromString(@"EOJoin") alloc] init] autorelease]; if ([pkeys containsObject:sa]) relName = [@"to" stringByAppendingString:[dt _pgModelMakeClassName]]; else { relName = [@"to" stringByAppendingString: [[sa _pgModelMakeInstanceVarName] _pgStringWithCapitalizedFirstChar]]; if ([relName hasSuffix:@"Id"]) relName = [relName substringToIndex:([relName length] - 2)]; } if ([relNamesUsed objectForKey:relName] != nil) { int useCount = [[relNamesUsed objectForKey:relName] intValue]; [relNamesUsed setObject:[NSNumber numberWithInt:(useCount++)] forKey:relName]; relName = [NSString stringWithFormat:@"%@%d", relName, useCount]; } else [relNamesUsed setObject:[NSNumber numberWithInt:0] forKey:relName]; [rel setName:relName]; //[rel setDestinationEntity:(EOEntity *)[dt _pgModelMakeClassName]]; [rel setToMany:NO]; // TODO: EOJoin is removed, fix this ... [(id)join setSourceAttribute: (EOAttribute *)[sa _pgModelMakeInstanceVarName]]; [(id)join setDestinationAttribute: (EOAttribute *)[da _pgModelMakeInstanceVarName]]; [rel addJoin:join]; [entity addRelationship:rel]; [classProperties addObjectsFromArray:[entity classProperties]]; [classProperties addObject:rel]; [entity setClassProperties:classProperties]; [buildRelShips addObject:rel]; } [entity setAttributesUsedForLocking:[entity attributes]]; } [buildRelShips makeObjectsPerformSelector: @selector(replaceStringsWithObjects)]; /* // make reverse relations { int cnt, rc = [buildRelShips count]; for (cnt = 0; cnt < rc; cnt++) { EORelationship *rel = [buildRelShips objectAtIndex:cnt]; NSMutableArray *classProperties = [NSMutableArray new]; EORelationship *reverse = [rel reversedRelationShip]; EOEntity *entity = [rel destinationEntity]; NSArray *pkeys = [entity primaryKeyAttributes]; BOOL isToMany = [reverse isToMany]; EOAttribute *sa = [[[reverse joins] lastObject] sourceAttribute]; NSString *relName = nil; if ([pkeys containsObject:sa] || isToMany) relName = [@"to" stringByAppendingString: [(EOEntity *)[reverse destinationEntity] name]]; else { relName = [@"to" stringByAppendingString: [[[sa name] _pgModelMakeInstanceVarName] _pgStringWithCapitalizedFirstChar]]; if ([relName hasSuffix:@"Id"]) { int cLength = [relName cStringLength]; relName = [relName substringToIndex:cLength - 2]; } } if ([entity relationshipNamed:relName]) { int cnt = 1; NSString *numName; numName = [NSString stringWithFormat:@"%s%d", [relName cString], cnt]; while ([entity relationshipNamed:numName]) { cnt++; numName = [NSString stringWithFormat:@"%s%d", [relName cString], cnt]; } relName = numName; } [reverse setName:relName]; [entity addRelationship:reverse]; [classProperties addObjectsFromArray:[entity classProperties]]; [classProperties addObject:reverse]; [entity setClassProperties:classProperties]; } } */ [model setAdaptorName:@"PostgreSQL72"]; [model setAdaptorClassName:@"PostgreSQL72Adaptor"]; [model setConnectionDictionary: [[adaptorContext adaptor] connectionDictionary]]; return model; } - (NSArray *)_runSingleColumnQuery:(NSString *)_query { NSMutableArray *names; NSArray *resultDescription; NSString *attributeName; NSDictionary *row; if (![self evaluateExpression:_query]) { fprintf(stderr, "Could not evaluate expression: '%s'\n", #if LIB_FOUNDATION_LIBRARY [_query cString] #else [_query UTF8String] #endif ); return nil; } resultDescription = [self describeResults]; attributeName = [(EOAttribute *)[resultDescription objectAtIndex:0] name]; names = [NSMutableArray arrayWithCapacity:16]; while ((row = [self fetchAttributes:resultDescription withZone:NULL])) [names addObject:[row objectForKey:attributeName]]; return names; } - (NSArray *)describeTableNames { NSString *sql; sql = @"SELECT relname " @"FROM pg_class " @"WHERE (relkind='r') AND (relname !~ '^pg_') AND " @"(relname !~ '^xinv[0-9]+') " @"ORDER BY relname"; return [self _runSingleColumnQuery:sql]; } - (NSArray *)describeDatabaseNames { return [self _runSingleColumnQuery: @"SELECT datname FROM pg_database ORDER BY datname"]; } - (NSArray *)describeUserNames { return [self _runSingleColumnQuery:@"SELECT usename FROM pg_user"]; } @end /* PostgreSQL72Channel(ModelFetching) */ void __link_PostgreSQL72ChannelModel() { // used to force linking of object file __link_PostgreSQL72ChannelModel(); } SOPE/sope-gdl1/PostgreSQL/PGResultSet.m0000644000000000000000000000677015004363604016472 0ustar rootroot/* PGConnection.m Copyright (C) 2004-2006 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "PGConnection.h" #include "common.h" #include #include "pgconfig.h" @implementation PGResultSet /* wraps PGresult */ - (id)initWithConnection:(PGConnection *)_con handle:(void *)_handle { if (_handle == NULL) { [self release]; return nil; } if ((self = [super init])) { self->connection = [_con retain]; self->results = _handle; } return self; } - (void)dealloc { [self clear]; [self->connection release]; [super dealloc]; } /* accessors */ - (BOOL)isValid { return self->results != NULL ? YES : NO; } - (BOOL)containsBinaryTuples { #if NG_HAS_BINARY_TUPLES if (self->results == NULL) return NO; return PQbinaryTuples(self->results) ? YES : NO; #else return NO; #endif } - (NSString *)commandStatus { char *cstr; if (self->results == NULL) return nil; if ((cstr = PQcmdStatus(self->results)) == NULL) return nil; return [self->connection _stringFromCString:cstr]; } - (NSString *)commandTuples { char *cstr; if (self->results == NULL) return nil; if ((cstr = PQcmdTuples(self->results)) == NULL) return nil; return [self->connection _stringFromCString:cstr]; } /* fields */ - (unsigned)fieldCount { return self->results != NULL ? PQnfields(self->results) : 0; } - (NSString *)fieldNameAtIndex:(unsigned int)_idx { // TODO: charset if (self->results == NULL) return nil; return [self->connection _stringFromCString:PQfname(self->results, _idx)]; } - (int)indexOfFieldNamed:(NSString *)_name { return PQfnumber(self->results, [_name UTF8String]); } - (int)fieldSizeAtIndex:(unsigned int)_idx { if (self->results == NULL) return 0; return PQfsize(self->results, _idx); } - (int)modifierAtIndex:(unsigned int)_idx { if (self->results == NULL) return 0; #if NG_HAS_FMOD return PQfmod(self->results, _idx); #else return 0; #endif } /* tuples */ - (unsigned int)tupleCount { if (self->results == NULL) return 0; return PQntuples(self->results); } - (BOOL)isNullTuple:(int)_tuple atIndex:(unsigned int)_idx { if (self->results == NULL) return NO; return PQgetisnull(self->results, _tuple, _idx) ? YES : NO; } - (void *)rawValueOfTuple:(int)_tuple atIndex:(unsigned int)_idx { if (self->results == NULL) return NULL; return PQgetvalue(self->results, _tuple, _idx); } - (int)lengthOfTuple:(int)_tuple atIndex:(unsigned int)_idx { if (self->results == NULL) return 0; return PQgetlength(self->results, _tuple, _idx); } /* operations */ - (void)clear { if (self->results == NULL) return; PQclear(self->results); self->results = NULL; } @end /* PGResultSet */ SOPE/sope-gdl1/PostgreSQL/test.eomodel0000644000000000000000000000120115004363604016440 0ustar rootroot{ EOModelVersion = 1; adaptorClassName = PostgreSQLAdaptor; adaptorName = PostgreSQL; entities = ( { name = Doof; externalName = doof; className = EOGenericRecord; primaryKeyAttributes = ( pkey ); attributesUsedForLocking = ( pkey ); classProperties = ( pkey ); attributes = ( { valueClassName = NSNumber; columnName = pkey; name = pkey; valueType = i; externalType = INT; // t_id }, ); } ); } SOPE/sope-gdl1/PostgreSQL/EOAttribute+PostgreSQL72.m0000644000000000000000000001573315004363604020647 0ustar rootroot/* EOAttribute+PostgreSQL72.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2004 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #include "EOAttribute+PostgreSQL72.h" #if 0 #include #else #include #endif //#include // Sybase dateformat: (need to be corrected for PostgreSQL) static NSString *PGSQL_DATETIME_FORMAT = @"%b %d %Y %I:%M:%S:000%p"; static NSString *PGSQL_TIMESTAMP_FORMAT = @"%Y-%m-%d %H:%M:%S%z"; @implementation EOAttribute(PostgreSQL72AttributeAdditions) - (void)loadValueClassAndTypeUsingPostgreSQLType:(Oid)_type size:(int)_size modification:(int)_modification binary:(BOOL)_isBinary { if (_isBinary) [self setValueClassName:@"NSData"]; switch (_type) { /* where in the PostgreSQL72 headers are these OIDs defined ??? */ case BOOLOID: [self setExternalType:@"bool"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"i"]; return; case NAMEOID: [self setExternalType:@"name"]; [self setValueClassName:@"NSString"]; return; case TEXTOID: [self setExternalType:@"textoid"]; [self setValueClassName:@"NSString"]; return; case INT2OID: [self setExternalType:@"int2"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; return; case INT4OID: [self setExternalType:@"int4"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; return; case INT8OID: [self setExternalType:@"int8"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; return; case CHAROID: [self setExternalType:@"char"]; [self setValueClassName:@"NSString"]; break; case VARCHAROID: [self setExternalType:@"varchar"]; [self setValueClassName:@"NSString"]; break; case NUMERICOID: [self setExternalType:@"numeric"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; break; case FLOAT4OID: [self setExternalType:@"float4"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"f"]; break; case FLOAT8OID: [self setExternalType:@"float8"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"f"]; break; case DATEOID: [self setExternalType:@"datetime"]; [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:PGSQL_DATETIME_FORMAT]; break; case TIMEOID: [self setExternalType:@"time"]; [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:PGSQL_DATETIME_FORMAT]; break; case TIMESTAMPOID: [self setExternalType:@"timestamp"]; [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:PGSQL_DATETIME_FORMAT]; break; case TIMESTAMPTZOID: [self setExternalType:@"timestamptz"]; [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:PGSQL_DATETIME_FORMAT]; break; case BITOID: [self setExternalType:@"bit"]; break; default: NSLog(@"What is PGSQL Oid %i ???", _type); break; } } - (void)loadValueClassForExternalPostgreSQLType:(NSString *)_type { if ([_type isEqualToString:@"bool"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"i"]; } else if ([_type isEqualToString:@"int2"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"i"]; } else if ([_type isEqualToString:@"int4"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"i"]; } else if ([_type isEqualToString:@"float4"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"f"]; } else if ([_type isEqualToString:@"float8"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; } else if ([_type isEqualToString:@"decimal"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; } else if ([_type isEqualToString:@"numeric"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; } else if ([_type isEqualToString:@"cardinal_number"]) { // TODO: not sure whether this is correct (comes from sql_features table) [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; } else if ([_type isEqualToString:@"name"]) { [self setExternalType:@"name"]; [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"varchar"]) { [self setExternalType:@"varchar"]; [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"char"]) { [self setExternalType:@"char"]; [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"character_data"]) { // TODO: not sure whether this is correct (comes from sql_features table) [self setExternalType:@"character_data"]; [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"timestamp"]) { [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:PGSQL_TIMESTAMP_FORMAT]; } else if ([_type isEqualToString:@"timestamptz"]) { [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:PGSQL_TIMESTAMP_FORMAT]; } else if ([_type isEqualToString:@"datetime"]) { [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:PGSQL_DATETIME_FORMAT]; } else if ([_type isEqualToString:@"date"]) { [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"time"]) { [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"text"]) { [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"oid"]) { // TODO: is this correct? [self setValueClassName:@"NSString"]; } else { NSLog(@"%s: invalid argument %@", __PRETTY_FUNCTION__, _type); [NSException raise:@"InvalidArgumentException" format: @"invalid PostgreSQL72 type %@ passed to " @"-loadValueClassForExternalPostgreSQLType:", _type]; } } @end /* EOAttribute(PostgreSQL72) */ void __link_EOAttributePostgreSQL72() { // used to force linking of object file __link_EOAttributePostgreSQL72(); } SOPE/sope-gdl1/PostgreSQL/types.psql0000644000000000000000000000042415004363604016166 0ustar rootroot # type test table create table pgtypetest ( t_int2 int2, t_int4 int4, t_int8 int8, t_int int, t_varchar255 varchar(255), t_datetime datetime, t_timestamp timestamp, t_timestamp_wtz timestamp with time zone ); SOPE/sope-gdl1/PostgreSQL/TODO0000644000000000000000000000011615004363604014607 0ustar rootrootTODO ==== - cache field-names in PostgreSQL72Channel -primaryFetch (see TODO) SOPE/sope-gdl1/PostgreSQL/GNUmakefile.preamble0000644000000000000000000000452415004363604017766 0ustar rootroot# # GNUmakefile # # Copyright (C) 2003-2005 SKYRIX Software AG # # Author: Helge Hess (helge.hess@skyrix.com) # # This file is part of the PostgreSQL Adaptor Library # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library 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 # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with this library; see the file COPYING.LIB. # If not, write to the Free Software Foundation, # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. SOPE_ROOT=../.. ifeq ($(frameworks),yes) BUNDLE_INSTALL_DIR := $(FRAMEWORK_INSTALL_DIR)/GDLAccess.framework/Resources/GDLAdaptors/ else BUNDLE_INSTALL_DIR = $(SOPE_DBADAPTORS)/ endif # PG config ADDITIONAL_INCLUDE_DIRS += -I$(shell pg_config --includedir) PG_LIB_DIRS += -L$(shell pg_config --libdir) PostgreSQL_BUNDLE_LIBS += -lpq # set compile flags and go ADDITIONAL_INCLUDE_DIRS += \ -I../GDLAccess -I.. ADDITIONAL_INCLUDE_DIRS += \ -I.. -I$(SOPE_ROOT) \ -I$(SOPE_ROOT)/sope-core/ \ -I$(SOPE_ROOT)/sope-core/NGExtensions # TODO: is this required? ADDITIONAL_INCLUDE_DIRS += \ -I/usr/local/include # dependencies ifneq ($(frameworks),yes) PostgreSQL_BUNDLE_LIBS += -lGDLAccess -lEOControl gdltest_TOOL_LIBS += -lGDLAccess else PostgreSQL_BUNDLE_LIBS += -framework GDLAccess -framework EOControl gdltest_TOOL_LIBS += -framework GDLAccess endif # library/framework search pathes DEP_DIRS = \ ../GDLAccess \ $(SOPE_ROOT)/sope-core/EOControl ifneq ($(frameworks),yes) ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),\ -L$(GNUSTEP_BUILD_DIR)/$(dir)/$(GNUSTEP_OBJ_DIR_NAME)) else ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir)) endif SYSTEM_LIB_DIR += $(CONFIGURE_SYSTEM_LIB_DIR) $(PG_LIB_DIRS) # TODO: not necessary? covered by pg_config? #ifeq ($(FOUNDATION_LIB),apple) #PostgreSQL_BUNDLE_LIBS += -lssl -lcrypto #ADDITIONAL_INCLUDE_DIRS += -I/Library/PostgreSQL/include/ #endif SOPE/sope-gdl1/PostgreSQL/EOKeyGlobalID+PGVal.m0000644000000000000000000000273115004363604017561 0ustar rootroot/* EOKeyGlobalID+PGVal.m Copyright (C) 2006 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "PostgreSQL72Channel.h" #include "common.h" @implementation EOKeyGlobalID(PostgreSQL72Values) - (NSString *)stringValueForPostgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute { if (self->count == 0) { NSLog(@"ERROR(%s): got a EOKeyGlobalID w/o key values: %@", __PRETTY_FUNCTION__, self); return nil; } return [self->values[0] stringValueForPostgreSQLType:_type attribute:_attribute]; } @end /* EOKeyGlobalID(PostgreSQL72Values) */ SOPE/sope-gdl1/PostgreSQL/NSData+PGVal.m0000644000000000000000000000722215004363604016361 0ustar rootroot/* NSData+PGVal.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2005 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #include "PostgreSQL72Values.h" #include "PostgreSQL72Channel.h" #include "common.h" @implementation NSData(PostgreSQL72Values) static BOOL doDebug = NO; static NSData *EmptyData = nil; + (id)valueFromCString:(const char *)_cstr length:(int)_length postgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute adaptorChannel:(PostgreSQL72Channel *)_channel { if (_length == 0) { if (EmptyData == nil) EmptyData = [[NSData alloc] init]; return EmptyData; } return [[[self alloc] initWithBytes:_cstr length:_length] autorelease]; } + (id)valueFromBytes:(const void *)_bytes length:(int)_length postgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute adaptorChannel:(PostgreSQL72Channel *)_channel { if (_length == 0) { if (EmptyData == nil) EmptyData = [[NSData alloc] init]; return EmptyData; } return [[[self alloc] initWithBytes:_bytes length:_length] autorelease]; } - (NSString *)stringValueForPostgreSQLType:(NSString *)_type attribute:(EOAttribute *)_attribute { // TODO: UNICODE // TODO: this method looks slow // example type: "VARCHAR(4000)" static NSStringEncoding enc = 0; NSString *str, *t; unsigned len; unichar c1; if ((len = [self length]) == 0) return @""; if (enc == 0) { // enc = [NSString defaultCStringEncoding]; enc = NSUTF8StringEncoding; NSLog(@"Note: PostgreSQL adaptor using '%@' encoding for data=>string " @"conversion.", [NSString localizedNameOfStringEncoding:enc]); } str = [[NSString alloc] initWithData:self encoding:enc]; if (doDebug) { NSLog(@"Note: made string (len=%i) for data (len=%i), type %@", (int)[str length], (int)[self length], _type); } if ((len = [_type length]) == 0) { NSLog(@"WARNING(%s): missing type for data=>string conversion!", __PRETTY_FUNCTION__); return [str autorelease]; } c1 = [_type characterAtIndex:0]; switch (c1) { case 'c': case 'C': // char case 'v': case 'V': // varchar case 'm': case 'M': // money case 't': case 'T': // text t = [_type lowercaseString]; if ([t hasPrefix:@"char"] || [t hasPrefix:@"varchar"] || [t hasPrefix:@"money"] || [t hasPrefix:@"text"]) { if (doDebug) NSLog(@" converting type: %@", t); t = [[str stringValueForPostgreSQLType:_type attribute:_attribute] copy]; [str release]; if (doDebug) NSLog(@" result len %i", (int)[t length]); return [t autorelease]; } } NSLog(@"WARNING(%s): no processing of type '%@' for " @"data=>string conversion!", __PRETTY_FUNCTION__, _type); return [str autorelease];; } @end /* NSData(PostgreSQL72Values) */ SOPE/sope-gdl1/PostgreSQL/PostgreSQL72Channel+Model.h0000644000000000000000000000262115004363604020774 0ustar rootroot/* PostgreSQL72Channel+Model.h Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Copyright (C) 2000-2004 SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the PostgreSQL72 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___PostgreSQL72_ModelFetching_H___ #define ___PostgreSQL72_ModelFetching_H___ #import "PostgreSQL72Channel.h" @class NSArray; @class EOModel; @interface PostgreSQL72Channel(ModelFetching) - (EOModel *)describeModelWithTableNames:(NSArray *)_tableNames; - (NSArray *)describeUserNames; - (NSArray *)describeTableNames; - (NSArray *)describeDatabaseNames; @end #endif SOPE/sope-gdl1/PostgreSQL/postgres_types.h0000644000000000000000000000201715004363604017364 0ustar rootroot/* TBD: explain this! */ #define BOOLOID 16 #define BYTEAOID 17 #define CHAROID 18 #define NAMEOID 19 #define INT8OID 20 #define INT2OID 21 #define INT2VECTOROID 22 #define INT4OID 23 #define REGPROCOID 24 #define TEXTOID 25 #define OIDOID 26 #define TIDOID 27 #define XIDOID 28 #define CIDOID 29 #define OIDVECTOROID 30 #define POINTOID 600 #define LSEGOID 601 #define PATHOID 602 #define BOXOID 603 #define POLYGONOID 604 #define LINEOID 628 #define FLOAT4OID 700 #define FLOAT8OID 701 #define ABSTIMEOID 702 #define RELTIMEOID 703 #define TINTERVALOID 704 #define UNKNOWNOID 705 #define CIRCLEOID 718 #define CASHOID 790 #define MACADDROID 829 #define INETOID 869 #define CIDROID 650 #define ACLITEMSIZE 8 #define BPCHAROID 1042 #define VARCHAROID 1043 #define DATEOID 1082 #define TIMEOID 1083 #define TIMESTAMPOID 1114 #define TIMESTAMPTZOID 1184 #define INTERVALOID 1186 #define TIMETZOID 1266 #define BITOID 1560 #define VARBITOID 1562 #define NUMERICOID 1700 #define REFCURSOROID 1790 SOPE/sope-gdl1/MySQL/0000755000000000000000000000000015004363604013063 5ustar rootrootSOPE/sope-gdl1/MySQL/MySQL4Exception.m0000644000000000000000000000324115004363604016151 0ustar rootroot/* MySQL4Exception.m Copyright (C) 2003-2005 Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #import "MySQL4Exception.h" #include "common.h" @implementation MySQL4Exception + (void)raiseWithFormat:(NSString *)_format, ... { NSString *tmp = nil; va_list ap; va_start(ap, _format); tmp = [[NSString allocWithZone:[self zone]] initWithFormat:_format arguments:ap]; va_end(ap); AUTORELEASE(tmp); [[[self alloc] initWithName:NSStringFromClass([self class]) reason:tmp userInfo:nil] raise]; } @end @implementation MySQL4CouldNotOpenChannelException @end @implementation MySQL4CouldNotConnectException @end @implementation MySQL4CouldNotBindException @end void __link_MySQL4Exception() { // used to force linking of object file __link_MySQL4Exception(); } SOPE/sope-gdl1/MySQL/MySQL4Channel.m0000644000000000000000000005467515004363604015604 0ustar rootroot/* MySQL4Channel.m Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "MySQL4Channel.h" #include "MySQL4Adaptor.h" #include "MySQL4Exception.h" #include "NSString+MySQL4.h" #include "MySQL4Values.h" #include "EOAttribute+MySQL4.h" #include "common.h" #include #ifndef MIN # define MIN(x, y) ((x > y) ? y : x) #endif #define MAX_CHAR_BUF 16384 @implementation MySQL4Channel static EONull *null = nil; static NSString *encoding = nil; + (void)initialize { if (null == NULL) null = [[EONull null] retain]; encoding = [[NSUserDefaults standardUserDefaults] stringForKey: @"MySQL4Encoding"]; if (!encoding) { encoding = [NSString stringWithString: @"utf8"]; }; [encoding retain]; } - (id)initWithAdaptorContext:(EOAdaptorContext*)_adaptorContext { if ((self = [super initWithAdaptorContext:_adaptorContext])) { [self setDebugEnabled:[[NSUserDefaults standardUserDefaults] boolForKey:@"MySQL4DebugEnabled"]]; self->_attributesForTableName = [[NSMutableDictionary alloc] initWithCapacity:16]; self->_primaryKeysNamesForTableName = [[NSMutableDictionary alloc] initWithCapacity:16]; } return self; } - (void)_adaptorWillFinalize:(id)_adaptor { } - (void)dealloc { if ([self isOpen]) [self closeChannel]; [self->_attributesForTableName release]; [self->_primaryKeysNamesForTableName release]; [super dealloc]; } /* NSCopying methods */ - (id)copyWithZone:(NSZone *)zone { return [self retain]; } // debugging - (void)setDebugEnabled:(BOOL)_flag { self->isDebuggingEnabled = _flag; } - (BOOL)isDebugEnabled { return self->isDebuggingEnabled; } - (void)receivedMessage:(NSString *)_message { NSLog(@"%@: message %@.", _message); } /* open/close */ static int openConnectionCount = 0; - (BOOL)isOpen { return (self->_connection != NULL) ? YES : NO; } - (int)maxOpenConnectionCount { static int MaxOpenConnectionCount = -1; if (MaxOpenConnectionCount != -1) return MaxOpenConnectionCount; MaxOpenConnectionCount = [[NSUserDefaults standardUserDefaults] integerForKey:@"MySQL4MaxOpenConnectionCount"]; if (MaxOpenConnectionCount == 0) MaxOpenConnectionCount = 150; return MaxOpenConnectionCount; } - (BOOL)openChannel { const char *cDBName, *sslKey, *sslCert, *sslCa; MySQL4Adaptor *adaptor; NSString *host, *socket, *s, *sslKeyPath, *sslCertPath, *sslCaPath; BOOL isSSL; int options; void *rc; if (self->_connection != NULL) { NSLog(@"%s: Connection already open !!!", __PRETTY_FUNCTION__); return NO; } adaptor = (MySQL4Adaptor *)[adaptorContext adaptor]; if (![super openChannel]) return NO; if (openConnectionCount > [self maxOpenConnectionCount]) { [MySQL4CouldNotOpenChannelException raise:@"NoMoreConnections" format:@"cannot open a additional connection !"]; return NO; } cDBName = [[adaptor databaseName] UTF8String]; if ((self->_connection = mysql_init(NULL)) == NULL) { NSLog(@"ERROR(%s): could not allocate MySQL4 connection!"); return NO; } // TODO: could change options using mysql_options() host = [adaptor serverName]; if ([host hasPrefix:@"/"]) { /* treat hostname as Unix socket path */ socket = host; host = nil; } else socket = nil; isSSL = [[NSUserDefaults standardUserDefaults] boolForKey:@"MySQL4SSLEnabled"]; options = 0; if (isSSL) { sslKey = NULL; sslCert = NULL; sslCa = NULL; sslKeyPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"MySQL4SSLKeyPath"]; if (sslKeyPath && [sslKeyPath length] > 0) sslKey = [sslKeyPath UTF8String]; sslCertPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"MySQL4SSLCertPath"]; if (sslCertPath && [sslCertPath length] > 0) sslCert = [sslCertPath UTF8String]; sslCaPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"MySQL4SSLCaPath"]; if (sslCaPath && [sslCaPath length] > 0) sslCa = [sslCaPath UTF8String]; mysql_ssl_set(self->_connection, sslKey, sslCert, sslCa, NULL, NULL); options |= CLIENT_SSL; } rc = mysql_real_connect(self->_connection, [host UTF8String], [[adaptor loginName] UTF8String], [[adaptor loginPassword] UTF8String], cDBName, [[adaptor port] intValue], [socket cString], options); if (rc == NULL) { NSLog(@"ERROR: could not open MySQL4 connection to database '%@': %s", [adaptor databaseName], mysql_error(self->_connection)); mysql_close(self->_connection); self->_connection = NULL; return NO; } s = [NSString stringWithFormat: @"SET CHARACTER SET %@", encoding]; if (mysql_query(self->_connection, [s UTF8String]) != 0) { NSLog(@"WARNING(%s): could not put MySQL4 connection into UTF-8 mode: %s", __PRETTY_FUNCTION__, mysql_error(self->_connection)); #if 0 mysql_close(self->_connection); self->_connection = NULL; return NO; #endif } if (isDebuggingEnabled) { NSLog(@"MySQL4 connection established 0x%p", self->_connection); NSLog(@"---------- %s: %@ opens channel count[%d]", __PRETTY_FUNCTION__, self, openConnectionCount); } openConnectionCount++; #if LIB_FOUNDATION_BOEHM_GC [GarbageCollector registerForFinalizationObserver:self selector:@selector(_adaptorWillFinalize:) object:[[self adaptorContext] adaptor]]; #endif if (isDebuggingEnabled) { NSLog(@"MySQL4 channel 0x%p opened (connection=0x%p,%s)", self, self->_connection, cDBName); } return YES; } - (void)primaryCloseChannel { if ([self isFetchInProgress]) [self cancelFetch]; if (self->_connection != NULL) { mysql_close(self->_connection); if (isDebuggingEnabled) NSLog(@"---------- %s: %@ close channel count[%d]", __PRETTY_FUNCTION__, self, openConnectionCount); openConnectionCount--; if (isDebuggingEnabled) { fprintf(stderr, "MySQL4 connection dropped 0x%p (channel=0x%p)\n", self->_connection, self); } self->_connection = NULL; } } - (void)closeChannel { [super closeChannel]; [self primaryCloseChannel]; } /* fetching rows */ - (void)cancelFetch { self->fields = NULL; /* apparently we do not need to free those */ if (self->results != NULL) { mysql_free_result(self->results); self->results = NULL; } [super cancelFetch]; } - (MYSQL_FIELD *)_fetchFields { if (self->results == NULL) return NULL; if (self->fields != NULL) return self->fields; self->fields = mysql_fetch_fields(self->results); self->fieldCount = mysql_num_fields(self->results); return self->fields; } - (NSArray *)describeResults:(BOOL)_beautifyNames { // TODO: make exception-less method MYSQL_FIELD *mfields; int cnt; NSMutableArray *result = nil; NSMutableDictionary *usedNames = nil; NSNumber *yesObj; yesObj = [NSNumber numberWithBool:YES]; if (![self isFetchInProgress]) { [MySQL4Exception raise:@"NoFetchInProgress" format:@"No fetch in progress (channel=%@)", self]; return nil; } if ((mfields = [self _fetchFields]) == NULL) { [MySQL4Exception raise:@"NoFieldInfo" format:@"Failed to fetch field info (channel=%@)", self]; return nil; } result = [[NSMutableArray alloc] initWithCapacity:fieldCount]; usedNames = [[NSMutableDictionary alloc] initWithCapacity:fieldCount]; for (cnt = 0; cnt < fieldCount; cnt++) { EOAttribute *attribute = nil; NSString *columnName = nil; NSString *attrName = nil; columnName = [NSString stringWithUTF8String:mfields[cnt].name]; attrName = _beautifyNames ? [columnName _mySQL4ModelMakeInstanceVarName] : columnName; if ([[usedNames objectForKey:attrName] boolValue]) { int cnt2 = 0; char buf[64]; NSString *newAttrName = nil; for (cnt2 = 2; cnt2 < 100; cnt2++) { NSString *s; sprintf(buf, "%i", cnt2); // TODO: unicode s = [[NSString alloc] initWithCString:buf]; newAttrName = [attrName stringByAppendingString:s]; [s release]; if (![[usedNames objectForKey:newAttrName] boolValue]) { attrName = newAttrName; break; } } } [usedNames setObject:yesObj forKey:attrName]; attribute = [[EOAttribute alloc] init]; [attribute setName:attrName]; [attribute setColumnName:columnName]; [attribute setAllowsNull: (mfields[cnt].flags & NOT_NULL_FLAG) ? NO : YES]; /* We also know whether a field: is primary is unique is auto-increment is zero-fill is unsigned */ switch (mfields[cnt].type) { case FIELD_TYPE_STRING: [attribute setExternalType:@"CHAR"]; [attribute setValueClassName:@"NSString"]; // TODO: length etc break; case FIELD_TYPE_VAR_STRING: [attribute setExternalType:@"VARCHAR"]; [attribute setValueClassName:@"NSString"]; // TODO: length etc break; case FIELD_TYPE_TINY: if ((mfields[cnt].flags & UNSIGNED_FLAG)) { [attribute setExternalType:@"TINY UNSIGNED"]; [attribute setValueClassName:@"NSNumber"]; [attribute setValueType:@"C"]; } else { [attribute setExternalType:@"TINY"]; [attribute setValueClassName:@"NSNumber"]; [attribute setValueType:@"c"]; } break; case FIELD_TYPE_SHORT: if ((mfields[cnt].flags & UNSIGNED_FLAG)) { [attribute setExternalType:@"SHORT UNSIGNED"]; [attribute setValueClassName:@"NSNumber"]; [attribute setValueType:@"S"]; } else { [attribute setExternalType:@"SHORT"]; [attribute setValueClassName:@"NSNumber"]; [attribute setValueType:@"s"]; } break; case FIELD_TYPE_LONG: if ((mfields[cnt].flags & UNSIGNED_FLAG)) { [attribute setExternalType:@"LONG UNSIGNED"]; [attribute setValueClassName:@"NSNumber"]; [attribute setValueType:@"L"]; } else { [attribute setExternalType:@"LONG"]; [attribute setValueClassName:@"NSNumber"]; [attribute setValueType:@"l"]; } break; case FIELD_TYPE_INT24: if ((mfields[cnt].flags & UNSIGNED_FLAG)) { [attribute setExternalType:@"INT UNSIGNED"]; [attribute setValueClassName:@"NSNumber"]; [attribute setValueType:@"I"]; } else { [attribute setExternalType:@"INT"]; [attribute setValueClassName:@"NSNumber"]; [attribute setValueType:@"i"]; // bumped } break; case FIELD_TYPE_LONGLONG: if ((mfields[cnt].flags & UNSIGNED_FLAG)) { [attribute setExternalType:@"LONGLONG UNSIGNED"]; [attribute setValueClassName:@"NSNumber"]; [attribute setValueType:@"Q"]; } else { [attribute setExternalType:@"LONGLONG"]; [attribute setValueClassName:@"NSNumber"]; [attribute setValueType:@"q"]; } break; case FIELD_TYPE_DECIMAL: [attribute setExternalType:@"DECIMAL"]; [attribute setValueClassName:@"NSNumber"]; [attribute setValueType:@"f"]; // TODO: need NSDecimalNumber here ... break; case FIELD_TYPE_FLOAT: [attribute setExternalType:@"FLOAT"]; [attribute setValueClassName:@"NSNumber"]; [attribute setValueType:@"f"]; break; case FIELD_TYPE_DOUBLE: [attribute setExternalType:@"DOUBLE"]; [attribute setValueClassName:@"NSNumber"]; [attribute setValueType:@"d"]; break; case FIELD_TYPE_TIMESTAMP: [attribute setExternalType:@"TIMESTAMP"]; [attribute setValueClassName:@"NSCalendarDate"]; break; case FIELD_TYPE_DATE: [attribute setExternalType:@"DATE"]; [attribute setValueClassName:@"NSCalendarDate"]; break; case FIELD_TYPE_DATETIME: [attribute setExternalType:@"DATETIME"]; [attribute setValueClassName:@"NSCalendarDate"]; break; case FIELD_TYPE_BLOB: case FIELD_TYPE_TINY_BLOB: case FIELD_TYPE_MEDIUM_BLOB: case FIELD_TYPE_LONG_BLOB: // TODO: length etc if (mfields[cnt].flags & BINARY_FLAG) { [attribute setExternalType:@"BLOB"]; [attribute setValueClassName:@"NSData"]; } else { [attribute setExternalType:@"TEXT"]; [attribute setValueClassName:@"NSString"]; } break; case FIELD_TYPE_NULL: // TODO: whats that? case FIELD_TYPE_TIME: case FIELD_TYPE_YEAR: case FIELD_TYPE_SET: case FIELD_TYPE_ENUM: default: NSLog(@"ERROR(%s): unexpected MySQL4 type at column %i: %@", __PRETTY_FUNCTION__, cnt, attribute); break; } [result addObject:attribute]; [attribute release]; } [usedNames release]; usedNames = nil; return [result autorelease]; } - (NSArray *)describeResults { return [self describeResults:NO]; } - (NSMutableDictionary *)primaryFetchAttributes:(NSArray *)_attributes withZone:(NSZone *)_zone { /* Note: we expect that the attributes match the generated SQL. This is because auto-generated SQL can contain SQL table prefixes (like alias.column-name which cannot be detected using the attributes schema) */ // TODO: add a primaryFetchAttributesX method? MYSQL_ROW rawRow; NSMutableDictionary *row = nil; unsigned attrCount = [_attributes count]; unsigned cnt; unsigned long *lengths; if (self->results == NULL) { NSLog(@"ERROR(%s): no fetch in progress?", __PRETTY_FUNCTION__); [self cancelFetch]; return nil; } /* raw fetch */ if ((rawRow = mysql_fetch_row(self->results)) == NULL) { // TODO: might need to close channel on connect exceptions unsigned int merrno; if ((merrno = mysql_errno(self->_connection)) != 0) { const char *error; error = mysql_error(self->_connection); [MySQL4Exception raise:@"FetchFailed" format:@"%@",[NSString stringWithUTF8String:error]]; return nil; } /* regular end of result set */ [self cancelFetch]; return nil; } /* ensure field info */ if ([self _fetchFields] == NULL) { [self cancelFetch]; [MySQL4Exception raise:@"FetchFailed" format:@"could not fetch field info!"]; return nil; } if ((lengths = mysql_fetch_lengths(self->results)) == NULL) { [self cancelFetch]; [MySQL4Exception raise:@"FetchFailed" format:@"could not fetch field lengths!"]; return nil; } /* build row */ row = [NSMutableDictionary dictionaryWithCapacity:attrCount]; for (cnt = 0; cnt < attrCount; cnt++) { EOAttribute *attribute; NSString *attrName; id value = nil; MYSQL_FIELD mfield; attribute = [_attributes objectAtIndex:cnt]; attrName = [attribute name]; mfield = ((MYSQL_FIELD *)self->fields)[cnt]; if (rawRow[cnt] == NULL) { value = [null retain]; } else { Class valueClass; valueClass = NSClassFromString([attribute valueClassName]); if (valueClass == Nil) { NSLog(@"ERROR(%s): %@: got no value class for column:\n" @" attribute=%@\n type=%@", __PRETTY_FUNCTION__, self, attrName, [attribute externalType]); value = null; continue; } value = [[valueClass alloc] initWithMySQL4Field:&mfield value:rawRow[cnt] length:lengths[cnt]]; if (value == nil) { NSLog(@"ERROR(%s): %@: got no value for column: attribute=%@\n valueClass=%@\n type=%@", __PRETTY_FUNCTION__, self, attrName, NSStringFromClass(valueClass), [attribute externalType]); continue; } } if (value != nil) { [row setObject:value forKey:attrName]; [value release]; } } return row; } /* sending SQL to server */ - (NSException *)evaluateExpressionX:(NSString *)_expression { NSMutableString *sql; BOOL result; const char *s; int rc; *(&result) = YES; if (_expression == nil) { return [NSException exceptionWithName:@"InvalidArgumentException" reason: @"parameter for evaluateExpression: must not be null" userInfo:nil]; } sql = [[_expression mutableCopy] autorelease]; [sql appendString:@";"]; /* ask delegate */ if (delegateRespondsTo.willEvaluateExpression) { EODelegateResponse response; response = [delegate adaptorChannel:self willEvaluateExpression:sql]; if (response == EODelegateRejects) { return [NSException exceptionWithName:@"EODelegateRejects" reason:@"delegate rejected insert" userInfo:nil]; } if (response == EODelegateOverrides) return nil; } /* check some preconditions */ if (![self isOpen]) { return [MySQL4Exception exceptionWithName:@"ChannelNotOpenException" reason:@"MySQL4 connection is not open" userInfo:nil]; } if (self->results != NULL) { return [MySQL4Exception exceptionWithName:@"CommandInProgressException" reason:@"an evaluation is in progress" userInfo:nil]; return NO; } if ([self isFetchInProgress]) { NSLog(@"WARNING: a fetch is still in progress: %@", self); [self cancelFetch]; } if (isDebuggingEnabled) NSLog(@"%@ SQL: %@", self, sql); /* reset environment */ self->isFetchInProgress = NO; /* start query */ s = [sql UTF8String]; if ((rc = mysql_real_query(self->_connection, s, strlen(s))) != 0) { // TODO: might need to close channel on connect exceptions const char *error; error = mysql_error(self->_connection); if (isDebuggingEnabled) NSLog(@"%@ ERROR: %s", self, error); return [MySQL4Exception exceptionWithName:@"ExecutionFailed" reason:[NSString stringWithUTF8String:error] userInfo:nil]; } /* fetch */ if ((self->results = mysql_use_result(self->_connection)) != NULL) { if (isDebuggingEnabled) NSLog(@"%@ query has results, entering fetch-mode.", self); self->isFetchInProgress = YES; } else { /* error _OR_ statement without result-set */ unsigned int merrno; if ((merrno = mysql_errno(self->_connection)) != 0) { const char *error; error = mysql_error(self->_connection); if (isDebuggingEnabled) NSLog(@"%@ cannot use result: '%s'", self, error); return [MySQL4Exception exceptionWithName:@"FetchFailed" reason:[NSString stringWithUTF8String:error] userInfo:nil]; } if (isDebuggingEnabled) NSLog(@"%@ query has no results.", self); } if (delegateRespondsTo.didEvaluateExpression) [delegate adaptorChannel:self didEvaluateExpression:sql]; return nil /* everything is OK */; } - (BOOL)evaluateExpression:(NSString *)_sql { NSException *e; NSString *n; if ((e = [self evaluateExpressionX:_sql]) == nil) return YES; /* for compatibility with non-X methods, translate some errors to a bool */ n = [e name]; if ([n isEqualToString:@"EOEvaluationError"]) return NO; if ([n isEqualToString:@"EODelegateRejects"]) return NO; NSLog(@"ERROR eval '%@': %@", _sql, e); [e raise]; return NO; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:64]; [ms appendFormat:@"<%@[0x%p] connection=0x%p", NSStringFromClass([self class]), self, self->_connection]; [ms appendString:@">"]; return ms; } /* PrimaryKeyGeneration */ - (NSDictionary *)primaryKeyForNewRowWithEntity:(EOEntity *)_entity { NSException *error; NSArray *pkeys; MySQL4Adaptor *adaptor; NSString *seqName, *seq; NSArray *seqs; NSDictionary *pkey; unsigned i, count; id key; pkeys = [_entity primaryKeyAttributeNames]; adaptor = (id)[[self adaptorContext] adaptor]; seqName = [adaptor primaryKeySequenceName]; pkey = nil; seq = nil; if ([seqName length] > 0) { // TODO: if we do this, we also need to make the 'id' configurable ... seq = [@"UPDATE " stringByAppendingString:seqName]; seq = [seq stringByAppendingString:@" SET id=LAST_INSERT_ID(id+1)"]; seqs = [NSArray arrayWithObjects: seq, @"SELECT_LAST_INSERT_ID()", nil]; } else seqs = [[adaptor newKeyExpression] componentsSeparatedByString:@";"]; if ((count = [seqs count]) == 0) { NSLog(@"ERROR(%@): got no primary key expressions %@: %@", self, seqName, _entity); return nil; } for (i = 0; i < count - 1; i++) { if ((error = [self evaluateExpressionX:[seqs objectAtIndex:i]]) != nil) { NSLog(@"ERROR(%@): could not prepare next pkey value %@: %@", self, [seqs objectAtIndex:i], error); return nil; } } seq = [seqs lastObject]; if ((error = [self evaluateExpressionX:seq]) != nil) { NSLog(@"ERROR(%@): could not select next pkey value from sequence %@: %@", self, seqName, error); return nil; } if (![self isFetchInProgress]) { NSLog(@"ERROR(%@): primary key expression returned no result: '%@'", self, seq); return nil; } // TODO: this is kinda slow key = [self describeResults]; pkey = [self fetchAttributes:key withZone:NULL]; [self cancelFetch]; if (pkey != nil) { pkey = [[pkey allValues] lastObject]; pkey = [NSDictionary dictionaryWithObject:pkey forKey:[pkeys objectAtIndex:0]]; } return pkey; } @end /* MySQL4Channel */ void __link_MySQL4Channel() { // used to force linking of object file __link_MySQL4Channel(); } SOPE/sope-gdl1/MySQL/MySQL4Expression.m0000644000000000000000000000537615004363604016365 0ustar rootroot/* MySQL4Expression.m Copyright (C) 2003-2005 Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "MySQL4Expression.h" @implementation MySQL4Expression + (Class)selectExpressionClass { return [MySQL4SelectSQLExpression class]; } @end /* MySQL4Expression */ @implementation MySQL4SelectSQLExpression - (id)selectExpressionForAttributes:(NSArray *)attributes lock:(BOOL)flag qualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder channel:(EOAdaptorChannel *)channel { lock = flag; [super selectExpressionForAttributes:attributes lock:flag qualifier:qualifier fetchOrder:fetchOrder channel:channel]; return self; } - (NSString *)fromClause { NSMutableString *fromClause; NSEnumerator *enumerator; BOOL first = YES; id key; fromClause = [NSMutableString stringWithCString:" "]; enumerator = [fromListEntities objectEnumerator]; // Compute the FROM list from all the aliases found in // entitiesAndPropertiesAliases dictionary. Note that this dictionary // contains entities and relationships. The last ones are there for // flattened attributes over reflexive relationships. while((key = [enumerator nextObject])) { if(first) first = NO; else [fromClause appendString:@", "]; [fromClause appendFormat:@"%@ %@", [key isKindOfClass:[EORelationship class]] ? [[key destinationEntity] externalName] // flattened attribute : [key externalName], // EOEntity [entitiesAndPropertiesAliases objectForKey:key]]; #if 0 if (lock) [fromClause appendString:@" HOLDLOCK"]; #endif } return fromClause; } @end /* MySQL4SelectSQLExpression */ void __link_MySQL4Expression() { // used to force linking of object file __link_MySQL4Expression(); } SOPE/sope-gdl1/MySQL/gdltest.m0000644000000000000000000001234315004363604014712 0ustar rootroot/* gdltest.m Copyright (C) 1999-2005 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #import #include static void fetchExprInChannel(NSString *expr, EOAdaptorChannel *ch) { NSArray *attrs; NSDictionary *record; if (![ch evaluateExpression:expr]) { NSLog(@"ERROR: failed to evaluate: %@", expr); return; } attrs = [ch describeResults]; NSLog(@"results: %@", attrs); while ((record = [ch fetchAttributes:attrs withZone:nil]) != nil) NSLog(@"fetched %@", record); } static void fetchSomePersonRecord(EOEntity *e, EOAdaptorChannel *ch) { EOSQLQualifier *q; NSArray *attrs; attrs = [e attributes]; q = [[EOSQLQualifier alloc] initWithEntity:e qualifierFormat:@"%A='helge'", @"login"]; [q autorelease]; if ([ch selectAttributes:attrs describedByQualifier:q fetchOrder:nil lock:NO]) { NSDictionary *record; record = [ch fetchAttributes:attrs withZone:nil]; } else NSLog(@"Could not select .."); } static void fetchSomeTeamRecords(EOEntity *e, EOAdaptorChannel *ch) { EOSQLQualifier *q; NSArray *attrs; q = [e qualifier]; attrs = [e attributes]; if ([ch selectAttributes:attrs describedByQualifier:q fetchOrder:nil lock:NO]) { NSDictionary *record; while ((record = [ch fetchAttributes:attrs withZone:NULL]) != nil) { NSLog(@"fetched %@ birthday %@", [record valueForKey:@"description"], [record valueForKey:@"companyId"]); } } else NSLog(@"Could not select team records .."); } static void runtestInOpenChannel(EOAdaptorChannel *ch) { NSAutoreleasePool *pool = [NSAutoreleasePool new]; EOEntity *e; EOSQLQualifier *q; NSArray *attrs; EOAdaptorContext *ctx; EOModel *m; NSString *expr; ctx = [ch adaptorContext]; m = [[ctx adaptor] model]; expr = [[NSUserDefaults standardUserDefaults] stringForKey:@"sql"]; NSLog(@"channel is open"); if (![ctx beginTransaction]) { NSLog(@"ERROR: could not begin transaction ..."); return; } NSLog(@"began tx .."); /* do something */ pool = [[NSAutoreleasePool alloc] init]; #if 1 if (expr) fetchExprInChannel(expr, ch); #endif /* fetch some MyEntity records */ e = [m entityNamed:@"MyEntity"]; NSLog(@"entity: %@", e); if (e == nil) exit(1); q = [e qualifier]; attrs = [e attributes]; // NSLog(@"ATTRS: %@", attrs); if ([ch selectAttributes:attrs describedByQualifier:q fetchOrder:nil lock:NO]) { NSDictionary *record; while ((record = [ch fetchAttributes:attrs withZone:nil]) != nil) NSLog(@"fetched record: %@", record); } else NSLog(@"Could not select .."); /* some OGo fetches */ if ((e = [m entityNamed:@"Team"]) != nil) fetchSomeTeamRecords(e, ch); if ((e = [m entityNamed:@"Person"]) != nil) fetchSomePersonRecord(e, ch); /* tear down */ [pool release]; NSLog(@"committing tx .."); if ([ctx commitTransaction]) NSLog(@" could commit."); else NSLog(@" commit failed."); } static void runtest(void) { EOModel *m = nil; EOAdaptor *a; EOAdaptorContext *ctx; EOAdaptorChannel *ch; NSDictionary *conDict; NS_DURING { conDict = [NSDictionary dictionaryWithContentsOfFile:@"condict.plist"]; NSLog(@"condict is %@", conDict); if ((a = [EOAdaptor adaptorWithName:@"MySQL4"]) == nil) { NSLog(@"found no MySQL4 adaptor .."); exit(1); } NSLog(@"got adaptor %@", a); [a setConnectionDictionary:conDict]; NSLog(@"got adaptor with condict %@", a); ctx = [a createAdaptorContext]; ch = [ctx createAdaptorChannel]; #if 1 m = AUTORELEASE([[EOModel alloc] initWithContentsOfFile:@"test.eomodel"]); if (m) { [a setModel:m]; [a setConnectionDictionary:conDict]; } #endif NSLog(@"opening channel .."); [ch setDebugEnabled:YES]; if ([ch openChannel]) { runtestInOpenChannel(ch); NSLog(@"closing channel .."); [ch closeChannel]; } } NS_HANDLER { fprintf(stderr, "exception: %s\n", [[localException description] cString]); abort(); } NS_ENDHANDLER; } int main(int argc, char **argv, char **env) { NSAutoreleasePool *pool; pool = [[NSAutoreleasePool alloc] init]; [NSProcessInfo initializeWithArguments:argv count:argc environment:env]; runtest(); [pool release]; return 0; } SOPE/sope-gdl1/MySQL/GNUmakefile0000644000000000000000000000336715004363604015146 0ustar rootroot# # GNUmakefile # # Copyright (C) 2005 Helge Hess # # Author: Helge Hess (helge.hess@opengroupware.org) # # This file is part of the MySQL4 Adaptor Library # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library 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 # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with this library; see the file COPYING.LIB. # If not, write to the Free Software Foundation, # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. include ../../config.make include $(GNUSTEP_MAKEFILES)/common.make include ../Version include ./Version BUNDLE_NAME = MySQL MySQL_PCH_FILE = common.h MySQL_OBJC_FILES = \ MySQL4Expression.m \ MySQL4Adaptor.m \ MySQL4Context.m \ MySQL4Channel.m \ MySQL4Channel+Model.m \ MySQL4Exception.m \ MySQL4Values.m \ NSString+MySQL4.m \ EOAttribute+MySQL4.m \ NSString+MySQL4Val.m \ NSData+MySQL4Val.m \ NSCalendarDate+MySQL4Val.m \ NSNumber+MySQL4Val.m \ MySQL_PRINCIPAL_CLASS = MySQL4Adaptor BUNDLE_INSTALL = MySQL # Use .gdladaptor as the bundle extension BUNDLE_EXTENSION = .gdladaptor MySQL_RESOURCE_FILES += Version # tool TOOL_NAME = gdltest gdltest_OBJC_FILES = gdltest.m -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/bundle.make ifeq ($(test),yes) include $(GNUSTEP_MAKEFILES)/tool.make endif -include GNUmakefile.postamble SOPE/sope-gdl1/MySQL/MySQL4Exception.h0000644000000000000000000000262715004363604016153 0ustar rootroot/* MySQL4Exception.h Copyright (C) 1999-2005 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___MySQL4_Exception_H___ #define ___MySQL4_Exception_H___ #import @interface MySQL4Exception : NSException { } + (void)raiseWithFormat:(NSString *)_format, ...; @end @interface MySQL4CouldNotOpenChannelException : MySQL4Exception { } @end @interface MySQL4CouldNotConnectException : MySQL4CouldNotOpenChannelException { } @end @interface MySQL4CouldNotBindException : MySQL4Exception { } @end #endif /* ___MySQL4_Exception_H___ */ SOPE/sope-gdl1/MySQL/ChangeLog0000644000000000000000000000501115004363604014632 0ustar rootroot2011-11-02 Francis Lachapelle * NSNumber+MySQL4Val.m (-stringValueForMySQL4Type:attribute:): boolean values are now converted to 0 or 1, as in NSNumber+PGVal.m. 2010-10-07 Wolfgang Sourdeau * EOAttribute+MySQL4.m (-loadValueClassAndTypeUsingMySQL4Type:size:modification:binary:): invalidated method. (-loadValueClassForExternalMySQL4Type:) idem. * NSNumber+MySQL4Val.m (-): added support for unsigned types. * MySQL4Channel.m (-describeResults): added support for unsigned types. 2006-07-24 Helge Hess * MySQL4Channel+Model.m: added SHOW TABLES to retrieve MySQL table names (v4.5.14) 2006-07-04 Helge Hess * use %p for pointer formats, fixed gcc 4.1 warnings (v4.5.13) 2005-07-29 Helge Hess * v4.5.12 * NSData+MySQL4Val.m: fixed handling of NSData rows (proper init was missing) * MySQL4Values.m: improved logging of unsupported types 2005-07-27 Helge Hess * fixed gcc 4.0 warnings (char signedness) (v4.5.11) 2005-04-23 Helge Hess * GNUmakefile.preamble: fixed include flags (v4.5.10) 2005-04-21 Helge Hess * v4.5.9 * GNUmakefile.preamble: use mysql_config --cflags instead of --include, the former is also available with MySQL 3.x * MySQL4Channel.m: added a -describeResults: method to allow descriptions without beautified names 2005-04-20 Helge Hess * MySQL4Channel.m: only warn if the character set could not be changed to UTF-8 (v4.5.8) * renamed MySQL4 adaptor to MySQL to avoid confusion (v4.5.7) 2005-04-19 Helge Hess * v4.5.6 * MySQL4Channel.m: added support for primary key generation * NSNumber+MySQL4Val.m: added support for basic number types * v4.5.5 * MySQL4Values.m: added a workaround to support NSTemporaryString * MySQL4Channel.m: fixed errno result handling * MySQL4Adaptor.m: do not fall back to PGHOST variable if not hostname is set 2005-04-13 Helge Hess * MySQL4Channel.m: finished fetching code (v4.5.4) 2005-04-12 Helge Hess * MySQL4Channel.m: added some fetch result processing (v4.5.3) 2005-04-12 Helge Hess * MySQL4Channel.m: implemented query (v4.5.2) 2005-04-11 Helge Hess * started MySQL4 adaptor based on SQLite one (v4.5.1) SOPE/sope-gdl1/MySQL/common.h0000644000000000000000000000223315004363604014524 0ustar rootroot/* common.h Copyright (C) 1999-2005 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___MySQL4_common_H___ #define ___MySQL4_common_H___ #include #include #include #include #include #endif /* ___MySQL4_common_H___ */ SOPE/sope-gdl1/MySQL/MySQL4Context.h0000644000000000000000000000225415004363604015635 0ustar rootroot/* MySQL4Context.h Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___MySQL4_Context_H___ #define ___MySQL4_Context_H___ #import @interface MySQL4Context : EOAdaptorContext - (BOOL)primaryBeginTransaction; - (BOOL)primaryCommitTransaction; - (BOOL)primaryRollbackTransaction; @end #endif SOPE/sope-gdl1/MySQL/EOAttribute+MySQL4.m0000644000000000000000000001536415004363604016466 0ustar rootroot/* EOAttribute+MySQL4.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #import "EOAttribute+MySQL4.h" static NSString *MYSQL4_DATETIME_FORMAT = @"%b %d %Y %I:%M:%S:000%p"; static NSString *MYSQL4_TIMESTAMP_FORMAT = @"%Y-%m-%d %H:%M:%S%z"; @implementation EOAttribute(MySQL4AttributeAdditions) - (void)loadValueClassAndTypeUsingMySQL4Type:(int)_type size:(int)_size modification:(int)_modification binary:(BOOL)_isBinary { /* This method makes no sense with MySQL4? */ [NSException raise: @"EOAttributeMySQL4ImplementationException" format: @"this method (%s) is not expected to be invoked", __PRETTY_FUNCTION__]; if (_isBinary) [self setValueClassName:@"NSData"]; #if 0 switch (_type) { case BOOLOID: [self setExternalType:@"bool"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"i"]; return; case NAMEOID: [self setExternalType:@"name"]; [self setValueClassName:@"NSString"]; return; case TEXTOID: [self setExternalType:@"textoid"]; [self setValueClassName:@"NSString"]; return; case INT2OID: [self setExternalType:@"int2"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; return; case INT4OID: [self setExternalType:@"int4"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; return; case INT8OID: [self setExternalType:@"int8"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; return; case CHAROID: [self setExternalType:@"char"]; [self setValueClassName:@"NSString"]; break; case VARCHAROID: [self setExternalType:@"varchar"]; [self setValueClassName:@"NSString"]; break; case NUMERICOID: [self setExternalType:@"numeric"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; break; case FLOAT4OID: [self setExternalType:@"float4"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"f"]; break; case FLOAT8OID: [self setExternalType:@"float8"]; [self setValueClassName:@"NSNumber"]; [self setValueType:@"f"]; break; case DATEOID: [self setExternalType:@"datetime"]; [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:MYSQL4_DATETIME_FORMAT]; break; case TIMEOID: [self setExternalType:@"time"]; [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:MYSQL4_DATETIME_FORMAT]; break; case TIMESTAMPOID: [self setExternalType:@"timestamp"]; [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:MYSQL4_DATETIME_FORMAT]; break; case TIMESTAMPTZOID: [self setExternalType:@"timestamptz"]; [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:MYSQL4_DATETIME_FORMAT]; break; case BITOID: [self setExternalType:@"bit"]; break; default: NSLog(@"What is MYSQL4 Oid %i ???", _type); break; } #endif } - (void)loadValueClassForExternalMySQL4Type:(NSString *)_type { /* This method makes no sense with MySQL4? */ [NSException raise: @"EOAttributeMySQL4ImplementationException" format: @"this method (%s) is not expected to be invoked", __PRETTY_FUNCTION__]; if ([_type isEqualToString:@"bool"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"i"]; } else if ([_type isEqualToString:@"int2"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"i"]; } else if ([_type isEqualToString:@"int2 unsigned"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"I"]; } else if ([_type isEqualToString:@"int4"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"i"]; } else if ([_type isEqualToString:@"int4 unsigned"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"I"]; } else if ([_type isEqualToString:@"float4"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"f"]; } else if ([_type isEqualToString:@"float8"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; } else if ([_type isEqualToString:@"decimal"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; } else if ([_type isEqualToString:@"numeric"]) { [self setValueClassName:@"NSNumber"]; [self setValueType:@"d"]; } else if ([_type isEqualToString:@"name"]) { [self setExternalType:@"name"]; [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"varchar"]) { [self setExternalType:@"varchar"]; [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"char"]) { [self setExternalType:@"char"]; [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"timestamp"]) { [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:MYSQL4_TIMESTAMP_FORMAT]; } else if ([_type isEqualToString:@"timestamptz"]) { [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:MYSQL4_TIMESTAMP_FORMAT]; } else if ([_type isEqualToString:@"datetime"]) { [self setValueClassName:@"NSCalendarDate"]; [self setCalendarFormat:MYSQL4_DATETIME_FORMAT]; } else if ([_type isEqualToString:@"date"]) { [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"time"]) { [self setValueClassName:@"NSString"]; } else if ([_type isEqualToString:@"text"]) { [self setValueClassName:@"NSString"]; } else { NSLog(@"invalid argument %@", _type); [NSException raise:@"InvalidArgumentException" format:@"invalid MySQL4 type %@ passed to %s", _type, __PRETTY_FUNCTION__]; } } @end /* EOAttribute(MySQL4) */ void __link_EOAttributeMySQL4() { // used to force linking of object file __link_EOAttributeMySQL4(); } SOPE/sope-gdl1/MySQL/NSString+MySQL4Val.m0000644000000000000000000000702415004363604016443 0ustar rootroot/* MySQL4Adaptor.h Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "MySQL4Channel.h" #include #import #include "common.h" #include @implementation NSString(MySQL4Values) static Class EOExprClass = Nil; - (id)initWithMySQL4Field:(MYSQL_FIELD *)_field value:(const void *)_v length:(int)_len { // Note: never used on lF (NSTemporaryString!) if (_v == NULL) { [self release]; return nil; } switch (_field->type) { case FIELD_TYPE_BLOB: case FIELD_TYPE_TINY_BLOB: case FIELD_TYPE_MEDIUM_BLOB: case FIELD_TYPE_LONG_BLOB: ; /* fall through */ default: /* we always fallback to the UTF-8 string ... */ return [self initWithUTF8String:_v]; } } #if 0 - (id)initWithMySQL4Int:(int)_value { char buf[256]; sprintf(buf, "%i", _value); return [self initWithCString:buf]; } - (id)initWithMySQL4Double:(double)_value { char buf[256]; sprintf(buf, "%g", _value); return [self initWithCString:buf]; } - (id)initWithMySQL4Text:(const unsigned char *)_value { return [self initWithUTF8String:_value]; } - (id)initWithMySQL4Data:(const void *)_value length:(int)_length { NSData *d; d = [[NSData alloc] initWithBytes:_value length:_length]; self = [self initWithData:d encoding:NSUTF8StringEncoding]; [d release]; return self; } #endif /* generate SQL value */ - (NSString *)stringValueForMySQL4Type:(NSString *)_type attribute:(EOAttribute *)_attribute { // TODO: all this looks slow ... unsigned len; unichar c1; if ((len = [_type length]) == 0) return self; c1 = [_type characterAtIndex:0]; switch (c1) { case 'c': case 'C': // char case 'v': case 'V': // varchar case 't': case 'T': { // text NSString *s; id expr; if (len < 4) return self; _type = [_type lowercaseString]; if (!([_type hasPrefix:@"char"] || [_type hasPrefix:@"varchar"] || [_type hasPrefix:@"text"])) break; /* TODO: creates too many autoreleased strings :-( */ expr = [self stringByReplacingString:@"\\" withString:@"\\\\"]; if (EOExprClass == Nil) EOExprClass = [EOQuotedExpression class]; expr = [[EOExprClass alloc] initWithExpression:expr quote:@"'" escape:@"\\'"]; s = [[(EOQuotedExpression *)expr expressionValueForContext:nil] retain]; [expr release]; return [s autorelease]; } case 'i': case 'I': { // int char buf[128]; sprintf(buf, "%i", [self intValue]); return [NSString stringWithCString:buf]; } default: NSLog(@"WARNING(%s): return string as is for type %@", __PRETTY_FUNCTION__, _type); break; } return self; } @end /* NSString(MySQL4Values) */ SOPE/sope-gdl1/MySQL/fhs.make0000644000000000000000000000122515004363604014502 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) FHS_LIB_DIR=$(CONFIGURE_FHS_INSTALL_LIBDIR) FHS_DB_DIR=$(FHS_LIB_DIR)sope-$(SOPE_MAJOR_VERSION).$(SOPE_MINOR_VERSION)/dbadaptors/ fhs-db-dirs :: $(MKDIRS) $(FHS_DB_DIR) move-bundles-to-fhs :: fhs-db-dirs @echo "moving bundles $(BUNDLE_INSTALL_DIR) to $(FHS_DB_DIR) .." for i in $(BUNDLE_NAME); do \ j="$(FHS_DB_DIR)/$${i}$(BUNDLE_EXTENSION)"; \ if test -d $$j; then rm -r $$j; fi; \ mv "$(BUNDLE_INSTALL_DIR)/$${i}$(BUNDLE_EXTENSION)" $$j; \ done move-to-fhs :: move-bundles-to-fhs after-install :: move-to-fhs endif SOPE/sope-gdl1/MySQL/COPYING.LIB0000644000000000000000000006126115004363604014531 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 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. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-gdl1/MySQL/README0000644000000000000000000000166315004363604013751 0ustar rootroot# MySQL4 Adaptor Note: this is far from being complete! The adaptor is currently a fork of the MySQL4 adaptor. http://sql-info.de/mysql/gotchas.html TODO ==== - implement Basics ====== Open a Shell: mysql --password=abc > use OGo > insert schema > select * from date_x; Configure the Adaptor (below does not work yet for MySQL4!) Defaults write ogo-webui-1.0a LSAdaptor MySQL4 Defaults write ogo-webui-1.0a LSConnectionDictionary \ '{ databaseName = OGo; }' Defaults write ogo-webui-1.0a PKeyGeneratorDictionary \ "{ newKeyExpression=\"select nextval(\\'key_generator\\');\" }" MySQL4DebugEnabled Setup gdltest Database ====================== mysql --password=abc > create database Test; > use Test; > CREATE TABLE my_table ( pkey INT PRIMARY KEY ); Notes ===== mysql_store_result - does not block the server, full result in memory vs mysql_use_result - does block the server, one row in memory SOPE/sope-gdl1/MySQL/condict.plist0000644000000000000000000000015215004363604015561 0ustar rootroot{ hostName = "127.0.0.1"; userName = "OGo"; password = "OGo"; databaseName = "OGo"; } SOPE/sope-gdl1/MySQL/EOAttribute+MySQL4.h0000644000000000000000000000251215004363604016450 0ustar rootroot/* EOAttribute+MySQL4.h Copyright (C) 2003-2004 Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___MySQL4_EOAttribute_H___ #define ___MySQL4_EOAttribute_H___ #import @class NSString; @interface EOAttribute(MySQL4AttributeAdditions) - (void)loadValueClassAndTypeUsingMySQL4Type:(int)_type size:(int)_size modification:(int)_modification binary:(BOOL)_isBinary; - (void)loadValueClassForExternalMySQL4Type:(NSString *)_type; @end #endif /* ___MySQL4_EOAttribute_H___ */ SOPE/sope-gdl1/MySQL/MySQL4Channel.h0000644000000000000000000000451615004363604015564 0ustar rootroot/* MySQL4Channel.h Copyright (C) 2003-2005 Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___MySQL4_Channel_H___ #define ___MySQL4_Channel_H___ #import @class NSArray, NSString, NSMutableDictionary; @interface MySQL4Channel : EOAdaptorChannel { // connection is valid after an openChannel call void *_connection; void *results; void *fields; int fieldCount; #if 0 int tupleCount; BOOL containsBinaryData; NSString *cmdStatus; NSString *cmdTuples; NSString *oidStatus; int currentTuple; #endif // turns on/off channel debugging BOOL isDebuggingEnabled; NSMutableDictionary *_attributesForTableName; NSMutableDictionary *_primaryKeysNamesForTableName; } - (void)setDebugEnabled:(BOOL)_flag; - (BOOL)isDebugEnabled; - (BOOL)isOpen; - (BOOL)openChannel; - (void)closeChannel; - (NSMutableDictionary *)primaryFetchAttributes:(NSArray *)_attributes withZone:(NSZone *)_zone; - (BOOL)evaluateExpression:(NSString *)_expression; // cancelFetch is always called to terminate a fetch // (even by primaryFetchAttributes) // it frees all fetch-local variables - (void)cancelFetch; // uses dataFormat type information to create EOAttribute objects - (NSArray *)describeResults; @end @interface NSObject(Sybase10ChannelDelegate) - (NSArray*)sqlite3Channel:(MySQL4Channel *)channel willFetchAttributes:(NSArray *)attributes; - (BOOL)sqlite3Channel:(MySQL4Channel *)channel willReturnRow:(NSDictionary *)row; @end #endif /* ___MySQL4_Channel_H___ */ SOPE/sope-gdl1/MySQL/NSCalendarDate+MySQL4Val.m0000644000000000000000000001563015004363604017506 0ustar rootroot/* NSCalendarDate+MySQL4Val.m Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #include #include "MySQL4Channel.h" #include "common.h" #if COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY @interface NSCalendarDate(UsedPrivates) - (id)initWithTimeIntervalSince1970:(NSTimeInterval)_tv; @end #endif static NSString *MYSQL4_DATETIME_FORMAT = @"%b %d %Y %I:%M:%S:000%p"; @implementation NSCalendarDate(MySQL4Values) /* Format: '2001-07-26 14:00:00+02' '2001-07-26 14:00:00+09:30' 0123456789012345678901234 Matthew: "07/25/2003 06:00:00 CDT". */ static NSTimeZone *DefServerTimezone = nil; #if 0 static NSTimeZone *gmt = nil; static NSTimeZone *gmt01 = nil; static NSTimeZone *gmt02 = nil; #endif - (id)initWithMySQL4Field:(MYSQL_FIELD *)_field value:(const void *)_v length:(int)_len { NSString *s; NSString *calfmt; s = [[NSString alloc] initWithCString:_v length:_len]; // Unicode calfmt = nil; // TODO: avoid using format strings switch (_len) { // as suggested by SQLClient case 14: calfmt = @"%Y%m%d%H%M%S"; break; case 12: calfmt = @"%y%m%d%H%M%S"; break; case 10: calfmt = @"%y%m%d%H%M"; break; case 8: calfmt = @"%y%m%d%H"; break; case 6: calfmt = @"%y%m%d"; break; case 4: calfmt = @"%y%m"; break; default: calfmt = _len > 14 ? @"%Y-%m-%d %H:%M:%S" : @"%y"; break; } if ((self = [self initWithString:s calendarFormat:calfmt]) == nil) { NSLog(@"WARNING(%s): got no value for string '%@' format '%@'.", __PRETTY_FUNCTION__, s, calfmt); } [s release]; [self setCalendarFormat:MYSQL4_DATETIME_FORMAT]; return self; } #if 0 - (id)initWithMySQL4Data:(const void *)_value length:(int)_length { static unsigned char buf[28]; // reused buffer, THREAD const char *_cstr = _value; unsigned char *p; NSTimeZone *attrTZ; NSCalendarDate *date; int year, month, day, hour, min, sec, tzOffset; if (_length == 0) return nil; if (_length != 22 && _length != 25) { NSLog(@"ERROR(%s): unexpected date string '%s', returning now" @" (expected format: '2001-07-26 14:00:00+02')", __PRETTY_FUNCTION__, _cstr); return [NSCalendarDate date]; } strncpy(buf, _cstr, 25); buf[25] = '\0'; /* perform on reverse, so that we don't overwrite with null-terminators */ if (_length == 22) { p = &(buf[19]); tzOffset = atoi(p) * 60; } else if (_length >= 25) { int mins; p = &(buf[23]); mins = atoi(p); buf[22] = '\0'; // the ':' p = &(buf[19]); tzOffset = atoi(p) * 60; tzOffset = tzOffset > 0 ? (tzOffset + mins) : (tzOffset - mins); } p = &(buf[17]); buf[19] = '\0'; sec = atoi(p); p = &(buf[14]); buf[16] = '\0'; min = atoi(p); p = &(buf[11]); buf[13] = '\0'; hour = atoi(p); p = &(buf[8]); buf[10] = '\0'; day = atoi(p); p = &(buf[5]); buf[7] = '\0'; month = atoi(p); p = &(buf[0]); buf[4] = '\0'; year = atoi(p); /* TODO: cache all timezones (just 26 ;-) */ switch (tzOffset) { case 0: if (gmt == nil) { gmt = [[NSTimeZone timeZoneForSecondsFromGMT:0] retain]; NSAssert(gmt, @"could not create GMT timezone?!"); } attrTZ = gmt; break; case 60: if (gmt01 == nil) { gmt01 = [[NSTimeZone timeZoneForSecondsFromGMT:3600] retain]; NSAssert(gmt01, @"could not create GMT+01 timezone?!"); } attrTZ = gmt01; break; case 120: if (gmt02 == nil) { gmt02 = [[NSTimeZone timeZoneForSecondsFromGMT:7200] retain]; NSAssert(gmt02, @"could not create GMT+02 timezone?!"); } attrTZ = gmt02; break; default: { /* cache the first, "alternative" timezone */ static int firstTZOffset = 0; // can use 0 since GMT is a separate case static NSTimeZone *firstTZ = nil; if (firstTZOffset == 0) { firstTZOffset = tzOffset; firstTZ = [[NSTimeZone timeZoneForSecondsFromGMT:(tzOffset*60)] retain]; } attrTZ = (firstTZOffset == tzOffset) ? firstTZ : [NSTimeZone timeZoneForSecondsFromGMT:(tzOffset * 60)]; break; } } if (NSCalDateClass == Nil) NSCalDateClass = [NSCalendarDate class]; date = [NSCalDateClass dateWithYear:year month:month day:day hour:hour minute:min second:sec timeZone:attrTZ]; if (date == nil) { NSLog(@"ERROR(%s): could not construct date from string '%s': " @"year=%i,month=%i,day=%i,hour=%i,minute=%i,second=%i, tz=%@", __PRETTY_FUNCTION__, _cstr, year, month, day, hour, min, sec, attrTZ); } return date; } #endif /* generating value */ - (NSString *)stringValueForMySQL4Type:(NSString *)_type attribute:(EOAttribute *)_attribute { #if 0 NSString *format; #endif EOQuotedExpression *expr; NSTimeZone *serverTimeZone; NSString *format; NSString *val; unsigned len; unichar c1; if ((len = [_type length]) == 0) c1 = 0; else c1 = [_type characterAtIndex:0]; if (c1 == 'i' || c1 == 'I') { // INTEGER char buf[64]; sprintf(buf, "%d", ((unsigned int)[self timeIntervalSince1970])); return [NSString stringWithCString:buf]; } if (c1 == 'r' || c1 == 'R') { // REAL char buf[64]; // TODO: check format sprintf(buf, "%f", [self timeIntervalSince1970]); return [NSString stringWithCString:buf]; } if ((serverTimeZone = [_attribute serverTimeZone]) == nil ) { if (DefServerTimezone == nil) { DefServerTimezone = [[NSTimeZone localTimeZone] retain]; NSLog(@"Note: MySQL4 adaptor using timezone '%@' as default", DefServerTimezone); } serverTimeZone = DefServerTimezone; } #if 0 format = [_attribute calendarFormat]; #else /* hm, why is that? */ format = @"%Y-%m-%d %H:%M:%S%z"; #endif if (format == nil) format = MYSQL4_DATETIME_FORMAT; [self setTimeZone:serverTimeZone]; val = [self descriptionWithCalendarFormat:format]; expr = [[EOQuotedExpression alloc] initWithExpression:val quote:@"\'" escape:@"\\'"]; val = [[expr expressionValueForContext:nil] retain]; [expr release]; return [val autorelease]; } @end /* NSCalendarDate(MySQL4Values) */ SOPE/sope-gdl1/MySQL/NSString+MySQL4.h0000644000000000000000000000244515004363604015775 0ustar rootroot/* NSString+MySQL4.h Copyright (C) 1999-2005 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___MySQL4_NSString_H___ #define ___MySQL4_NSString_H___ #import @interface NSString(MySQL4MiscStrings) - (NSString *)_mySQL4ModelMakeInstanceVarName; - (NSString *)_mySQL4ModelMakeClassName; - (NSString *)_mySQL4StringWithCapitalizedFirstChar; - (NSString *)_mySQL4StripEndSpaces; @end #endif /* ___MySQL4_NSString_H___ */ SOPE/sope-gdl1/MySQL/NSNumber+MySQL4Val.m0000644000000000000000000000755315004363604016434 0ustar rootroot/* MySQL4Adaptor.h Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #include "MySQL4Channel.h" #include "common.h" #include @implementation NSNumber(MySQL4Values) - (id)initWithMySQL4Field:(MYSQL_FIELD *)_field value:(const void *)_v length:(int)_len { if (_v == NULL) { [self release]; return nil; } switch (_field->type) { case FIELD_TYPE_TINY: return ((_field->flags & UNSIGNED_FLAG) ? [self initWithUnsignedChar:atoi(_v)] : [self initWithChar:atoi(_v)]); case FIELD_TYPE_SHORT: return ((_field->flags & UNSIGNED_FLAG) ? [self initWithUnsignedShort:atoi(_v)] : [self initWithShort:atoi(_v)]); case FIELD_TYPE_LONG: return ((_field->flags & UNSIGNED_FLAG) ? [self initWithUnsignedLong:strtoul(_v, NULL, 10)] : [self initWithLong:strtol(_v, NULL, 10)]); case FIELD_TYPE_LONGLONG: return ((_field->flags & UNSIGNED_FLAG) ? [self initWithUnsignedLong:strtoull(_v, NULL, 10)] : [self initWithLongLong:strtoll(_v, NULL, 10)]); case FIELD_TYPE_FLOAT: return [self initWithFloat:atof(_v)]; case FIELD_TYPE_DOUBLE: return [self initWithDouble:atof(_v)]; default: NSLog(@"ERROR(%s): unsupported MySQL type: %i (len=%d)", __PRETTY_FUNCTION__, _field->type, _len); [self release]; return nil; } } /* generation */ - (NSString *)stringValueForMySQL4Type:(NSString *)_type attribute:(EOAttribute *)_attribute { // TODO: can we avoid the lowercaseString? unsigned len; unichar c1; if ((len = [_type length]) == 0) return [self stringValue]; if (len < 4) { #if GNUSTEP_BASE_LIBRARY /* on gstep-base -stringValue of bool's return YES or NO, which seems to be different on Cocoa and liBFoundation. */ { static Class BoolClass = Nil; if (BoolClass == Nil) BoolClass = NSClassFromString(@"NSBoolNumber"); if ([self isKindOfClass:BoolClass]) return [self boolValue] ? @"1" : @"0"; } #endif return [self stringValue]; } c1 = [_type characterAtIndex:0]; switch (c1) { case 'b': case 'B': if (![[_type lowercaseString] hasPrefix:@"bool"]) break; return [self boolValue] ? @"true" : @"false"; case 'm': case 'M': { if (![[_type lowercaseString] hasPrefix:@"money"]) break; return [@"$" stringByAppendingString:[self stringValue]]; } case 'c': case 'C': case 't': case 'T': case 'v': case 'V': { static NSMutableString *ms = nil; // reuse mstring, THREAD _type = [_type lowercaseString]; if (!([_type hasPrefix:@"char"] || [_type hasPrefix:@"varchar"] || [_type hasPrefix:@"text"])) break; // TODO: can we get this faster?! if (ms == nil) ms = [[NSMutableString alloc] initWithCapacity:256]; [ms setString:@"'"]; [ms appendString:[self stringValue]]; [ms appendString:@"'"]; return [[ms copy] autorelease]; } } return [self stringValue]; } @end /* NSNumber(MySQL4Values) */ SOPE/sope-gdl1/MySQL/NSString+MySQL4.m0000644000000000000000000001030015004363604015767 0ustar rootroot/* NSString+MySQL4.m Copyright (C) 1999 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if LIB_FOUNDATION_BOEHM_GC # include #endif #include "NSString+MySQL4.h" #include "common.h" @implementation NSString(MySQL4MiscStrings) - (NSString *)_mySQL4ModelMakeInstanceVarName { unsigned clen = 0; char *s = NULL; int cnt, cnt2; if ([self length] == 0) return @""; clen = [self cStringLength]; s = malloc(clen + 10); [self getCString:s maxLength:clen]; for (cnt = cnt2 = 0; cnt < clen; cnt++, cnt2++) { if ((s[cnt] == '_') && (s[cnt + 1] != '\0')) { s[cnt2] = toupper(s[cnt + 1]); cnt++; } else if ((s[cnt] == '2') && (s[cnt + 1] != '\0')) { s[cnt2] = s[cnt]; cnt++; cnt2++; s[cnt2] = toupper(s[cnt]); } else s[cnt2] = tolower(s[cnt]); } s[cnt2] = '\0'; return [[[NSString alloc] initWithCStringNoCopy:s length:strlen(s) freeWhenDone:YES] autorelease]; } - (NSString *)_mySQL4ModelMakeClassName { unsigned clen = 0; char *s = NULL; int cnt, cnt2; if ([self length] == 0) return @""; clen = [self cStringLength]; s = malloc(clen + 10); [self getCString:s maxLength:clen]; for (cnt = cnt2 = 0; cnt < clen; cnt++, cnt2++) { if ((s[cnt] == '_') && (s[cnt + 1] != '\0')) { s[cnt2] = toupper(s[cnt + 1]); cnt++; } else if ((s[cnt] == '2') && (s[cnt + 1] != '\0')) { s[cnt2] = s[cnt]; cnt++; cnt2++; s[cnt2] = toupper(s[cnt]); } else s[cnt2] = tolower(s[cnt]); } s[cnt2] = '\0'; s[0] = toupper(s[0]); return [[[NSString alloc] initWithCStringNoCopy:s length:strlen(s) freeWhenDone:YES] autorelease]; } - (NSString *)_mySQL4StringWithCapitalizedFirstChar { NSCharacterSet *upperSet; NSMutableString *str; if ([self length] == 0) return @""; upperSet = [NSCharacterSet uppercaseLetterCharacterSet]; if ([upperSet characterIsMember:[self characterAtIndex:0]]) return [[self copy] autorelease]; str = [NSMutableString stringWithCapacity:[self length]]; [str appendString:[[self substringToIndex:1] uppercaseString]]; [str appendString:[self substringFromIndex:1]]; return [[str copy] autorelease]; } - (NSString *)_mySQL4StripEndSpaces { NSCharacterSet *spaceSet; NSMutableString *str; unichar (*charAtIndex)(id, SEL, int); NSRange range; if ([self length] == 0) return [[self copy] autorelease]; spaceSet = [NSCharacterSet whitespaceCharacterSet]; str = [NSMutableString stringWithCapacity:[self length]]; charAtIndex = (unichar (*)(id, SEL, int)) [self methodForSelector:@selector(characterAtIndex:)]; range.length = 0; for (range.location = ([self length] - 1); range.location >= 0; range.location++, range.length++) { unichar c; c = charAtIndex(self, @selector(characterAtIndex:), range.location); if (![spaceSet characterIsMember:c]) break; } if (range.length > 0) { [str appendString:self]; [str deleteCharactersInRange:range]; return [[str copy] autorelease]; } return [[self copy] autorelease]; } @end void __link_NSStringMySQL4() { // used to force linking of object file __link_NSStringMySQL4(); } SOPE/sope-gdl1/MySQL/NSData+MySQL4Val.m0000644000000000000000000000564215004363604016052 0ustar rootroot/* NSData+MySQL4Val.m Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "MySQL4Values.h" #include "MySQL4Channel.h" #import #include "common.h" @implementation NSData(MySQL4Values) - (id)initWithMySQL4Field:(MYSQL_FIELD *)_field value:(const void *)_v length:(int)_len { // Note: never used on lF (NSTemporaryString!) if (_v == NULL) { [self release]; return nil; } return [self initWithBytes:_v length:_len]; } #if 0 // unused? - (id)initWithMySQL4Int:(int)_value { return [self initWithBytes:&_value length:sizeof(int)]; } - (id)initWithMySQL4Double:(double)_value { return [self initWithBytes:&_value length:sizeof(double)]; } - (id)initWithMySQL4Text:(const unsigned char *)_value { return [self initWithBytes:_value length:strlen((char *)_value)]; } - (id)initWithMySQL4Data:(const void *)_value length:(int)_length { return [self initWithBytes:_value length:_length]; } #endif - (NSString *)stringValueForMySQL4Type:(NSString *)_type attribute:(EOAttribute *)_attribute { // TODO: UNICODE // TODO: this method looks slow static NSStringEncoding enc = 0; NSString *str, *t; unsigned len; unichar c1; if ((len = [self length]) == 0) return @""; if (enc == 0) { enc = [NSString defaultCStringEncoding]; NSLog(@"Note: MySQL4 adaptor using '%@' encoding for data=>string " @"conversion.", [NSString localizedNameOfStringEncoding:enc]); } str = [[NSString alloc] initWithData:self encoding:enc]; if (((len = [_type length]) == 0) || (len != 4 && len != 5 && len != 7)) return [str autorelease]; c1 = [_type characterAtIndex:0]; switch (c1) { case 'c': case 'C': case 'v': case 'V': case 'm': case 'M': case 't': case 'T': t = [_type lowercaseString]; if ([t hasPrefix:@"char"] || [t hasPrefix:@"varchar"] || [t hasPrefix:@"money"] || [t hasPrefix:@"text"]) { t = [[str stringValueForMySQL4Type:_type attribute:_attribute] retain]; [str release]; return [t autorelease]; } } return [str autorelease];; } @end /* NSData(MySQL4Values) */ SOPE/sope-gdl1/MySQL/MySQL4Adaptor.h0000644000000000000000000000375515004363604015612 0ustar rootroot/* MySQL4Adaptor.h Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___MySQL4_Adaptor_H___ #define ___MySQL4_Adaptor_H___ /* The MySQL4 adaptor. The connection dictionary of this adaptor understands these keys: hostName port options userName password databaseName */ #import #import #import @class NSString, NSMutableDictionary; @interface MySQL4Adaptor : EOAdaptor { } - (id)initWithName:(NSString *)_name; // connection management - (NSString *)serverName; - (NSString *)loginName; - (NSString *)loginPassword; - (NSString *)databaseName; - (NSString *)port; - (NSString *)options; - (NSString *)newKeyExpression; // sequence for primary key generation - (NSString *)primaryKeySequenceName; // value formatting - (id)formatValue:(id)value forAttribute:(EOAttribute *)attribute; // attribute typing - (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr; // classes used - (Class)adaptorContextClass; // MySQL4Context - (Class)adaptorChannelClass; // MySQL4Channel - (Class)expressionClass; // MySQL4Expression @end #endif SOPE/sope-gdl1/MySQL/Version0000644000000000000000000000004515004363604014432 0ustar rootroot# Version file SUBMINOR_VERSION:=14 SOPE/sope-gdl1/MySQL/MySQL4Values.m0000644000000000000000000001143715004363604015460 0ustar rootroot/* MySQL4Values.m Copyright (C) 1999-2005 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "MySQL4Values.h" #include "common.h" #include @implementation MySQL4DataTypeMappingException - (id)initWithObject:(id)_obj forAttribute:(EOAttribute *)_attr andMySQL4Type:(NSString *)_dt inChannel:(MySQL4Channel *)_channel; { NSDictionary *ui; NSString *typeName = nil; NSString *r; typeName = _dt; if (typeName == nil) typeName = [NSString stringWithFormat:@"Oid[%i]", _dt]; r = [NSString stringWithFormat: @"mapping between %@ and " @"MySQL4 type %@ is not supported", [_obj description], NSStringFromClass([_obj class]), typeName]; ui = [NSDictionary dictionaryWithObjectsAndKeys: _attr, @"attribute", _channel, @"channel", _obj, @"object", nil]; return [self initWithName:@"DataTypeMappingNotSupported" reason:r userInfo:ui]; } @end /* MySQL4DataTypeMappingException */ @implementation NSNull(MySQL4Values) - (NSString *)stringValueForMySQL4Type:(NSString *)_type attribute:(EOAttribute *)_attribute { return @"null"; } @end /* NSNull(MySQL4Values) */ @implementation NSObject(MySQL4Values) - (id)initWithMySQL4Field:(MYSQL_FIELD *)_field value:(const void *)_v length:(int)_len { /* Note: called for NSTemporaryString! */ if (![self respondsToSelector:@selector(initWithUTF8String:)]) { if (_v == NULL) { [self release]; return nil; } NSLog(@"WARNING(%s): %@ falling back to NSString for MySQL4 value" @" (type %i, 0x%p, len=%d)", __PRETTY_FUNCTION__, NSStringFromClass([self class]), _field->type, _v, _len); [self release]; return [[NSString alloc] initWithMySQL4Field:_field value:_v length:_len]; } /* we assume NSTemporaryString here */ switch (_field->type) { case FIELD_TYPE_BLOB: case FIELD_TYPE_TINY_BLOB: case FIELD_TYPE_MEDIUM_BLOB: case FIELD_TYPE_LONG_BLOB: ; /* fall through */ default: /* we always fallback to the UTF-8 string ... */ return [(NSString *)self initWithUTF8String:_v]; } } #if 0 - (id)initWithMySQL4Int:(int)_value { if ([self respondsToSelector:@selector(initWithInt:)]) return [(NSNumber *)self initWithInt:_value]; if ([self respondsToSelector:@selector(initWithDouble:)]) return [(NSNumber *)self initWithDouble:_value]; if ([self respondsToSelector:@selector(initWithString:)]) { NSString *s; char buf[256]; sprintf(buf, "%i", _value); s = [[NSString alloc] initWithCString:buf]; self = [(NSString *)self initWithString:s]; [s release]; return self; } [self release]; return nil; } - (id)initWithMySQL4Double:(double)_value { if ([self respondsToSelector:@selector(initWithDouble:)]) return [(NSNumber *)self initWithDouble:_value]; [self release]; return nil; } - (id)initWithMySQL4Text:(const unsigned char *)_value { if ([self respondsToSelector:@selector(initWithString:)]) { NSString *s; s = [[NSString alloc] initWithUTF8String:_value]; self = [(NSString *)self initWithString:s]; [s release]; return self; } [self release]; return nil; } - (id)initWithMySQL4Data:(const void *)_data length:(int)_length { if ([self respondsToSelector:@selector(initWithBytes:length:)]) return [(NSData *)self initWithBytes:_data length:_length]; if ([self respondsToSelector:@selector(initWithData:)]) { NSData *d; d = [[NSData alloc] initWithBytes:_data length:_length]; self = [(NSData *)self initWithData:d]; [d release]; return self; } [self release]; return nil; } #endif @end /* NSObject(MySQL4Values) */ void __link_MySQL4Values() { // used to force linking of object file __link_MySQL4Values(); } SOPE/sope-gdl1/MySQL/MySQL4Channel+Model.h0000644000000000000000000000231115004363604016607 0ustar rootroot/* MySQL4Channel+Model.h Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___MySQL4_ModelFetching_H___ #define ___MySQL4_ModelFetching_H___ #import "MySQL4Channel.h" @class NSArray; @class EOModel; @interface MySQL4Channel(ModelFetching) - (EOModel *)describeModelWithTableNames:(NSArray *)_tableNames; - (NSArray *)describeTableNames; @end #endif SOPE/sope-gdl1/MySQL/test.eomodel0000644000000000000000000000131615004363604015411 0ustar rootroot{ EOModelVersion = 1; adaptorClassName = SQLiteAdaptor; adaptorName = SQLite3; entities = ( { /* CREATE TABLE my_table ( pkey INT PRIMARY KEY ); */ name = MyEntity; externalName = my_table; className = EOGenericRecord; primaryKeyAttributes = ( pkey ); attributesUsedForLocking = ( pkey ); classProperties = ( pkey ); attributes = ( { valueClassName = NSNumber; columnName = pkey; name = pkey; valueType = i; externalType = INT; // t_id }, ); } ); } SOPE/sope-gdl1/MySQL/MySQL4Expression.h0000644000000000000000000000304415004363604016346 0ustar rootroot/* MySQL4Expression.h Copyright (C) 1999-2005 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___MySQL4_SQLExpression_H___ #define ___MySQL4_SQLExpression_H___ #include @class NSString, NSArray; @class EOSQLQualifier, EOAdaptorChannel; @interface MySQL4Expression : EOSQLExpression + (Class)selectExpressionClass; @end @interface MySQL4SelectSQLExpression : EOSelectSQLExpression { BOOL lock; } - (id)selectExpressionForAttributes:(NSArray *)attributes lock:(BOOL)flag qualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder channel:(EOAdaptorChannel *)channel; - (NSString *)fromClause; @end #endif /* ___MySQL4_SQLExpression_H___ */ SOPE/sope-gdl1/MySQL/MySQL4Values.h0000644000000000000000000000412415004363604015446 0ustar rootroot/* MySQL4Values.h Copyright (C) 1999-2005 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ___MySQL4_Values_H___ #define ___MySQL4_Values_H___ #import #import #import #import #import #import "MySQL4Exception.h" #include @class EOAttribute; @class MySQL4Channel; @interface MySQL4DataTypeMappingException : MySQL4Exception - (id)initWithObject:(id)_obj forAttribute:(EOAttribute *)_attr andMySQL4Type:(NSString *)_dt inChannel:(MySQL4Channel *)_channel; @end @protocol MySQL4Values - (NSString *)stringValueForMySQL4Type:(NSString *)_type attribute:(EOAttribute *)_attribute; @end @interface NSObject(MySQL4Values) - (id)initWithMySQL4Field:(MYSQL_FIELD *)_field value:(const void *)_v length:(int)_len; @end @interface NSString(MySQL4Values) < MySQL4Values > @end @interface NSNumber(MySQL4Values) < MySQL4Values > @end @interface NSData(MySQL4Values) < MySQL4Values > @end @interface NSCalendarDate(MySQL4Values) < MySQL4Values > @end @interface EONull(MySQL4Values) - (NSString *)stringValueForMySQL4Type:(NSString *)_type attribute:(EOAttribute *)_attribute; @end #endif /* ___MySQL4_Values_H___ */ SOPE/sope-gdl1/MySQL/MySQL4Context.m0000644000000000000000000000444315004363604015644 0ustar rootroot/* MySQL4Context.m Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "MySQL4Context.h" #include "MySQL4Channel.h" #include "common.h" /* Note: MySQL doesn't know 'BEGIN TRANSACTION'. It prefers 'START TRANSACTION' which was added in 4.0.11, which is why we use just 'BEGIN' (available since 3.23.17) */ @implementation MySQL4Context - (void)channelDidInit:_channel { if ([channels count] > 0) { [NSException raise:@"TooManyOpenChannelsException" format:@"MySQL4 only supports one channel per context"]; } [super channelDidInit:_channel]; } - (BOOL)primaryBeginTransaction { BOOL result; result = [[[channels lastObject] nonretainedObjectValue] evaluateExpression:@"BEGIN"]; return result; } - (BOOL)primaryCommitTransaction { BOOL result; result = [[[channels lastObject] nonretainedObjectValue] evaluateExpression:@"COMMIT"]; return result; } - (BOOL)primaryRollbackTransaction { BOOL result; result = [[[channels lastObject] nonretainedObjectValue] evaluateExpression:@"ROLLBACK"]; return result; } - (BOOL)canNestTransactions { return NO; } // NSCopying methods - (id)copyWithZone:(NSZone *)zone { return [self retain]; } @end /* MySQL4Context */ void __link_MySQL4Context() { // used to force linking of object file __link_MySQL4Context(); } SOPE/sope-gdl1/MySQL/MySQL4Channel+Model.m0000644000000000000000000002505415004363604016625 0ustar rootroot/* MySQL4Channel+Model.m Copyright (C) 2003-2006 SKYRIX Software AG Copyright (C) 2006 Helge Hess Author: Helge Hess (helge.hess@skyrix.com) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "MySQL4Channel.h" #include "NSString+MySQL4.h" #include "EOAttribute+MySQL4.h" #include "common.h" @interface EORelationship(FixMe) - (void)addJoin:(id)_join; @end @implementation MySQL4Channel(ModelFetching) - (NSArray *)_attributesForTableName:(NSString *)_tableName { NSMutableArray *attributes; NSString *sqlExpr; NSArray *resultDescription; NSDictionary *row; if ([_tableName length] == 0) return nil; attributes = [self->_attributesForTableName objectForKey:_tableName]; if (attributes == nil) { #if 1 // TODO: we would need to parse the SQL field of 'sqlite_master'? NSLog(@"ERROR(%s): operation not supported on MySQL4!", __PRETTY_FUNCTION__); return nil; #else sqlExpr = [NSString stringWithFormat:sqlExpr, _tableName]; #endif if (![self evaluateExpression:sqlExpr]) { fprintf(stderr, "Couldn`t evaluate column-describe '%s' on table '%s'\n", [sqlExpr cString], [_tableName cString]); return nil; } resultDescription = [self describeResults]; attributes = [NSMutableArray arrayWithCapacity:16]; while ((row = [self fetchAttributes:resultDescription withZone:NULL])) { EOAttribute *attribute; NSString *columnName = nil; NSString *externalType = nil; NSString *attrName = nil; columnName = [[row objectForKey:@"attname"] stringValue]; attrName = [columnName _mySQL4ModelMakeInstanceVarName]; externalType = [[row objectForKey:@"typname"] stringValue]; attribute = [[EOAttribute alloc] init]; [attribute setColumnName:columnName]; [attribute setName:attrName]; [attribute setExternalType:externalType]; [attribute loadValueClassForExternalMySQL4Type:externalType]; [attributes addObject:attribute]; [attribute release]; } [self->_attributesForTableName setObject:attributes forKey:_tableName]; //NSLog(@"got attrs: %@", attributes); } return attributes; } - (NSArray *)_primaryKeysNamesForTableName:(NSString *)_tableName { //NSArray *pkNameForTableName = nil; if ([_tableName length] == 0) return nil; NSLog(@"ERROR(%s): operation not supported on MySQL4!", __PRETTY_FUNCTION__); return nil; } - (NSArray *)_foreignKeysForTableName:(NSString *)_tableName { return nil; } - (EOModel *)describeModelWithTableNames:(NSArray *)_tableNames { NSMutableArray *buildRelShips = [NSMutableArray arrayWithCapacity:64]; EOModel *model = AUTORELEASE([EOModel new]); int cnt, tc = [_tableNames count]; for (cnt = 0; cnt < tc; cnt++) { NSMutableDictionary *relNamesUsed; NSMutableArray *classProperties, *primaryKeyAttributes; NSString *tableName; NSArray *attributes, *pkeys, *fkeys; EOEntity *entity; int cnt2, ac, fkc; relNamesUsed = [NSMutableDictionary dictionaryWithCapacity:16]; classProperties = [NSMutableArray arrayWithCapacity:16]; primaryKeyAttributes = [NSMutableArray arrayWithCapacity:2]; tableName = [_tableNames objectAtIndex:cnt]; attributes = [self _attributesForTableName:tableName]; pkeys = [self _primaryKeysNamesForTableName:tableName]; fkeys = [self _foreignKeysForTableName:tableName]; entity = [[[EOEntity alloc] init] autorelease]; ac = [attributes count]; fkc = [fkeys count]; [entity setName:[tableName _mySQL4ModelMakeClassName]]; [entity setClassName: [@"EO" stringByAppendingString: [tableName _mySQL4ModelMakeClassName]]]; [entity setExternalName:tableName]; [classProperties addObjectsFromArray:[entity classProperties]]; [primaryKeyAttributes addObjectsFromArray:[entity primaryKeyAttributes]]; [model addEntity:entity]; for (cnt2 = 0; cnt2 < ac; cnt2++) { EOAttribute *attribute = [attributes objectAtIndex:cnt2]; NSString *columnName = [attribute columnName]; [entity addAttribute:attribute]; [classProperties addObject:attribute]; if ([pkeys containsObject:columnName]) [primaryKeyAttributes addObject:attribute]; } [entity setClassProperties:classProperties]; [entity setPrimaryKeyAttributes:primaryKeyAttributes]; for (cnt2 = 0; cnt2 < fkc; cnt2++) { NSDictionary *fkey; NSMutableArray *classProperties; NSString *sa, *da, *dt; EORelationship *rel; EOJoin *join; // TODO: fix me, EOJoin is deprecated NSString *relName; fkey = [fkeys objectAtIndex:cnt2]; classProperties = [NSMutableArray arrayWithCapacity:8]; sa = [fkey objectForKey:@"sourceAttr"]; da = [fkey objectForKey:@"targetAttr"]; dt = [fkey objectForKey:@"targetTable"]; rel = [[[EORelationship alloc] init] autorelease]; // TODO: fix me join = [[[NSClassFromString(@"EOJoin") alloc] init] autorelease]; if ([pkeys containsObject:sa]) { relName = [@"to" stringByAppendingString: [dt _mySQL4ModelMakeClassName]]; } else { relName = [@"to" stringByAppendingString: [[sa _mySQL4ModelMakeInstanceVarName] _mySQL4StringWithCapitalizedFirstChar]]; if ([relName hasSuffix:@"Id"]) { int cLength = [relName cStringLength]; relName = [relName substringToIndex:cLength - 2]; } } if ([relNamesUsed objectForKey:relName]) { int useCount = [[relNamesUsed objectForKey:relName] intValue]; [relNamesUsed setObject:[NSNumber numberWithInt:(useCount++)] forKey:relName]; relName = [NSString stringWithFormat:@"%s%d", [relName cString], useCount]; } else [relNamesUsed setObject:[NSNumber numberWithInt:0] forKey:relName]; [rel setName:relName]; //[rel setDestinationEntity:(EOEntity *)[dt _mySQL4ModelMakeClassName]]; [rel setToMany:NO]; // TODO: EOJoin is removed, fix this ... [(id)join setSourceAttribute: (EOAttribute *)[sa _mySQL4ModelMakeInstanceVarName]]; [(id)join setDestinationAttribute: (EOAttribute *)[da _mySQL4ModelMakeInstanceVarName]]; [rel addJoin:join]; [entity addRelationship:rel]; [classProperties addObjectsFromArray:[entity classProperties]]; [classProperties addObject:rel]; [entity setClassProperties:classProperties]; [buildRelShips addObject:rel]; } [entity setAttributesUsedForLocking:[entity attributes]]; } [buildRelShips makeObjectsPerformSelector: @selector(replaceStringsWithObjects)]; /* // make reverse relations { int cnt, rc = [buildRelShips count]; for (cnt = 0; cnt < rc; cnt++) { EORelationship *rel = [buildRelShips objectAtIndex:cnt]; NSMutableArray *classProperties = [NSMutableArray new]; EORelationship *reverse = [rel reversedRelationShip]; EOEntity *entity = [rel destinationEntity]; NSArray *pkeys = [entity primaryKeyAttributes]; BOOL isToMany = [reverse isToMany]; EOAttribute *sa = [[[reverse joins] lastObject] sourceAttribute]; NSString *relName = nil; if ([pkeys containsObject:sa] || isToMany) relName = [@"to" stringByAppendingString: [(EOEntity *)[reverse destinationEntity] name]]; else { relName = [@"to" stringByAppendingString: [[[sa name] _mySQL4ModelMakeInstanceVarName] _mySQL4StringWithCapitalizedFirstChar]]; if ([relName hasSuffix:@"Id"]) { int cLength = [relName cStringLength]; relName = [relName substringToIndex:cLength - 2]; } } if ([entity relationshipNamed:relName]) { int cnt = 1; NSString *numName; numName = [NSString stringWithFormat:@"%s%d", [relName cString], cnt]; while ([entity relationshipNamed:numName]) { cnt++; numName = [NSString stringWithFormat:@"%s%d", [relName cString], cnt]; } relName = numName; } [reverse setName:relName]; [entity addRelationship:reverse]; [classProperties addObjectsFromArray:[entity classProperties]]; [classProperties addObject:reverse]; [entity setClassProperties:classProperties]; } } */ [model setAdaptorName:@"MySQL4"]; [model setAdaptorClassName:@"MySQL4Adaptor"]; [model setConnectionDictionary: [[adaptorContext adaptor] connectionDictionary]]; return model; } - (NSArray *)describeTableNames { NSMutableArray *tableNames = nil; NSArray *resultDescription = nil; NSString *attributeName = nil; NSDictionary *row = nil; NSString *selectExpression = nil; selectExpression = @"SHOW TABLES"; if (![self evaluateExpression:selectExpression]) { fprintf(stderr, "Could not evaluate table-describe expression '%s'\n", [selectExpression cString]); return nil; } resultDescription = [self describeResults]; attributeName = [(EOAttribute *)[resultDescription objectAtIndex:0] name]; tableNames = [NSMutableArray arrayWithCapacity:16]; while ((row = [self fetchAttributes:resultDescription withZone:NULL])!=nil) [tableNames addObject:[row objectForKey:attributeName]]; return tableNames; } @end /* MySQL4Channel(ModelFetching) */ void __link_MySQL4ChannelModel() { // used to force linking of object file __link_MySQL4ChannelModel(); } SOPE/sope-gdl1/MySQL/MySQL4Adaptor.m0000644000000000000000000000774515004363604015622 0ustar rootroot/* MySQL4Adaptor.m Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) This file is part of the MySQL4 Adaptor Library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "MySQL4Adaptor.h" #include "MySQL4Context.h" #include "MySQL4Channel.h" #include "MySQL4Expression.h" #include "MySQL4Values.h" #include "common.h" @implementation MySQL4Adaptor - (id)initWithName:(NSString *)_name { if ((self = [super initWithName:_name])) { } return self; } /* NSCopying methods */ - (id)copyWithZone:(NSZone *)_zone { return [self retain]; } /* connections */ - (NSString *)_copyOfConDictString:(NSString *)_key { return [[[[self connectionDictionary] objectForKey:_key] copy] autorelease]; } - (NSString *)serverName { NSString *serverName; serverName = [[self connectionDictionary] objectForKey:@"hostName"]; #if 0 // do not default to something, to allow for sockets? if (serverName == nil) serverName = @"127.0.0.1"; #endif return [[serverName copy] autorelease]; } - (NSString *)loginName { return [self _copyOfConDictString:@"userName"]; } - (NSString *)loginPassword { return [self _copyOfConDictString:@"password"]; } - (NSString *)databaseName { return [[[[self connectionDictionary] objectForKey:@"databaseName"] copy] autorelease]; } - (NSString *)port { return [self _copyOfConDictString:@"port"]; } - (NSString *)options { return [[[[self connectionDictionary] objectForKey:@"options"] copy] autorelease]; } /* sequence for primary key generation */ - (NSString *)primaryKeySequenceName { NSString *seqName; seqName = [[self pkeyGeneratorDictionary] objectForKey:@"primaryKeySequenceName"]; return [[seqName copy] autorelease]; } - (NSString *)newKeyExpression { NSString *newKeyExpr; newKeyExpr = [[self pkeyGeneratorDictionary] objectForKey:@"newKeyExpression"]; return [[newKeyExpr copy] autorelease]; } /* formatting */ - (NSString *)charConvertExpressionForAttributeNamed:(NSString *)_attrName { return _attrName; } - (id)formatValue:(id)value forAttribute:(EOAttribute *)attribute { NSString *result; result = [value stringValueForMySQL4Type:[attribute externalType] attribute:attribute]; //NSLog(@"formatting value %@ result %@", value, result); //NSLog(@" value class %@ attr %@ attr type %@", // [value class], attribute, [attribute externalType]); return result; } - (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr { return YES; } /* types */ - (BOOL)isValidQualifierType:(NSString *)_typeName { return YES; } /* adaptor info */ - (Class)adaptorContextClass { return [MySQL4Context class]; } - (Class)adaptorChannelClass { return [MySQL4Channel class]; } - (Class)expressionClass { return [MySQL4Expression class]; } @end /* MySQL4Adaptor */ void __linkMySQL4Adaptor(void) { extern void __link_EOAttributeMySQL4(); extern void __link_NSStringMySQL4(); extern void __link_MySQL4ChannelModel(); extern void __link_MySQL4Values(); ; [MySQL4Channel class]; [MySQL4Context class]; [MySQL4Exception class]; [MySQL4Expression class]; __link_EOAttributeMySQL4(); __link_NSStringMySQL4(); //__link_MySQL4ChannelModel(); __link_MySQL4Values(); __linkMySQL4Adaptor(); } SOPE/sope-gdl1/MySQL/GNUmakefile.preamble0000644000000000000000000000370315004363604016726 0ustar rootroot# # GNUmakefile # # Copyright (C) 2003-2005 Helge Hess # # Author: Helge Hess (helge.hess@opengroupware.org) # # This file is part of the SQLite3 Adaptor Library # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library 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 # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with this library; see the file COPYING.LIB. # If not, write to the Free Software Foundation, # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. SOPE_ROOT=../.. ifeq ($(frameworks),yes) BUNDLE_INSTALL_DIR := $(FRAMEWORK_INSTALL_DIR)/GDLAccess.framework/Resources/GDLAdaptors/ else BUNDLE_INSTALL_DIR = $(SOPE_DBADAPTORS)/ endif MySQL_BUNDLE_LIBS += \ -lGDLAccess \ $(shell mysql_config --libs) MySQLD_BUNDLE_LIBS += \ -lGDLAccess \ -lEOControl \ $(shell mysql_config --libs) gdltest_TOOL_LIBS += \ -lGDLAccess \ -lNGExtensions # set compile flags and go ADDITIONAL_CFLAGS += $(shell mysql_config --cflags) ADDITIONAL_INCLUDE_DIRS += \ -I../GDLAccess -I.. -I$(SOPE_ROOT) ADDITIONAL_INCLUDE_DIRS += \ -I$(SOPE_ROOT)/sope-core/ \ -I$(SOPE_ROOT)/sope-core/NGExtensions \ $(shell mysql_config --include) # dependencies # library/framework search pathes DEP_DIRS = \ ../GDLAccess \ $(SOPE_ROOT)/sope-core/EOControl ifneq ($(frameworks),yes) ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),\ -L$(GNUSTEP_BUILD_DIR)/$(dir)/$(GNUSTEP_OBJ_DIR_NAME)) else ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir)) endif SYSTEM_LIB_DIR += $(CONFIGURE_SYSTEM_LIB_DIR) SOPE/sope-gdl1/Version0000644000000000000000000000037615004363604013474 0ustar rootroot# # This file is included by library makefiles to set the version information # of the executable. MAJOR_VERSION=4 MINOR_VERSION=9 # the SUBMINOR_VERSION is set by the Version file inside of a library project SOPE_MAJOR_VERSION=4 SOPE_MINOR_VERSION=9 SOPE/sope-gdl1/common.make0000644000000000000000000000120015004363604014236 0ustar rootroot# GNUstep makefile SKYROOT=.. include $(GNUSTEP_MAKEFILES)/common.make include $(SKYROOT)/Version -include ./Version GNUSTEP_INSTALLATION_DIR = $(GNUSTEP_LOCAL_ROOT) ADDITIONAL_CPPFLAGS += -pipe -Wall -Wno-protocol SOPEDIR="../.." ADDITIONAL_INCLUDE_DIRS += \ -I.. \ -I$(SOPEDIR)/sope-xml \ -I$(SOPEDIR)/sope-core \ -I$(SOPEDIR)/sope-core/NGExtensions ADDITIONAL_LIB_DIRS += \ -L./$(GNUSTEP_OBJ_DIR) \ -L$(SOPEDIR)/sope-xml/SaxObjC/$(GNUSTEP_OBJ_DIR) \ -L$(SOPEDIR)/sope-xml/DOM/$(GNUSTEP_OBJ_DIR) \ -L$(SOPEDIR)/sope-core/EOControl/$(GNUSTEP_OBJ_DIR) \ -L$(SOPEDIR)/sope-core/NGExtensions/$(GNUSTEP_OBJ_DIR) SOPE/sope-gdl1/GDLAccess/0000755000000000000000000000000015004363604013646 5ustar rootrootSOPE/sope-gdl1/GDLAccess/NSObject+EONullInit.h0000644000000000000000000000066315004363604017451 0ustar rootroot// $Id: NSObject+EONullInit.h 1 2004-08-20 10:38:46Z znek $ #ifndef __GDLAccess_NSObject_EONull_H__ #define __GDLAccess_NSObject_EONull_H__ #import #import @class EOEntity; @interface NSObject(EONullInit) - (void)setAllAttributesToEONull:(EOEntity *)_entity; - (void)setAllAttributesToEONull; // assume the object respondsTo: entity @end #endif /* __GDLAccess_NSObject_EONull_H__ */ SOPE/sope-gdl1/GDLAccess/FoundationExt/0000755000000000000000000000000015004363604016435 5ustar rootrootSOPE/sope-gdl1/GDLAccess/FoundationExt/GNUmakefile0000644000000000000000000000057715004363604020520 0ustar rootroot# GNUstep makefile include ../../../config.make include $(GNUSTEP_MAKEFILES)/common.make include ../../Version include ../Version SUBPROJECT_NAME = FoundationExt FoundationExt_OBJC_FILES = \ DefaultScannerHandler.m \ PrintfFormatScanner.m \ FormatScanner.m \ ADDITIONAL_INCLUDE_DIRS += -I. -I.. -I../../../sope-core/NGExtensions include $(GNUSTEP_MAKEFILES)/subproject.make SOPE/sope-gdl1/GDLAccess/FoundationExt/COPYING0000644000000000000000000000171615004363604017475 0ustar rootroot Copyright (C) 1995, 1996, 1997, 1998 Ovidiu Predescu and Mircea Oancea. All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation for ANY purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. This software may be included in any commercial product provided that its distribution contain the libFoundation copyright notice and this permission notice. We disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness, in no event shall we be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. SOPE/sope-gdl1/GDLAccess/FoundationExt/PrintfFormatScanner.m0000644000000000000000000000444215004363604022544 0ustar rootroot/* PrintfFormatScanner.m Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea. All rights reserved. Author: Ovidiu Predescu This file is part of libFoundation. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. We disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness, in no event shall we be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. */ #import #include "PrintfFormatScanner.h" #include "DefaultScannerHandler.h" @implementation PrintfFormatScanner - (NSString *)stringWithFormat:(NSString *)format arguments:(va_list)args { va_list va; #ifdef __va_copy // args being NULL breaks heavily on amd64. It shouldn't be // possible to be NULL at all, but we're called with an array as // argument instead of a va_list in EOSQLQualifier and are thus // calling __va_copy on an array, which is something that really // shouldn't be done. Checking whether args is NULL breaks on arm, // alpha and sh4 however, because a va_list isn't a pointer, so we // don't do the check on arm, alpha and sh4. #if !defined(__arm__) && !defined(__aarch64__) && !defined(__alpha__) && !defined(__sh__) if (!args) return format; #endif __va_copy(va, args); #else va = args; #endif self->result = [NSMutableString stringWithCapacity:[format cStringLength]]; [self parseFormatString:format context:&va]; return [[self->result copy] autorelease]; } - (BOOL)handleOrdinaryString:(NSString *)string { [self->result appendString:string]; return YES; } - (BOOL)handleFormatSpecifierWithContext:(void *)context { [self->result appendString:[handler stringForArgument:context scanner:self]]; return YES; } @end /* PrintfFormatScanner */ SOPE/sope-gdl1/GDLAccess/FoundationExt/FormatScanner.h0000644000000000000000000001022215004363604021345 0ustar rootroot/* FormatScanner.h Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea. All rights reserved. Author: Ovidiu Predescu This file is part of libFoundation. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. We disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness, in no event shall we be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. */ #ifndef __FormatScanner_h__ #define __FormatScanner_h__ #include #include @class NSString; /* * A FormatScanner scans a NSString format. When it reaches a specifier * similar to printf(3S), it calls a handler object previously registered to * it. The handler object is usually inherited from the DefaultScannerHandler * class. The handler object maintains a mapping between format characters and * selectors that have to be called when a specifier is found in the format * string. The selector must have exactly two arguments: the first one is a * pointer to a va_list and the second one is the format scanner. It is the * responsability of handler to increase the pointer to the va_list with the * size of the object it handles. During the execution of the method the * scanner calls, the handler can ask the scanner about the flags, width, * precision, modifiers and the specifier character. The method should return a * NSString object that represents the converted object. * * FormatScanner is an abstract class. Use the PrintfFormatScanner class that * is used to write printf-like functions. Additional classes can be inherited * to write scanf-like functions. */ typedef enum { FS_ALTERNATE_FORM = 1, FS_ZERO = 2, FS_MINUS_SIGN = 4, FS_PLUS_SIGN = 8, FS_BLANK = 16 } FormatScannerFlags; @interface FormatScanner : NSObject { int specifierLen, specifierSize; char *currentSpecifier; id handler; unsigned flags; int width; int precision; char modifier; char characterSpecifier; BOOL allowFlags:1; BOOL allowWidth:1; BOOL allowPeriod:1; BOOL allowPrecision:1; BOOL allowModifier:1; } /* This method start the searching of specifiers in `format'. `context' is passed in handleFormatSpecifierWithContext: unmodified. */ - (BOOL)parseFormatString:(NSString*)format context:(void*)context; /* This method is called whenever a string between two specifiers is found. Rewrite it in subclasses to perform whatever action you want (for example to collect them in a result string if you're doing printf). The method should return NO if the scanning of format should stop. */ - (BOOL)handleOrdinaryString:(NSString*)string; /* This method is called whenever a format specifier is found in `format'. Again, rewrite this method in subclasses to perform whatever action you want. The method should return NO if the scanning of the format should stop. */ - (BOOL)handleFormatSpecifierWithContext:(void*)context; - (void)setFormatScannerHandler:(id)anObject; - (id)formatScannerHandler; - (unsigned int)flags; - (int)width; - (int)precision; - (char)modifier; - (char)characterSpecifier; - (const char*)currentSpecifier; - (id)setAllowFlags:(BOOL)flag; - (id)setAllowWidth:(BOOL)flag; - (id)setAllowPeriod:(BOOL)flag; - (id)setAllowPrecision:(BOOL)flag; - (id)setAllowModifier:(BOOL)flag; /* A shorthand for sending all -setAllow* messages with !flag as argument */ - (id)setAllowOnlySpecifier:(BOOL)flag; - (BOOL)allowFlags; - (BOOL)allowWidth; - (BOOL)allowPeriod; - (BOOL)allowPrecision; - (BOOL)allowModifier; @end #endif /* __FormatScanner_h__ */ /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/FoundationExt/FormatScanner.m0000644000000000000000000002167715004363604021372 0ustar rootroot/* FormatScanner.m Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea. All rights reserved. Author: Ovidiu Predescu This file is part of libFoundation. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. We disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness, in no event shall we be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. */ #include #include "common.h" #import #import #import #import //#include #include "FormatScanner.h" @implementation FormatScanner enum { SPECIFIER_SIZE = 1000 }; /* This value should be sufficient */ - (id)init { specifierSize = SPECIFIER_SIZE; currentSpecifier = MallocAtomic(specifierSize); allowFlags = YES; allowWidth = YES; allowPeriod = YES; allowPrecision = YES; allowModifier = YES; return self; } - (void)dealloc { if (self->currentSpecifier) free(currentSpecifier); RELEASE(self->handler); [super dealloc]; } - (void)setFormatScannerHandler:(id)anObject { ASSIGN(self->handler, anObject); } - (id)setAllowOnlySpecifier:(BOOL)flag { allowFlags = !flag; allowWidth = !flag; allowPeriod = !flag; allowPrecision = !flag; allowModifier = !flag; return self; } - (id)setAllowFlags:(BOOL)flag { allowFlags = flag; return self; } - (BOOL)allowFlags { return allowFlags; } - (id)setAllowWidth:(BOOL)flag { allowWidth = flag; return self; } - (BOOL)allowWidth { return allowWidth; } - (id)setAllowPeriod:(BOOL)flag { allowPeriod = flag; return self; } - (BOOL)allowPeriod { return allowPeriod; } - (id)setAllowPrecision:(BOOL)flag { allowPrecision = flag; return self; } - (BOOL)allowPrecision { return allowPrecision; } - (id)setAllowModifier:(BOOL)flag { allowModifier = flag; return self; } - (BOOL)allowModifier { return allowModifier; } - (id)formatScannerHandler { return handler; } - (unsigned int)flags { return self->flags; } - (int)width { return self->width; } - (int)precision { return self->precision; } - (char)modifier { return self->modifier; } - (char)characterSpecifier { return self->characterSpecifier; } - (const char *)currentSpecifier { return self->currentSpecifier; } #define CHECK_END \ if(i >= length) { \ /* An unterminated specifier. Break the loop. */ \ [self handleOrdinaryString: \ [NSString stringWithCString:currentSpecifier]]; \ goto _return; \ } /* Scans the format string looking after specifiers. Doesn't handle '*' as a valid width or precision. */ - (BOOL)parseFormatString:(NSString*)format context:(void *)context { NSRange searchRange, foundRange; int i, length; unichar ch; NSCharacterSet *decimals; i = 0; length = [format length]; decimals = [NSCharacterSet decimalDigitCharacterSet]; *currentSpecifier = 0; specifierLen = 0; while (i < length) { searchRange.location = i; searchRange.length = length - i; foundRange = [format rangeOfString:@"%" options:0 range:searchRange]; if (foundRange.length == 0) foundRange.location = length; searchRange.length = foundRange.location - searchRange.location; if (searchRange.length) { if (![self handleOrdinaryString: [format substringWithRange:searchRange]]) return NO; } i = foundRange.location; CHECK_END i++; strcpy(currentSpecifier, "%"); specifierLen = 1; CHECK_END flags = width = precision = modifier = characterSpecifier = 0; /* Check for flags. */ if (self->allowFlags) { for (; i < length; i++) { ch = [format characterAtIndex:i]; switch(ch) { case '#': strcat(currentSpecifier, "#"); flags |= FS_ALTERNATE_FORM; break; case '0': strcat(currentSpecifier, "0"); flags |= FS_ZERO; break; case '-': strcat(currentSpecifier, "-"); flags |= FS_MINUS_SIGN; break; case '+': strcat(currentSpecifier, "+"); flags |= FS_PLUS_SIGN; break; case ' ': strcat(currentSpecifier, " "); flags |= FS_BLANK; break; default: goto quit; } if (++specifierLen == specifierSize) { currentSpecifier = Realloc(currentSpecifier, specifierSize += SPECIFIER_SIZE); } } quit: CHECK_END } /* Check for width. */ if (self->allowWidth) { for(; i < length; i++) { char str[2] = { 0, 0 }; ch = [format characterAtIndex:i]; if (![decimals characterIsMember:ch]) break; str[0] = ch; strcat(currentSpecifier, str); if(++specifierLen == specifierSize) { currentSpecifier = Realloc(currentSpecifier, specifierSize += SPECIFIER_SIZE); } width = 10 * width + (ch - '0'); } CHECK_END } /* Check for period. */ if (self->allowPeriod) { ch = [format characterAtIndex:i]; if(ch == '.') { char str[2] = { ch, 0 }; strcat(currentSpecifier, str); if(++specifierLen == specifierSize) { currentSpecifier = Realloc(currentSpecifier, specifierSize += SPECIFIER_SIZE); } i++; CHECK_END } } /* Check for precision. */ if (self->allowPrecision) { for(; i < length; i++) { char str[2] = { 0, 0 }; ch = [format characterAtIndex:i]; if (![decimals characterIsMember:ch]) break; str[0] = ch; strcat(currentSpecifier, str); if(++specifierLen == specifierSize) { currentSpecifier = Realloc(currentSpecifier, specifierSize += SPECIFIER_SIZE); } precision = 10 * precision + (ch - '0'); } CHECK_END } /* Check for data-width modifier. */ if (allowModifier) { ch = [format characterAtIndex:i]; if (ch == 'h' || ch == 'l') { char str[2] = { ch, 0 }; strcat(currentSpecifier, str); if (++specifierLen == specifierSize) { currentSpecifier = Realloc(currentSpecifier, specifierSize += SPECIFIER_SIZE); } modifier = ch; i++; CHECK_END } } /* Finally, the conversion character. */ { char str[2] = { 0, 0 }; ch = [format characterAtIndex:i]; str[0] = ch; strcat(currentSpecifier, str); if(++specifierLen == specifierSize) { currentSpecifier = Realloc(currentSpecifier, specifierSize += SPECIFIER_SIZE); } characterSpecifier = ch; } if (![self handleFormatSpecifierWithContext:context]) return NO; i++; *currentSpecifier = 0; specifierLen = 0; CHECK_END } _return: return YES; } - (BOOL)handleOrdinaryString:(NSString*)string { return YES; } - (BOOL)handleFormatSpecifierWithContext:(void*)context { return YES; } @end /* FormatScanner */ /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/FoundationExt/COPYRIGHT0000644000000000000000000000027415004363604017733 0ustar rootroot Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea. All rights reserved. Author: Ovidiu Predescu Helge Hess SOPE/sope-gdl1/GDLAccess/FoundationExt/DefaultScannerHandler.m0000644000000000000000000000460215004363604023011 0ustar rootroot/* DefaultScannerHandler.m Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea. All rights reserved. Author: Ovidiu Predescu Helge Hess This file is part of libFoundation. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. We disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness, in no event shall we be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. */ #import #include "FormatScanner.h" #include "DefaultScannerHandler.h" @implementation DefaultScannerHandler - (id)init { int i; IMP unknownSpecifierIMP = [self methodForSelector:@selector(unknownSpecifier:scanner:)]; for(i = 0; i < 256; i++) specHandler[i] = unknownSpecifierIMP; return self; } - (NSString *)unknownSpecifier:(void *)arg scanner:scanner { char str[] = { [scanner characterSpecifier], 0 }; return [NSString stringWithCString:str]; } - (NSString *)stringForArgument:(void *)arg scanner:scanner { return (*specHandler[(int)[scanner characterSpecifier]]) (self, _cmd, arg, scanner); } @end /* DefaultScannerHandler */ @implementation DefaultEnumScannerHandler - (id)init { int i; IMP unknownSpecifierIMP; unknownSpecifierIMP = [self methodForSelector:@selector(unknownSpecifier:scanner:)]; for(i = 0; i < 256; i++) self->specHandler[i] = unknownSpecifierIMP; return self; } - (NSString *)unknownSpecifier:(void *)arg scanner:scanner { char str[] = { [scanner characterSpecifier], 0 }; return [NSString stringWithCString:str]; } - (NSString *)stringForArgument:(void *)arg scanner:scanner { return (*specHandler[(int)[scanner characterSpecifier]]) (self, _cmd, arg, scanner); } @end /* DefaultEnumScannerHandler */ /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/FoundationExt/DefaultScannerHandler.h0000644000000000000000000000323015004363604023000 0ustar rootroot/* DefaultScannerHandler.h Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea. All rights reserved. Author: Ovidiu Predescu This file is part of libFoundation. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. We disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness, in no event shall we be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. */ #ifndef __DefaultScannerHandler_h__ #define __DefaultScannerHandler_h__ #include @class NSString; @class FormatScanner; @interface DefaultScannerHandler : NSObject { IMP specHandler[256]; } - (NSString *)stringForArgument:(void *)arg scanner:(id)aFormatScanner; - (NSString *)unknownSpecifier:(void *)arg scanner:(id)scanner; @end @class NSEnumerator; @interface DefaultEnumScannerHandler : NSObject { IMP specHandler[256]; } - (NSString *)stringForArgument:(void *)arg scanner:(id)aFormatScanner; - (NSString *)unknownSpecifier:(void *)arg scanner:(id)scanner; @end #endif /* __DefaultScannerHandler_h__ */ /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/FoundationExt/LICENSE0000644000000000000000000000136215004363604017444 0ustar rootroot Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. We disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness, in no event shall we be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. SOPE/sope-gdl1/GDLAccess/FoundationExt/PrintfFormatScanner.h0000644000000000000000000000264115004363604022536 0ustar rootroot/* PrintfFormatScanner.h Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea. All rights reserved. Author: Ovidiu Predescu This file is part of libFoundation. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. We disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness, in no event shall we be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. */ #ifndef __PrintfFormatScanner_h__ #define __PrintfFormatScanner_h__ #if XCODE_SELF_COMPILE # include "FormatScanner.h" #else # include #endif @class NSMutableString; @interface PrintfFormatScanner : FormatScanner { NSMutableString *result; } - (NSString *)stringWithFormat:(NSString *)format arguments:(va_list)args; @end #endif /* __PrintfFormatScanner_h__ */ /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/EOAdaptorOperation.m0000644000000000000000000000220115004363604017516 0ustar rootroot/* EOAttributeOrdering.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOAdaptorOperation.m 1 2004-08-20 10:38:46Z znek $ #include #include "common.h" @implementation EOAdaptorOperation @end /* EOAdaptorOperation */ SOPE/sope-gdl1/GDLAccess/EODatabaseChannel.m0000644000000000000000000013051415004363604017251 0ustar rootroot/* EODatabaseChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "EODatabaseChannel.h" #import "EOAdaptor.h" #import "EOAdaptorChannel.h" #import "EOAdaptorContext.h" #import "EOAttribute.h" #import "EODatabase.h" #import "EODatabaseContext.h" #import "EOEntity.h" #import "EODatabaseFault.h" #import "EOGenericRecord.h" #import "EOModel.h" #import "EOObjectUniquer.h" #import "EOSQLQualifier.h" #import "EORelationship.h" #import #import #import @class EOGenericRecord; NSString *EODatabaseChannelWillOpenNotificationName = @"EODatabaseChannelWillOpenNotification"; NSString *EODatabaseChannelDidOpenNotificationName = @"EODatabaseChannelDidOpenNotification"; NSString *EODatabaseChannelWillCloseNotificationName = @"EODatabaseChannelWillCloseNotification"; NSString *EODatabaseChannelDidCloseNotificationName = @"EODatabaseChannelDidCloseNotification"; NSString *EODatabaseChannelCouldNotOpenNotificationName = @"EODatabaseChannelCouldNotOpenNotification"; NSString *EODatabaseChannelWillInsertObjectName = @"EODatabaseChannelWillInsertObjectName"; NSString *EODatabaseChannelDidInsertObjectName = @"EODatabaseChannelDidInsertObjectName"; NSString *EODatabaseChannelWillUpdateObjectName = @"EODatabaseChannelWillUpdateObjectName"; NSString *EODatabaseChannelDidUpdateObjectName = @"EODatabaseChannelDidUpdateObjectName"; NSString *EODatabaseChannelWillDeleteObjectName = @"EODatabaseChannelWillDeleteObjectName"; NSString *EODatabaseChannelDidDeleteObjectName = @"EODatabaseChannelDidDeleteObjectName"; NSString *EODatabaseChannelWillLockObjectName = @"EODatabaseChannelWillLockObjectName"; NSString *EODatabaseChannelDidLockObjectName = @"EODatabaseChannelDidLockObjectName"; /* * Private methods declaration */ @interface EODatabaseChannel(Private) - (id)privateFetchWithZone:(NSZone *)_zone; - (Class)privateClassForEntity:(EOEntity *)anEntity; - (void)privateUpdateCurrentEntityInfo; - (void)privateClearCurrentEntityInfo; - (void)privateReportError:(SEL)method :(NSString *)format, ...; @end /* * EODatabaseChannel implementation */ @implementation EODatabaseChannel /* * Initializing a new instance */ - (id)initWithDatabaseContext:(EODatabaseContext *)_dbContext { if (_dbContext == nil) { AUTORELEASE(self); return nil; } self->notificationCenter = RETAIN([NSNotificationCenter defaultCenter]); self->databaseContext = RETAIN(_dbContext); [self setDelegate:[self->databaseContext delegate]]; [self->databaseContext channelDidInit:self]; return self; } - (void)dealloc { [self->databaseContext channelWillDealloc:self]; RELEASE(self->currentEditingContext); RELEASE(self->databaseContext); RELEASE(self->adaptorChannel); RELEASE(self->notificationCenter); [super dealloc]; } // notifications - (void)postNotification:(NSString *)_name { [self->notificationCenter postNotificationName:_name object:self]; } - (void)postNotification:(NSString *)_name object:(id)_obj { [self->notificationCenter postNotificationName:_name object:self userInfo:[NSDictionary dictionaryWithObject:_obj forKey:@"object"]]; } // accessors - (EOAdaptorChannel *)adaptorChannel { if (self->adaptorChannel == nil) { static int reuseAdaptorCh = -1; if (reuseAdaptorCh == -1) { reuseAdaptorCh = [[[NSUserDefaults standardUserDefaults] objectForKey:@"EOReuseAdaptorChannel"] boolValue] ? 1 : 0; } if (reuseAdaptorCh) { NSEnumerator *channels; EOAdaptorChannel *channel; channels = [[[[self databaseContext] adaptorContext] channels] objectEnumerator]; while ((channel = [channels nextObject])) { if ([channel isFetchInProgress]) continue; #if DEBUG NSLog(@"reuse adaptor channel: %@", channel); #endif self->adaptorChannel = channel; break; } } if (self->adaptorChannel == nil) { self->adaptorChannel = [[[self databaseContext] adaptorContext] createAdaptorChannel]; } RETAIN(self->adaptorChannel); } return self->adaptorChannel; } - (EODatabaseContext *)databaseContext { return self->databaseContext; } // delegate - (void)setDelegate:(id)_delegate { self->delegate = _delegate; } - (id)delegate { return self->delegate; } // Opening and closing a channel - (BOOL)isOpen { return [[self adaptorChannel] isOpen]; } - (BOOL)openChannel { BOOL result; [self postNotification:EODatabaseChannelWillOpenNotificationName]; if ((result = [[self adaptorChannel] openChannel])) { self->successfulOpenCount++; [self postNotification:EODatabaseChannelDidOpenNotificationName]; } else { self->failedOpenCount++; [self postNotification:EODatabaseChannelCouldNotOpenNotificationName]; } return result; } - (void)closeChannel { [self postNotification:EODatabaseChannelWillCloseNotificationName]; [[self adaptorChannel] closeChannel]; self->closeCount++; [self postNotification:EODatabaseChannelDidCloseNotificationName]; } // Modifying objects - (BOOL)_isNoRaiseOnModificationException:(NSException *)_exception { /* for compatibility with non-X methods, translate some errors to a bool */ NSString *n; n = [_exception name]; if ([n isEqualToString:@"EOEvaluationError"]) return YES; if ([n isEqualToString:@"EODelegateRejects"]) return YES; return NO; } - (BOOL)insertObject:(id)anObj { // TODO: split up this method // TODO: write an insertObjectX: which returns an exception NSException *exception = nil; EOEntity *entity = nil; NSDictionary *pkey = nil; NSDictionary *values = nil; NSDictionary *snapshot = nil; NSArray *attributes = nil; int i; [self postNotification:EODatabaseChannelWillInsertObjectName object:anObj]; if (![anObj prepareForInsertInChannel:self context:self->databaseContext]) return NO; // Check the delegate if ([self->delegate respondsToSelector: @selector(databaseChannel:willInsertObject:)]) anObj = [delegate databaseChannel:self willInsertObject:anObj]; // Check nil (delegate disallowes or given object was nil) if (anObj == nil) return NO; // Check if fault if ([EOFault isFault:anObj]) { [NSException raise:NSInvalidArgumentException format:@"Attempt to insert a fault in a database channel"]; } // Check if we can insert if ([databaseContext updateStrategy] == EONoUpdate) { [self privateReportError:_cmd : @"cannot insert if context has 'NoUpdate' update strategy."]; return NO; } /* validate object for insert */ if ((exception = [anObj validateForInsert])) { /* validation failed */ [exception raise]; } // Check if in a transaction if (![databaseContext transactionNestingLevel]) { [self privateReportError:_cmd : @"cannot insert if contex has no transaction opened."]; return NO; } // Get entity entity = [anObj respondsToSelector:@selector(entity)] ? [anObj entity] : [[[[adaptorChannel adaptorContext] adaptor] model] entityForObject:anObj]; // Check entity if (entity == nil) { [self privateReportError:_cmd : @"cannot determine entity for object %p class %@.", anObj, NSStringFromClass([anObj class])]; return NO; } if ([entity isReadOnly]) { [self privateReportError:_cmd : @"cannot insert object %p for readonly entity %@.", anObj, [entity name]]; return NO; } // Get array of attributes to insert attributes = [entity attributesUsedForInsert]; // Get simple values and convert them to adaptor values values = [anObj valuesForKeys:[entity attributesNamesUsedForInsert]]; values = [entity convertValuesToModel:values]; // Get and check *must insert* attributes (primary key, lock, readonly) for (i = [attributes count]-1; i >= 0; i--) { EOAttribute *attribute = [attributes objectAtIndex:i]; NSAssert(attribute, @"invalid attribute object .."); if (![values objectForKey:[attribute name]]) { [self privateReportError:_cmd : @"null value for insert attribute %@ for object %@ entity %@", [attribute name], anObj, [entity name]]; return NO; } } // Make primary key and snapshot snapshot = [entity snapshotForRow:values]; if (snapshot == nil) { [self privateReportError:_cmd : @"cannot determine snapshot for %p from values %@ entity %@.", anObj, [values description], [entity name]]; return NO; } pkey = [entity primaryKeyForRow:values]; if (pkey == nil) { [self privateReportError:_cmd : @"cannot determine primary key for %p from values %@ entity %@.", anObj, [values description], [entity name]]; return NO; } // Insert adaptor row exception = [adaptorChannel insertRowX:values forEntity:entity]; if (exception) { if (![self _isNoRaiseOnModificationException:exception]) [exception raise]; return NO; } // Record object in database context [databaseContext recordObject:anObj primaryKey:pkey entity:entity snapshot:values]; self->insertCount++; [anObj wasInsertedInChannel:self context:self->databaseContext]; // Notify delegate if ([delegate respondsToSelector:@selector(databaseChannel:didInsertObject:)]) [delegate databaseChannel:self didInsertObject:anObj]; [self postNotification:EODatabaseChannelDidInsertObjectName object:anObj]; return YES; } - (BOOL)updateObject:(id)anObj { // TODO: split up this huge method // TODO: make an updateObjectX: method which returns an exception NSException *exception = nil; EOEntity *entity = nil; EOSQLQualifier *qualifier = nil; NSDictionary *old_pkey = nil; NSDictionary *old_snapshot = nil; NSDictionary *new_pkey = nil; NSDictionary *new_snapshot = nil; NSDictionary *values = nil; BOOL needsOptimisticLock; [self postNotification:EODatabaseChannelWillUpdateObjectName object:anObj]; if (![anObj prepareForUpdateInChannel:self context:self->databaseContext]) return NO; // Check the delegate if ([delegate respondsToSelector:@selector(databaseChannel:willUpdateObject:)]) anObj = [delegate databaseChannel:self willUpdateObject:anObj]; // Check nil (delegate disallowes or given object was nil) if (anObj == nil) return NO; // Check if fault if ([EOFault isFault:anObj]) { [NSException raise:NSInvalidArgumentException format:@"Attempt to update a fault in a database channel"]; } // Check if we can update if ([databaseContext updateStrategy] == EONoUpdate) { [self privateReportError:_cmd : @"cannot update if context has 'NoUpdate' update strategy."]; return NO; } /* validate object for update */ if ((exception = [anObj validateForUpdate])) { /* validation failed */ [exception raise]; } // Check if in a transaction if (![databaseContext transactionNestingLevel]) { [self privateReportError:_cmd : @"cannot update if contex has no transaction opened."]; return NO; } // Get entity entity = [anObj respondsToSelector:@selector(entity)] ? [anObj entity] : [[[[adaptorChannel adaptorContext] adaptor] model] entityForObject:anObj]; // Check entity { if (entity == nil) { [self privateReportError:_cmd : @"cannot determine entity for object %p class %@.", anObj, NSStringFromClass([anObj class])]; return NO; } if ([entity isReadOnly]) { [self privateReportError:_cmd : @"cannot update object %p for readonly entity %@.", anObj, [entity name]]; return NO; } } // Get and check old snapshot and primary key { [databaseContext primaryKey:&old_pkey andSnapshot:&old_snapshot forObject:anObj]; if (old_snapshot == nil) { [self privateReportError:_cmd : @"cannot update object %p because there is no snapshot for it."]; return NO; } if (old_pkey == nil) old_pkey = [entity primaryKeyForRow:old_snapshot]; if (old_pkey == nil) { [self privateReportError:_cmd : @"cannot determine primary key for %p from snapshot %@ entity %@.", anObj, [old_snapshot description], [entity name]]; return NO; } } // Get simple values and convert them to adaptor values values = [anObj valuesForKeys:[entity attributesNamesUsedForInsert]]; values = [entity convertValuesToModel:values]; // Get and check new primary key and snapshot { new_snapshot = [entity snapshotForRow:values]; if (new_snapshot == nil) { [self privateReportError:_cmd : @"cannot determine snapshot for %p from values %@ entity %@.", anObj, [values description], [entity name]]; return NO; } new_pkey = [entity primaryKeyForRow:new_snapshot]; if (new_pkey == nil) { [self privateReportError:_cmd : @"cannot determine primary key for %p from values %@ entity %@.", anObj, [values description], [entity name]]; return NO; } } // Check if we need to lock optimistic before update // that is compare locking attributes with the existing ones in database switch([databaseContext updateStrategy]) { case EOUpdateWithOptimisticLocking: case EOUpdateWithPessimisticLocking: needsOptimisticLock = ![databaseContext isObjectLocked:anObj]; break; case EOUpdateWithNoLocking: needsOptimisticLock = NO; break; default: return NO; } // If we need an "optimistic lock" then perform lock // else just make the qualifier based on the primary key only if (needsOptimisticLock) { int i; BOOL canUseQualifier = YES; NSArray *lockAttrs = [entity attributesUsedForLocking]; EOAdaptor *adaptor = [[adaptorChannel adaptorContext] adaptor]; NSDictionary *row; // Check if attributes used for locking can be used in a qualifier for (i = [lockAttrs count]-1; i >= 0; i--) { if (![adaptor isValidQualifierType: [[lockAttrs objectAtIndex:i] externalType]]) { canUseQualifier = NO; break; } } if (canUseQualifier) // If YES just build the qualifier qualifier = [EOSQLQualifier qualifierForRow:old_snapshot entity:entity]; else { // If NO then lock the row in the database server, fetch the // new snapshot and compare it with the old one qualifier = [EOSQLQualifier qualifierForPrimaryKey:old_pkey entity:entity]; #ifdef DEBUG NSAssert2([lockAttrs count] > 0, @"missing locking attributes: lock=%@ object=%@", lockAttrs, anObj); #endif if (![adaptorChannel selectAttributes:lockAttrs describedByQualifier:qualifier fetchOrder:nil lock:YES]) { [self privateReportError:_cmd : @"could not lock=%@ with qualifier=%@ entity=%@.", anObj, [qualifier description], [entity name]]; return NO; } row = [adaptorChannel fetchAttributes:lockAttrs withZone:NULL]; [adaptorChannel cancelFetch]; if (row == nil) { [self privateReportError:_cmd : @"could not get row to lock %p with qualifier %@.", anObj, [qualifier description]]; return NO; } [databaseContext recordLockedObject:anObj]; if (![row isEqual:old_snapshot]) { [self privateReportError:_cmd : @"could not lock %p. Snapshots: self %@ database %@.", anObj, [old_snapshot description], [row description]]; return NO; } } } else { qualifier = [EOSQLQualifier qualifierForPrimaryKey:old_pkey entity:entity]; } // Compute values as delta from values and old_snapshot { NSMutableDictionary *delta; NSString *attributeName; NSArray *allKeys; int i, count; allKeys = [values allKeys]; delta = [NSMutableDictionary dictionary]; for (i = 0, count = [allKeys count]; i < count; i++) { id new_v, old_v; attributeName = [allKeys objectAtIndex:i]; new_v = [values objectForKey:attributeName]; old_v = [old_snapshot objectForKey:attributeName]; if ((old_v == nil) || ![new_v isEqual:old_v]) [delta setObject:new_v forKey:attributeName]; } values = delta; } // no reason for update --> fetch to be sure, that no one has deleted it // HH: The object was not changed, so we refetch to determine whether it // was deleted if ([values count] == 0) { if (![self refetchObject:anObj]) return NO; } // Update in adaptor else { NSException *ex; ex = [adaptorChannel updateRowX:values describedByQualifier:qualifier]; if (ex != nil) { if (![self _isNoRaiseOnModificationException:ex]) [ex raise]; return NO; } } // Record object in database context if (![new_pkey isEqual:old_pkey]) { NSLog(@"WARNING: (%s) primary key changed from %@ to %@", __PRETTY_FUNCTION__, old_pkey, new_pkey); [databaseContext forgetObject:anObj]; } [databaseContext recordObject:anObj primaryKey:new_pkey entity:entity snapshot:new_snapshot]; [databaseContext recordUpdatedObject:anObj]; self->updateCount++; [anObj wasUpdatedInChannel:self context:self->databaseContext]; // Notify delegate if ([delegate respondsToSelector:@selector(databaseChannel:didUpdateObject:)]) [delegate databaseChannel:self didUpdateObject:anObj]; [self postNotification:EODatabaseChannelDidUpdateObjectName object:anObj]; return YES; } - (BOOL)deleteObject:(id)anObj { // TODO: split this method // TODO: add an deleteObjectX: method which returns an NSException NSException *exception = nil; EOEntity *entity = nil; NSDictionary *pkey = nil; NSDictionary *snapshot = nil; EOSQLQualifier *qualifier = nil; [self postNotification:EODatabaseChannelWillDeleteObjectName object:anObj]; if (![anObj prepareForDeleteInChannel:self context:self->databaseContext]) return NO; // Check the delegate if ([delegate respondsToSelector:@selector(databaseChannel:willDeleteObject:)]) anObj = [delegate databaseChannel:self willDeleteObject:anObj]; // Check nil (delegate disallowes or given object was nil) if (anObj == nil) return NO; // Check if fault if ([EOFault isFault:anObj]) { [NSException raise:NSInvalidArgumentException format:@"Attempt to delete a fault in a database channel"]; } // Check if we can delete if ([databaseContext updateStrategy] == EONoUpdate) { [self privateReportError:_cmd : @"cannot delete if context has 'NoUpdate' update strategy."]; return NO; } /* validate object for delete */ if ((exception = [anObj validateForDelete])) { /* validation failed */ [exception raise]; } // Check if in a transaction if (![databaseContext transactionNestingLevel]) { [self privateReportError:_cmd : @"cannot update if contex has no transaction opened."]; return NO; } // Get entity entity = [anObj respondsToSelector:@selector(entity)] ? [anObj entity] : [[[[adaptorChannel adaptorContext] adaptor] model] entityForObject:anObj]; // Check entity if (entity == nil) { [self privateReportError:_cmd : @"cannot determine entity for object %p class %s.", anObj, NSStringFromClass([anObj class])]; return NO; } if ([entity isReadOnly]) { [self privateReportError:_cmd : @"cannot delete object %p for readonly entity %@.", anObj, [entity name]]; return NO; } // Get snapshot and old primary key [databaseContext primaryKey:&pkey andSnapshot:&snapshot forObject:anObj]; if (pkey == nil) { if (snapshot == nil) [self privateReportError:_cmd : @"cannot delete object %p because there is no snapshot for it."]; pkey = [entity primaryKeyForRow:snapshot]; } if (pkey == nil) { [self privateReportError:_cmd : @"cannot determine primary key for %p from values %@ entity %@.", anObj, [snapshot description], [entity name]]; return NO; } // Get and check qualifier for object to delete qualifier = [EOSQLQualifier qualifierForPrimaryKey:pkey entity:entity]; if (qualifier == nil) { [self privateReportError:_cmd : @"cannot make qualifier to delete %p primary key %@ entity %@.", anObj, [pkey description], [entity name]]; return NO; } // Delete adaptor row exception = [adaptorChannel deleteRowsDescribedByQualifierX:qualifier]; if (exception != nil) { if (![self _isNoRaiseOnModificationException:exception]) [exception raise]; return NO; } AUTORELEASE(RETAIN(anObj)); // Forget object in database context [databaseContext forgetObject:anObj]; self->deleteCount++; [anObj wasDeletedInChannel:self context:self->databaseContext]; // Notify delegate if ([delegate respondsToSelector: @selector(databaseChannel:didDeleteObject:)]) [delegate databaseChannel:self didDeleteObject:anObj]; [self postNotification:EODatabaseChannelDidDeleteObjectName object:anObj]; return YES; } - (BOOL)lockObject:(id)anObj { EOEntity *entity = nil; NSDictionary *pkey = nil; NSDictionary *snapshot = nil; EOSQLQualifier *qualifier = nil; [self postNotification:EODatabaseChannelWillLockObjectName object:anObj]; if (![anObj prepareForLockInChannel:self context:self->databaseContext]) return NO; // Check the delegate if ([delegate respondsToSelector:@selector(databaseChannel:willLockObject:)]) anObj = [delegate databaseChannel:self willLockObject:anObj]; // Check nil (delegate disallowes or given object was nil) if (anObj == nil) return NO; // Check if fault if ([EOFault isFault:anObj]) { [NSException raise:NSInvalidArgumentException format:@"Attempt to lock a fault in a database channel"]; } // Check if we can lock if ([databaseContext updateStrategy] == EONoUpdate) { [self privateReportError:_cmd : @"cannot lock if context has 'NoUpdate' update strategy."]; return NO; } // Check if in a transaction if (![databaseContext transactionNestingLevel]) { [self privateReportError:_cmd : @"cannot lock if contex has no transaction opened."]; return NO; } // Check if fetch is in progress if ([self isFetchInProgress]) { [self privateReportError:_cmd : @"cannot lock if contex has a fetch in progress."]; return NO; } // Get entity entity = [anObj respondsToSelector:@selector(entity)] ? [anObj entity] : [[[[adaptorChannel adaptorContext] adaptor] model] entityForObject:anObj]; // Check entity if (entity == nil) { [self privateReportError:_cmd : @"cannot determine entity for object %p class %s.", anObj, NSStringFromClass([anObj class])]; return NO; } if ([entity isReadOnly]) { [self privateReportError:_cmd : @"cannot lock object %p for readonly entity %@.", anObj, [entity name]]; return NO; } // Get snapshot and old primary key [databaseContext primaryKey:&pkey andSnapshot:&snapshot forObject:anObj]; if (snapshot == nil) { [self privateReportError:_cmd : @"cannot lock object %p because there is no snapshot for it."]; return NO; } if (pkey == nil) pkey = [entity primaryKeyForRow:snapshot]; if (pkey == nil) { [self privateReportError:_cmd : @"cannot determine primary key for %p from values %@ entity %@.", anObj, [snapshot description], [entity name]]; return NO; } { NSArray *lockAttrs = [entity attributesUsedForLocking]; NSDictionary *row = nil; qualifier = [EOSQLQualifier qualifierForPrimaryKey:pkey entity:entity]; #ifdef DEBUG NSAssert2([lockAttrs count] > 0, @"missing locking attributes: lock=%@ object=%@", lockAttrs, anObj); #endif if (![adaptorChannel selectAttributes:lockAttrs describedByQualifier:qualifier fetchOrder:nil lock:YES]) { [self privateReportError:_cmd : @"could not lock %p with qualifier %@.", anObj, [qualifier description]]; return NO; } row = [adaptorChannel fetchAttributes:lockAttrs withZone:NULL]; [adaptorChannel cancelFetch]; if (row == nil) { [self privateReportError:_cmd : @"could not lock %p with qualifier %@.", anObj, [qualifier description]]; return NO; } if (![row isEqual:snapshot]) { [self privateReportError:_cmd : @"could not lock %p. Snapshots: self %@ database %@.", anObj, [snapshot description], [row description]]; return NO; } } // Register lock object in database context [databaseContext recordLockedObject:anObj]; self->lockCount++; [anObj wasLockedInChannel:self context:self->databaseContext]; // Notify delegate if ([delegate respondsToSelector:@selector(databaseChannel:didLockObject:)]) [delegate databaseChannel:self didLockObject:anObj]; [self postNotification:EODatabaseChannelDidLockObjectName object:anObj]; return YES; } - (BOOL)refetchObject:(id)anObj { EOEntity *entity = nil; NSDictionary *pkey = nil; NSDictionary *snapshot = nil; EOSQLQualifier *qualifier = nil; // Check the delegate if ([delegate respondsToSelector: @selector(databaseChannel:willRefetchObject:)]) anObj = [delegate databaseChannel:self willRefetchObject:anObj]; // Check nil (delegate disallowes or given object was nil) if (anObj == nil) return NO; // Check if fault if ([EOFault isFault:anObj]) { [NSException raise:NSInvalidArgumentException format:@"Attempt to refetch a fault in a database channel"]; } // Check if in a transaction if (![databaseContext transactionNestingLevel]) { [self privateReportError:_cmd : @"cannot refetch if context has no transaction opened."]; return NO; } // Check if fetch is in progress if ([self isFetchInProgress]) { [self privateReportError:_cmd : @"cannot refetch if context has a fetch in progress."]; return NO; } // Get entity entity = [anObj respondsToSelector:@selector(entity)] ? [anObj entity] : [[[[adaptorChannel adaptorContext] adaptor] model] entityForObject:anObj]; // Check entity if (entity == nil) { [self privateReportError:_cmd : @"cannot determine entity for object %p class %s.", anObj, NSStringFromClass([anObj class])]; return NO; } // Get snapshot and old primary key [databaseContext primaryKey:&pkey andSnapshot:&snapshot forObject:anObj]; if (pkey == nil) { if (snapshot == nil) [self privateReportError:_cmd : @"cannot refetch object %p because there is no snapshot for it."]; pkey = [entity primaryKeyForRow:snapshot]; } if (pkey == nil) { [self privateReportError:_cmd : @"cannot determine primary key for %p from values %@ entity %@.", anObj, [snapshot description], [entity name]]; return NO; } // Get and check qualifier for object to refetch qualifier = [EOSQLQualifier qualifierForPrimaryKey:pkey entity:entity]; if (qualifier == nil) { [self privateReportError:_cmd : @"cannot make qualifier to refetch %p primary key %@ entity %@.", anObj, [pkey description], [entity name]]; return NO; } // Request object from adaptor [self setCurrentEntity:entity]; [self privateUpdateCurrentEntityInfo]; if (currentAttributes == nil) { [self privateReportError:_cmd : @"internal inconsitency while refetching %p.", anObj]; return NO; } #ifdef DEBUG NSAssert3([currentAttributes count] > 0, @"missing attributes for select: lock=%@ object=%@ entity=%@", currentAttributes, anObj, entity); #endif if (![adaptorChannel selectAttributes:currentAttributes describedByQualifier:qualifier fetchOrder:nil lock:([databaseContext updateStrategy] == EOUpdateWithPessimisticLocking)]) { [self privateClearCurrentEntityInfo]; return NO; } // Get object from adaptor, re-build its faults and record new snapshot anObj = [self privateFetchWithZone:NULL]; [self cancelFetch]; if (anObj == nil) { [self privateReportError:_cmd : @"could not refetch %p with qualifier %@.", anObj, [qualifier description]]; return NO; } // Notify delegate if ([delegate respondsToSelector:@selector(databaseChannel:didRefetchObject:)]) [delegate databaseChannel:self didRefetchObject:anObj]; return YES; } - (id)_createObjectForRow:(NSDictionary*)aRow entity:(EOEntity*)anEntity isPrimaryKey:(BOOL)yn zone:(NSZone*)zone { Class class = Nil; id anObj = nil; if (anEntity == nil) return nil; class = [self privateClassForEntity:anEntity]; // Create new instance if ([class respondsToSelector:@selector(classForEntity:values:)]) class = [class classForEntity:anEntity values:aRow]; anObj = [class allocWithZone:zone]; return anObj; } - (id)allocateObjectForRow:(NSDictionary *)row entity:(EOEntity *)anEntity zone:(NSZone *)zone { Class class = Nil; id anObj = nil; if (anEntity == nil) return nil; class = [self privateClassForEntity:anEntity]; // Create new instance if ([class respondsToSelector:@selector(classForEntity:values:)]) class = [class classForEntity:anEntity values:row]; anObj = [class allocWithZone:zone]; return anObj; } - (id)initializedObjectForRow:(NSDictionary *)row entity:(EOEntity *)anEntity zone:(NSZone *)zone { id anObj; anObj = [self allocateObjectForRow:row entity:anEntity zone:zone]; anObj = [anObj respondsToSelector:@selector(initWithPrimaryKey:entity:)] ? [anObj initWithPrimaryKey:row entity:anEntity] : [anObj init]; return AUTORELEASE(anObj); } /* * Fetching objects */ - (id)_fetchObject:(id)anObj qualifier:(EOSQLQualifier *)qualifier { id obj; [self selectObjectsDescribedByQualifier:qualifier fetchOrder:nil]; obj = [self fetchWithZone:NULL]; [self cancelFetch]; return obj; } - (BOOL)selectObjectsDescribedByQualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder { if ([delegate respondsToSelector: @selector(databaseChannel:willSelectObjectsDescribedByQualifier:fetchOrder:)]) if (![delegate databaseChannel:self willSelectObjectsDescribedByQualifier:qualifier fetchOrder:fetchOrder]) return NO; [self setCurrentEntity:[qualifier entity]]; [self privateUpdateCurrentEntityInfo]; if (self->currentAttributes == nil) { [self privateReportError:_cmd : @"internal inconsitency while selecting."]; } #ifdef DEBUG NSAssert3([self->currentAttributes count] > 0, @"missing select attributes: attrs=%@, qualifier=%@, entity=%@", self->currentAttributes, qualifier, self->currentEntity); #endif if (![adaptorChannel selectAttributes:self->currentAttributes describedByQualifier:qualifier fetchOrder:fetchOrder lock:([databaseContext updateStrategy] == EOUpdateWithPessimisticLocking)]) { [self privateClearCurrentEntityInfo]; [self privateReportError:_cmd : @"could not select attributes with qualifier %@.", [qualifier description]]; return NO; } if ([delegate respondsToSelector: @selector(databaseChannel:didSelectObjectsDescribedByQualifier:fetchOrder:)]) [delegate databaseChannel:self didSelectObjectsDescribedByQualifier:qualifier fetchOrder:fetchOrder]; return YES; } - (id)fetchWithZone:(NSZone *)zone { id object = nil; if ([delegate respondsToSelector: @selector(databaseChannel:willFetchObjectOfClass:withZone:)]) { Class class; class = currentClass ? currentClass : [self privateClassForEntity:currentEntity]; [delegate databaseChannel:self willFetchObjectOfClass:class withZone:zone]; } object = [self privateFetchWithZone:zone]; if (object == nil) return nil; if ([delegate respondsToSelector:@selector(databaseChannel:didFetchObject:)]) [delegate databaseChannel:self didFetchObject:object]; return object; } - (BOOL)isFetchInProgress { return [[self adaptorChannel] isFetchInProgress]; } - (void)cancelFetch { if ([[self adaptorChannel] isFetchInProgress]) { [self privateClearCurrentEntityInfo]; [[self adaptorChannel] cancelFetch]; } } - (void)setCurrentEntity:(EOEntity *)_entity { // Clear entity info [self privateClearCurrentEntityInfo]; // Set new entity NSAssert(self->currentEntity == nil, @"entity not cleared correctly .."); self->currentEntity = RETAIN(_entity); } - (void)privateClearCurrentEntityInfo { RELEASE(self->currentEntity); self->currentEntity = nil; RELEASE(self->currentAttributes); self->currentAttributes = nil; RELEASE(self->currentRelations); self->currentRelations = nil; self->currentClass = Nil; self->currentReady = NO; } - (void)privateUpdateCurrentEntityInfo { if (self->currentEntity == nil) { [NSException raise:NSInvalidArgumentException format:@"Must use setCurrentEntity if select is not done " @"through database"]; } if (self->currentAttributes == nil) self->currentAttributes = RETAIN([self->currentEntity attributesUsedForFetch]); if (self->currentRelations == nil) self->currentRelations = RETAIN([self->currentEntity relationsUsedForFetch]); self->currentReady = YES; } /* * Private methods */ - (Class)privateClassForEntity:(EOEntity *)anEntity { Class class; if (anEntity == currentEntity && currentClass) return currentClass; // Get class for new object class = NSClassFromString([anEntity className]); if (!class && [delegate respondsToSelector: @selector(databaseChannel:failedToLookupClassNamed:)]) class = [delegate databaseChannel:self failedToLookupClassNamed:[[anEntity className] cString]]; if (class == Nil) class = [EOGenericRecord class]; if (anEntity == currentEntity) currentClass = class; return class; } - (id)privateFetchWithZone:(NSZone *)_zone { NSMutableDictionary *values = nil; id object = nil; NSDictionary *pkey = nil; NSDictionary *snapshot = nil; NSDictionary *row = nil; NSDictionary *dict = nil;; // Be sure we have entity info (raises if no entity is set) if (!self->currentReady) [self privateUpdateCurrentEntityInfo]; // fetch row from adaptor row = [[self adaptorChannel] fetchAttributes:self->currentAttributes withZone:_zone]; if (row == nil) // Results set finished or no more result sets return nil; #if 0 row = [row copyWithZone:_zone]; AUTORELEASE(row); #endif // determine primary key and snapshot snapshot = [self->currentEntity snapshotForRow:row]; pkey = [self->currentEntity primaryKeyForRow:row]; if ((pkey == nil) || (snapshot == nil)) { // TODO - should we have a delegate method here ? [NSException raise:NSInvalidArgumentException format:@"Cannot determine primary key and snapshot for row"]; } // lookup object in context/database object = [self->databaseContext objectForPrimaryKey:pkey entity:currentEntity]; // use old, make new, clear fault if (object == nil) { //NSLog(@"new anObj\n"); object = [self initializedObjectForRow:row entity:currentEntity zone:_zone]; } if ([EOFault isFault:object]) { [EODatabaseFault clearFault:object]; object = [object respondsToSelector:@selector(initWithPrimaryKey:entity:)] ? [object initWithPrimaryKey:row entity:currentEntity] : [object init]; if (object == nil) { [NSException raise:NSInvalidArgumentException format:@"could not initialize cleared fault with " @"row `%@' and entity %@", [row description], [currentEntity name]]; } } // make values // TODO - handle only class properties to object values = [NSMutableDictionary dictionaryWithCapacity: ([row count] + [currentRelations count])]; [values addEntriesFromDictionary:row]; // resolve relationships (to-one and to-many) { EORelationship *rel = nil; int i, n = [self->currentRelations count]; id fault = nil; for (i = 0; i < n; i++) { rel = [self->currentRelations objectAtIndex:i]; // Check if the delegate can provide a different relationship if ([delegate respondsToSelector: @selector(databaseChannel:relationshipForRow:relationship:)]) { id nrel = [delegate databaseChannel:self relationshipForRow:row relationship:rel]; rel = nrel ? nrel : (id)rel; } if ([rel isToMany]) { // Build to-many fault EOSQLQualifier* qualifier = [EOSQLQualifier qualifierForRow:row relationship:rel]; if (qualifier == nil) { // HH: THROW was uncommented .. [NSException raise:NSInvalidArgumentException format: @"Cannot build fault qualifier for relationship"]; // TODO continue; } #if LIB_FOUNDATION_LIBRARY if ([NSClassFromString([[rel destinationEntity] className]) isGarbageCollectable]) fault = [EODatabaseFault gcArrayFaultWithQualifier:qualifier fetchOrder:nil databaseChannel:self zone:_zone]; else #endif fault = [EODatabaseFault arrayFaultWithQualifier:qualifier fetchOrder:nil databaseChannel:self zone:_zone]; } else { // Build to-one fault EOEntity *faultEntity; NSDictionary *faultKey; faultEntity = [rel destinationEntity]; faultKey = [rel foreignKeyForRow:row]; faultKey = [faultEntity primaryKeyForRow:faultKey]; if (faultEntity == nil) { [NSException raise:NSInvalidArgumentException format:@"Cannot get entity for relationship"]; } if (faultKey) { fault = [self->databaseContext objectForPrimaryKey:faultKey entity:faultEntity]; if (fault == nil) { fault = [EODatabaseFault objectFaultWithPrimaryKey:faultKey entity:faultEntity databaseChannel:self zone:_zone]; [databaseContext recordObject:fault primaryKey:faultKey entity:faultEntity snapshot:nil]; } } else fault = [EONull null]; } if (fault) [values setObject:fault forKey:[rel name]]; } } // check if is updated in another context or just updated or new (delegate) dict = values; if ([[databaseContext database] isObject:object updatedOutsideContext:databaseContext]) { if ([delegate respondsToSelector: @selector(databaseChannel:willRefetchConflictingObject:withSnapshot:)]) { dict = [delegate databaseChannel:self willRefetchConflictingObject:object withSnapshot:values]; } else { [NSException raise:NSInvalidArgumentException format:@"object updated in an uncommitted transaction " @"was fetched"]; } } else { if ([delegate respondsToSelector: @selector(databaseChannel:willRefetchObject:fromSnapshot:)]) { dict = [delegate databaseChannel:self willRefetchObject:object fromSnapshot:values]; } } // does delegate disallow setting the new values and recording the fetch ? if (dict == nil) return object; // put values [object takeValuesFromDictionary:dict]; // register lock if locked if ([databaseContext updateStrategy] == EOUpdateWithPessimisticLocking) [databaseContext recordLockedObject:object]; // register object in context [databaseContext recordObject:object primaryKey:pkey entity:currentEntity snapshot:snapshot]; // awake object from database channel if ([object respondsToSelector:@selector(awakeForDatabaseChannel:)]) [object awakeForDatabaseChannel:self]; // Done. return object; } // ******************** Reporting errors ******************** - (void)privateReportError:(SEL)method :(NSString*)format,... { NSString* message; va_list va; if (![[databaseContext database] logsErrorMessages]) return; va_start(va, format); message = AUTORELEASE([[NSString alloc] initWithFormat:format arguments:va]); va_end(va); [[databaseContext database] reportErrorFormat: @"EODatabaseChannel:error in [EODatabaseChannel %@]: %@", NSStringFromSelector(method), message]; } @end /* EODatabaseChannel */ @implementation NSObject(EODatabaseChannelEONotifications) - (BOOL)prepareForDeleteInChannel:(EODatabaseChannel *)_channel context:(EODatabaseContext *)_ctx { return YES; } - (void)wasDeletedInChannel:(EODatabaseChannel *)_channel context:(EODatabaseContext *)_ctx { } - (BOOL)prepareForInsertInChannel:(EODatabaseChannel *)_channel context:(EODatabaseContext *)_ctx { return YES; } - (void)wasInsertedInChannel:(EODatabaseChannel *)_channel context:(EODatabaseContext *)_ctx { } - (BOOL)prepareForUpdateInChannel:(EODatabaseChannel *)_channel context:(EODatabaseContext *)_ctx { return YES; } - (void)wasUpdatedInChannel:(EODatabaseChannel *)_channel context:(EODatabaseContext *)_ctx { } - (BOOL)prepareForLockInChannel:(EODatabaseChannel *)_channel context:(EODatabaseContext *)_ctx { return YES; } - (void)wasLockedInChannel:(EODatabaseChannel *)_channel context:(EODatabaseContext *)_ctx { } @end /* NSObject(EODatabaseChannelNotifications) */ @implementation EODatabaseChannel(Statistics) - (unsigned int)successfulOpenCount { return self->successfulOpenCount; } - (unsigned int)failedOpenCount { return self->failedOpenCount; } - (unsigned int)closeCount { return self->closeCount; } - (unsigned int)insertCount { return self->insertCount; } - (unsigned int)updateCount { return self->updateCount; } - (unsigned int)deleteCount { return self->deleteCount; } - (unsigned int)lockCount { return self->lockCount; } @end SOPE/sope-gdl1/GDLAccess/EORelationship.h0000644000000000000000000000751115004363604016710 0ustar rootroot/* EORelationship.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: August 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EORelationship_h__ #define __EORelationship_h__ #import #import @class NSString, NSDictionary, NSException; @class EOModel, EOEntity, EOAttribute; @interface EORelationship : NSObject { NSString *name; NSString *definition; NSDictionary *userDictionary; /* Garbage collectable objects */ EOEntity *entity; /* non-retained */ EOEntity *destinationEntity; /* non-retained */ /* Computed values */ NSMutableArray *componentRelationships; struct { BOOL isFlattened:1; BOOL isToMany:1; BOOL createsMutableObjects:1; BOOL isMandatory:1; } flags; // EOJoin EOAttribute *sourceAttribute; EOAttribute *destinationAttribute; } /* Initializing instances */ - (id)initWithName:(NSString*)name; /* Accessing the name */ - (BOOL)setName:(NSString*)name; - (NSString*)name; + (BOOL)isValidName:(NSString*)name; /* Using joins */ - (NSArray*)joins; /* Convering source row in destination row */ - (NSDictionary*)foreignKeyForRow:(NSDictionary*)row; /* Accessing the definition */ - (NSArray*)componentRelationships; - (void)setDefinition:(NSString*)definition; - (NSString*)definition; /* Accessing the entities joined */ - (void)setEntity:(EOEntity*)entity; - (EOEntity*)entity; - (void)resetEntities; - (BOOL)hasEntity; - (BOOL)hasDestinationEntity; - (EOEntity*)destinationEntity; /* Checking type */ - (BOOL)isCompound; // always NO (no compound joins supported) - (BOOL)isFlattened; /* Accessing to-many property */ - (BOOL)setToMany:(BOOL)flag; - (BOOL)isToMany; /* Checking references */ - (BOOL)referencesProperty:(id)property; /* Accessing the user dictionary */ - (void)setUserDictionary:(NSDictionary*)dictionary; - (NSDictionary*)userDictionary; @end @interface EORelationship(EOJoin) - (void)loadJoinPropertyList:(id)propertyList; /* Accessing join properties */ - (void)setDestinationAttribute:(EOAttribute*)attribute; - (EOAttribute*)destinationAttribute; - (void)setSourceAttribute:(EOAttribute*)attribute; - (EOAttribute*)sourceAttribute; - (EORelationship*)relationship; @end @interface EORelationship (EORelationshipPrivate) + (EORelationship*)relationshipFromPropertyList:(id)propertyList model:(EOModel*)model; - (void)replaceStringsWithObjects; - (void)initFlattenedRelationship; - (id)propertyList; - (void)setCreateMutableObjects:(BOOL)flag; - (BOOL)createsMutableObjects; @end /* EORelationship (EORelationshipPrivate) */ @class NSMutableDictionary; @interface EORelationship(PropertyListCoding) - (void)encodeIntoPropertyList:(NSMutableDictionary *)_plist; @end @class NSException; @interface EORelationship(EOF2Additions) /* constraints */ - (void)setIsMandatory:(BOOL)_flag; - (BOOL)isMandatory; - (NSException *)validateValue:(id *)_value; @end #endif /* __EORelationship_h__ */ /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/EOEntity.m0000644000000000000000000010126515004363604015531 0ustar rootroot/* EOEntity.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: August 1996 Author: Helge Hess Date: November 1999 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "EOEntity.h" #import "EOAttribute.h" #import "EOFExceptions.h" #import "EOModel.h" #import "EOPrimaryKeyDictionary.h" #import "EOSQLQualifier.h" #import "EORelationship.h" #import #import static int _compareByName(id obj1, id obj2, void * context); @interface NSObject(MappedArrayProtocol) - (NSArray *)mappedArrayUsingSelector:(SEL)_selector; @end @interface NSString(EntityBeautify) - (NSString *)_beautifyEntityName; @end @implementation EOEntity - (id)init { if ((self = [super init])) { self->attributes = [[NSArray alloc] init]; self->attributesByName = [[NSMutableDictionary alloc] init]; self->relationships = [[NSArray alloc] init]; self->relationshipsByName = [[NSMutableDictionary alloc] init]; self->classProperties = [[NSArray alloc] init]; self->model = nil; } return self; } - (void)resetAttributes { [self->attributes makeObjectsPerformSelector:@selector(resetEntity)]; } - (void)resetRelationships { [self->relationships makeObjectsPerformSelector:@selector(resetEntities)]; } - (void)dealloc { self->model = nil; RELEASE(self->qualifier); [self resetAttributes]; RELEASE(self->attributes); RELEASE(self->attributesByName); [self resetRelationships]; RELEASE(self->relationships); RELEASE(self->relationshipsByName); RELEASE(self->primaryKeyAttributes); RELEASE(self->classProperties); RELEASE(self->attributesUsedForLocking); RELEASE(self->attributesUsedForInsert); RELEASE(self->attributesUsedForFetch); RELEASE(self->relationsUsedForFetch); RELEASE(self->name); self->name = nil; RELEASE(self->className); self->className = nil; RELEASE(self->externalName); self->externalName = nil; RELEASE(self->externalQuery); self->externalQuery = nil; RELEASE(self->userDictionary); self->userDictionary = nil; RELEASE(self->primaryKeyAttributeNames); self->primaryKeyAttributeNames = nil; RELEASE(self->attributesNamesUsedForInsert); self->attributesNamesUsedForInsert = nil; RELEASE(self->classPropertyNames); self->classPropertyNames = nil; [super dealloc]; } // These methods should be here to let the library work with NeXT foundation - (id)copy { return RETAIN(self); } - (id)copyWithZone:(NSZone *)_zone { return RETAIN(self); } // Is equal only if same name; used to make aliasing ordering stable - (NSUInteger)hash { return [name hash]; } - (id)initWithName:(NSString *)_name { [self init]; ASSIGN(name, _name); return self; } - (BOOL)setName:(NSString *)_name { if([model entityNamed:name]) return NO; ASSIGN(name, _name); return YES; } + (BOOL)isValidName:(NSString *)attributeName { unsigned len = [attributeName cStringLength]; char buf[len + 1]; const char *s; s = buf; [attributeName getCString:buf]; if(!isalnum((int)*s) && *s != '@' && *s != '_' && *s != '#') return NO; for(++s; *s; s++) if(!isalnum((int)*s) && *s != '@' && *s != '_' && *s != '#' && *s != '$') return NO; return YES; } - (BOOL)addAttribute:(EOAttribute *)attribute { NSString* attributeName = [attribute name]; if([self->attributesByName objectForKey:attributeName]) return NO; if([self->relationshipsByName objectForKey:attributeName]) return NO; if([self createsMutableObjects]) [(NSMutableArray*)self->attributes addObject:attribute]; else { id newAttributes = [self->attributes arrayByAddingObject:attribute]; ASSIGN(self->attributes, newAttributes); } [self->attributesByName setObject:attribute forKey:attributeName]; [attribute setEntity:self]; [self invalidatePropertiesCache]; return YES; } - (void)removeAttributeNamed:(NSString *)attributeName { id attribute = [self->attributesByName objectForKey:attributeName]; if(attribute) { [attribute resetEntity]; if([self createsMutableObjects]) [(NSMutableArray*)attributes removeObject:attribute]; else { self->attributes = [AUTORELEASE(self->attributes) mutableCopy]; [(NSMutableArray*)self->attributes removeObject:attribute]; self->attributes = [AUTORELEASE(self->attributes) copy]; } [self->attributesByName removeObjectForKey:attributeName]; [self invalidatePropertiesCache]; } } - (EOAttribute *)attributeNamed:(NSString *)attributeName { return [self->attributesByName objectForKey:attributeName]; } - (BOOL)addRelationship:(EORelationship *)relationship { NSString* relationshipName = [relationship name]; if([self->attributesByName objectForKey:relationshipName]) return NO; if([self->relationshipsByName objectForKey:relationshipName]) return NO; if([self createsMutableObjects]) [(NSMutableArray*)relationships addObject:relationship]; else { id newRelationships = [self->relationships arrayByAddingObject:relationship]; ASSIGN(self->relationships, newRelationships); } [self->relationshipsByName setObject:relationship forKey:relationshipName]; [relationship setEntity:self]; [self invalidatePropertiesCache]; return YES; } - (void)removeRelationshipNamed:(NSString*)relationshipName { id relationship = [relationshipsByName objectForKey:relationshipName]; if(relationship) { [relationship setEntity:nil]; if([self createsMutableObjects]) [(NSMutableArray*)self->relationships removeObject:relationship]; else { self->relationships = [AUTORELEASE(self->relationships) mutableCopy]; [(NSMutableArray*)self->relationships removeObject:relationship]; self->relationships = [AUTORELEASE(relationships) copy]; } [self->relationshipsByName removeObjectForKey:relationship]; [self invalidatePropertiesCache]; } } - (EORelationship*)relationshipNamed:(NSString *)relationshipName { if([relationshipName isNameOfARelationshipPath]) { NSArray *defArray; int i, count; EOEntity *currentEntity = self; NSString *relName = nil; EORelationship *relationship = nil; defArray = [relationshipName componentsSeparatedByString:@"."]; relName = [defArray objectAtIndex:0]; for(i = 0, count = [defArray count]; i < count; i++) { if(![EOEntity isValidName:relName]) return nil; relationship = [currentEntity->relationshipsByName objectForKey:relName]; if(relationship == nil) return nil; currentEntity = [relationship destinationEntity]; } return relationship; } else return [self->relationshipsByName objectForKey:relationshipName]; } - (BOOL)setPrimaryKeyAttributes:(NSArray *)keys { int i, count = [keys count]; for(i = 0; i < count; i++) if(![self isValidPrimaryKeyAttribute:[keys objectAtIndex:i]]) return NO; RELEASE(self->primaryKeyAttributes); RELEASE(self->primaryKeyAttributeNames); if([keys isKindOfClass:[NSArray class]] || [keys isKindOfClass:[NSMutableArray class]]) self->primaryKeyAttributes = [keys copy]; else self->primaryKeyAttributes = [[NSArray alloc] initWithArray:keys]; self->primaryKeyAttributeNames = [NSMutableArray arrayWithCapacity:count]; for(i = 0; i < count; i++) { id key = [keys objectAtIndex:i]; [(NSMutableArray*)self->primaryKeyAttributeNames addObject:[(EOAttribute*)key name]]; } self->primaryKeyAttributeNames = RETAIN([self->primaryKeyAttributeNames sortedArrayUsingSelector:@selector(compare:)]); [self invalidatePropertiesCache]; return YES; } - (BOOL)isValidPrimaryKeyAttribute:(EOAttribute*)anAttribute { if(![anAttribute isKindOfClass:[EOAttribute class]]) return NO; if([self->attributesByName objectForKey:[anAttribute name]]) return YES; return NO; } - (NSDictionary *)primaryKeyForRow:(NSDictionary *)_row { return [EOPrimaryKeyDictionary dictionaryWithKeys: self->primaryKeyAttributeNames fromDictionary:_row]; } - (NSDictionary *)snapshotForRow:(NSDictionary *)aRow { NSArray *array; int i, n; NSMutableDictionary *dict; array = [self attributesUsedForLocking]; n = [array count]; dict = [NSMutableDictionary dictionaryWithCapacity:n]; for (i = 0; i < n; i++) { EOAttribute *attribute; NSString *attributeName; id value; attribute = [array objectAtIndex:i]; attributeName = [attribute name]; value = [aRow objectForKey:attributeName]; #if DEBUG NSString *columnName; columnName = [attribute columnName]; NSAssert1(columnName, @"missing column name in attribute %@ !", attribute); NSAssert3(value, @"missing value for column '%@' (attr '%@') in row %@", columnName, attribute, aRow); #endif [dict setObject:value forKey:attributeName]; } return dict; } /* Getting attributes used for database oprations */ - (NSArray*)attributesUsedForInsert { if (!flags.isPropertiesCacheValid) [self validatePropertiesCache]; return self->attributesUsedForInsert; } - (NSArray *)attributesUsedForFetch { if (!flags.isPropertiesCacheValid) [self validatePropertiesCache]; return self->attributesUsedForFetch; } - (NSArray *)relationsUsedForFetch { if (!flags.isPropertiesCacheValid) [self validatePropertiesCache]; return self->relationsUsedForFetch; } - (NSArray *)attributesNamesUsedForInsert { if (!flags.isPropertiesCacheValid) [self validatePropertiesCache]; return self->attributesNamesUsedForInsert; } - (BOOL)setClassProperties:(NSArray *)properties { int i, count = [properties count]; for(i = 0; i < count; i++) if(![self isValidClassProperty:[properties objectAtIndex:i]]) return NO; RELEASE(self->classProperties); self->classProperties = nil; RELEASE(self->classPropertyNames); self->classPropertyNames = nil; if([properties isKindOfClass:[NSArray class]] || [properties isKindOfClass:[NSMutableArray class]]) { self->classProperties = [properties copyWithZone:[self zone]]; } else { self->classProperties = [[NSArray allocWithZone:[self zone]] initWithArray:properties]; } self->classPropertyNames = [NSMutableArray arrayWithCapacity:count]; for(i = 0; i < count; i++) { id property = [properties objectAtIndex:i]; [(NSMutableArray*)classPropertyNames addObject:[(EOAttribute*)property name]]; } self->classPropertyNames = [self->classPropertyNames copyWithZone:[self zone]]; [self invalidatePropertiesCache]; return YES; } - (BOOL)isValidClassProperty:(id)aProperty { id thePropertyName = nil; if(!([aProperty isKindOfClass:[EOAttribute class]] || [aProperty isKindOfClass:[EORelationship class]])) return NO; thePropertyName = [(EOAttribute*)aProperty name]; if([self->attributesByName objectForKey:thePropertyName] || [self->relationshipsByName objectForKey:thePropertyName]) return YES; return NO; } - (NSArray *)relationshipsNamed:(NSString *)_relationshipPath { if([_relationshipPath isNameOfARelationshipPath]) { NSMutableArray *myRelationships = [[NSMutableArray alloc] init]; NSArray *defArray = [_relationshipPath componentsSeparatedByString:@"."]; int i, count = [defArray count] - 1; EOEntity *currentEntity = self; NSString *relName = nil; id relation = nil; for(i = 0; i < count; i++) { relName = [defArray objectAtIndex:i]; if([EOEntity isValidName:relName]) { relation = [currentEntity relationshipNamed:relName]; if(relation) { [myRelationships addObject:relation]; currentEntity = [relation destinationEntity]; } } } return AUTORELEASE(myRelationships); } return nil; } - (id)propertyNamed:(NSString *)_name { if([_name isNameOfARelationshipPath]) { NSArray *defArray = [_name componentsSeparatedByString:@"."]; EOEntity *currentEntity = self; NSString *propertyName; int i = 0, count = [defArray count]; id property; for(; i < count - 1; i++) { propertyName = [defArray objectAtIndex:i]; if(![EOEntity isValidName:propertyName]) return nil; property = [currentEntity propertyNamed:propertyName]; if(!property) return nil; currentEntity = [property destinationEntity]; } propertyName = [defArray lastObject]; property = [currentEntity attributeNamed:propertyName]; return property; } else { id attribute = nil; id relationship = nil; attribute = [self->attributesByName objectForKey:_name]; if(attribute) return attribute; relationship = [self->relationshipsByName objectForKey:_name]; if(relationship) return relationship; } return nil; } - (BOOL)setAttributesUsedForLocking:(NSArray *)_attributes { int i, count = [_attributes count]; for(i = 0; i < count; i++) if(![self isValidAttributeUsedForLocking: [_attributes objectAtIndex:i]]) return NO; RELEASE(self->attributesUsedForLocking); if([_attributes isKindOfClass:[NSArray class]] || [_attributes isKindOfClass:[NSMutableArray class]]) self->attributesUsedForLocking = [_attributes copy]; else self->attributesUsedForLocking = [[NSArray alloc] initWithArray:_attributes]; [self invalidatePropertiesCache]; return YES; } - (BOOL)isValidAttributeUsedForLocking:(EOAttribute*)anAttribute { if(!([anAttribute isKindOfClass:[EOAttribute class]] && [self->attributesByName objectForKey:[anAttribute name]])) return NO; return YES; } - (void)setModel:(EOModel *)aModel { self->model = aModel; /* non-retained */ } - (void)resetModel { self->model = nil; } - (BOOL)hasModel { return (self->model != nil) ? YES : NO; } - (void)setClassName:(NSString *)_name { if(!_name) _name = @"EOGenericRecord"; ASSIGN(self->className, _name); } - (void)setReadOnly:(BOOL)flag { flags.isReadOnly = flag; } - (BOOL)referencesProperty:(id)property { id propertyName = [(EOAttribute*)property name]; if([self->attributesByName objectForKey:propertyName] || [self->relationshipsByName objectForKey:propertyName]) return YES; return NO; } - (EOSQLQualifier*)qualifier { if (self->qualifier == nil) { self->qualifier = [[EOSQLQualifier allocWithZone:[self zone]] initWithEntity:self qualifierFormat:nil]; } return self->qualifier; } // accessors - (void)setExternalName:(NSString*)_name { ASSIGN(externalName, _name); } - (NSString *)externalName { return self->externalName; } - (void)setExternalQuery:(NSString*)query { ASSIGN(externalQuery, query); } - (NSString *)externalQuery { return self->externalQuery; } - (void)setUserDictionary:(NSDictionary*)dict { ASSIGN(userDictionary, dict); } - (NSDictionary *)userDictionary { return self->userDictionary; } - (NSString *)name { return self->name; } - (BOOL)isReadOnly { return self->flags.isReadOnly; } - (NSString *)className { return self->className; } - (NSArray *)attributesUsedForLocking { return self->attributesUsedForLocking; } - (NSArray *)classPropertyNames { return self->classPropertyNames; } - (NSArray *)classProperties { return self->classProperties; } - (NSArray *)primaryKeyAttributes { return self->primaryKeyAttributes; } - (NSArray *)primaryKeyAttributeNames { return self->primaryKeyAttributeNames; } - (NSArray *)relationships { return self->relationships; } - (EOModel *)model { return self->model; } - (NSArray *)attributes { return self->attributes; } /* EOEntityCreation */ + (EOEntity *)entityFromPropertyList:(id)propertyList model:(EOModel *)_model { NSDictionary *plist = propertyList; EOEntity *entity; NSArray *array; NSEnumerator *enumerator; id attributePList; id relationshipPList; entity = [[[EOEntity alloc] init] autorelease]; [entity setCreateMutableObjects:YES]; entity->name = RETAIN([plist objectForKey:@"name"]); entity->className = RETAIN([plist objectForKey:@"className"]); entity->externalName = RETAIN([plist objectForKey:@"externalName"]); entity->externalQuery = RETAIN([plist objectForKey:@"externalQuery"]); entity->userDictionary = RETAIN([plist objectForKey:@"userDictionary"]); array = [plist objectForKey:@"attributes"]; enumerator = [array objectEnumerator]; while ((attributePList = [enumerator nextObject])) { EOAttribute *attribute; attribute = [EOAttribute attributeFromPropertyList:attributePList]; if (![entity addAttribute:attribute]) { NSLog(@"duplicate name for attribute '%@' in entity '%@'", [attribute name], [entity name]); [_model errorInReading]; } } entity->attributesUsedForLocking = RETAIN([plist objectForKey:@"attributesUsedForLocking"]); entity->classPropertyNames = RETAIN([plist objectForKey:@"classProperties"]); if ((attributePList = [plist objectForKey:@"primaryKeyAttributes"])) { entity->primaryKeyAttributeNames = RETAIN([attributePList sortedArrayUsingSelector:@selector(compare:)]); } else if ((attributePList = [plist objectForKey:@"primaryKeyAttribute"])) entity->primaryKeyAttributeNames = RETAIN([NSArray arrayWithObject:attributePList]); array = [plist objectForKey:@"relationships"]; enumerator = [array objectEnumerator]; while((relationshipPList = [enumerator nextObject])) { EORelationship *relationship = [EORelationship relationshipFromPropertyList:relationshipPList model:_model]; if(![entity addRelationship:relationship]) { NSLog(@"duplicate name for relationship '%@' in entity '%@'", [relationship name], [entity name]); [_model errorInReading]; } } [entity setCreateMutableObjects:NO]; return entity; } - (void)replaceStringsWithObjects { NSEnumerator *enumerator = nil; EOAttribute *attribute = nil; NSString *attributeName = nil; NSString *propertyName = nil; NSMutableArray *array = nil; int i, count; enumerator = [self->primaryKeyAttributeNames objectEnumerator]; RELEASE(self->primaryKeyAttributes); self->primaryKeyAttributes = AUTORELEASE([NSMutableArray new]); while ((attributeName = [enumerator nextObject])) { attribute = [self attributeNamed:attributeName]; if((attribute == nil) || ![self isValidPrimaryKeyAttribute:attribute]) { NSLog(@"invalid attribute name specified as primary key attribute " @"'%s' in entity '%s'", [attributeName cString], [name cString]); [self->model errorInReading]; } else [(NSMutableArray*)self->primaryKeyAttributes addObject:attribute]; } self->primaryKeyAttributes = [self->primaryKeyAttributes copy]; enumerator = [self->classPropertyNames objectEnumerator]; RELEASE(self->classProperties); self->classProperties = AUTORELEASE([NSMutableArray new]); while((propertyName = [enumerator nextObject])) { id property; property = [self propertyNamed:propertyName]; if(!property || ![self isValidClassProperty:property]) { NSLog(@"invalid property '%s' specified as class property in " @"entity '%s'", [propertyName cString], [name cString]); [self->model errorInReading]; } else [(NSMutableArray*)self->classProperties addObject:property]; } self->classProperties = [self->classProperties copy]; array = AUTORELEASE([NSMutableArray new]); [array setArray:self->attributesUsedForLocking]; RELEASE(self->attributesUsedForLocking); count = [array count]; for(i = 0; i < count; i++) { attributeName = [array objectAtIndex:i]; attribute = [self attributeNamed:attributeName]; if(!attribute || ![self isValidAttributeUsedForLocking:attribute]) { NSLog(@"invalid attribute specified as attribute used for " @"locking '%@' in entity '%@'", attributeName, name); [self->model errorInReading]; } else [array replaceObjectAtIndex:i withObject:attribute]; } self->attributesUsedForLocking = [array copy]; } - (id)propertyList { id propertyList; propertyList = [NSMutableDictionary dictionary]; [self encodeIntoPropertyList:propertyList]; return propertyList; } - (void)setCreateMutableObjects:(BOOL)flag { if(self->flags.createsMutableObjects == flag) return; self->flags.createsMutableObjects = flag; if(self->flags.createsMutableObjects) { self->attributes = [AUTORELEASE(self->attributes) mutableCopy]; self->relationships = [AUTORELEASE(self->relationships) mutableCopy]; } else { self->attributes = [AUTORELEASE(self->attributes) copy]; self->relationships = [AUTORELEASE(self->relationships) copy]; } } - (BOOL)createsMutableObjects { return self->flags.createsMutableObjects; } #if 0 static inline void _printIds(NSArray *a, const char *pfx, const char *indent) { int i; if (pfx == NULL) pfx = ""; if (indent == NULL) indent = " "; printf("%s", pfx); for (i = 0; i < [a count]; i++) printf("%s0x%p\n", indent, (unsigned)[a objectAtIndex:i]); } #endif static inline BOOL _containsObject(NSArray *a, id obj) { id (*objAtIdx)(NSArray*, SEL, int idx); register int i; objAtIdx = (void *)[a methodForSelector:@selector(objectAtIndex:)]; for (i = [a count] - 1; i >= 0; i--) { register id o; o = objAtIdx(a, @selector(objectAtIndex:), i); if (o == obj) return YES; } return NO; } - (void)validatePropertiesCache { NSMutableArray *updAttr = [NSMutableArray new]; NSMutableArray *updName = [NSMutableArray new]; NSMutableArray *fetAttr = [NSMutableArray new]; NSMutableArray *fetRels = [NSMutableArray new]; int i; [self invalidatePropertiesCache]; #ifdef DEBUG NSAssert((updAttr != nil) && (updName != nil) && (fetAttr != nil) && (fetRels != nil), @"allocation of array failed !"); NSAssert(self->primaryKeyAttributes, @"no pkey attributes are set !"); NSAssert(self->attributesUsedForLocking, @"no locking attrs are set !"); NSAssert(self->classProperties, @"no class properties are set !"); #endif //_printIds(self->attributes, "attrs:\n", " "); //_printIds(self->attributesUsedForLocking, "lock:\n", " "); for (i = ([self->attributes count] - 1); i >= 0; i--) { EOAttribute *attr = [self->attributes objectAtIndex:i]; BOOL pk, lk, cp, sa; pk = _containsObject(self->primaryKeyAttributes, attr); lk = _containsObject(self->attributesUsedForLocking, attr); cp = _containsObject(self->classProperties, attr); sa = YES; #if 0 NSLog(@"attribute %@ pk=%i lk=%i cp=%i sa=%i", [attr name], pk, lk, cp, sa); #endif if ((pk || lk || cp) && (!_containsObject(fetAttr, attr))) [fetAttr addObject:attr]; if ((pk || lk || cp) && (sa) && (!_containsObject(updAttr, attr))) { [updAttr addObject:attr]; [updName addObject:[attr name]]; } } for (i = [relationships count]-1; i >= 0; i--) { id rel = [relationships objectAtIndex:i]; if (_containsObject(classProperties, rel)) [fetRels addObject:rel]; } RELEASE(self->attributesUsedForInsert); self->attributesUsedForInsert = [[NSArray alloc] initWithArray:updAttr]; RELEASE(self->relationsUsedForFetch); self->relationsUsedForFetch = [[NSArray alloc] initWithArray:fetRels]; RELEASE(self->attributesUsedForFetch); self->attributesUsedForFetch = [[NSArray alloc] initWithArray: [fetAttr sortedArrayUsingFunction:_compareByName context:nil]]; RELEASE(self->attributesNamesUsedForInsert); attributesNamesUsedForInsert = [updName copy]; if ([self->attributesUsedForFetch count] == 0) { NSLog(@"WARNING: entity %@ has no fetch attributes: " @"attributes=%@ !", self, [[(id)self->attributes mappedArrayUsingSelector:@selector(name)] componentsJoinedByString:@","]); } RELEASE(updAttr); updAttr = nil; RELEASE(fetAttr); fetAttr = nil; RELEASE(fetRels); fetRels = nil; RELEASE(updName); updName = nil; self->flags.isPropertiesCacheValid = YES; } - (void)invalidatePropertiesCache { if (flags.isPropertiesCacheValid) { RELEASE(self->attributesUsedForInsert); RELEASE(self->attributesUsedForFetch); RELEASE(self->relationsUsedForFetch); RELEASE(self->attributesNamesUsedForInsert); self->attributesUsedForInsert = nil; self->attributesUsedForFetch = nil; self->relationsUsedForFetch = nil; self->attributesNamesUsedForInsert = nil; flags.isPropertiesCacheValid = NO; } } // description - (NSString *)description { return [NSString stringWithFormat: @"<%@[0x%p]: name=%@ className=%@ tableName=%@ " @"readOnly=%s>", NSStringFromClass([self class]), self, [self name], [self className], [self externalName], [self isReadOnly] ? "YES" : "NO" ]; } @end /* EOEntity (EOEntityCreation) */ @implementation EOEntity(ValuesConversion) - (NSDictionary *)convertValuesToModel:(NSDictionary *)aRow { NSMutableDictionary *dict; NSEnumerator *enumerator; NSString *key; dict = [NSMutableDictionary dictionaryWithCapacity:[aRow count]]; enumerator = [aRow keyEnumerator]; while ((key = [enumerator nextObject]) != nil) { id old = [aRow objectForKey:key]; id new = [[self attributeNamed:key] convertValueToModel:old]; if (new != nil) [dict setObject:new forKey:key]; } return [dict count] > 0 ? dict : (NSMutableDictionary *)nil; } static int _compareByName(id obj1, id obj2, void * context) { return [[(EOAttribute*)obj1 name] compare:[(EOAttribute*)obj2 name]]; } @end /* EOAttribute (ValuesConversion) */ @implementation EOEntity(EOF2Additions) - (BOOL)isAbstractEntity { return NO; } /* ids */ - (EOGlobalID *)globalIDForRow:(NSDictionary *)_row { static Class EOKeyGlobalIDClass = Nil; unsigned int keyCount = [self->primaryKeyAttributeNames count]; id values[keyCount]; unsigned int i; for (i = 0; i < keyCount; i++) { NSString *attrName; attrName = [self->primaryKeyAttributeNames objectAtIndex:i]; values[i] = [_row objectForKey:attrName]; if (values[i] == nil) return nil; } if (EOKeyGlobalIDClass == Nil) EOKeyGlobalIDClass = [EOKeyGlobalID class]; return [EOKeyGlobalIDClass globalIDWithEntityName:self->name keys:&(values[0]) keyCount:keyCount zone:[self zone]]; } - (BOOL)isPrimaryKeyValidInObject:(id)_object { unsigned int keyCount = [self->primaryKeyAttributeNames count]; unsigned int i; if (_object == nil) return NO; for (i = 0; i < keyCount; i++) { if ([_object valueForKey:[self->primaryKeyAttributeNames objectAtIndex:i]] == nil) return NO; } return YES; } /* refs to other models */ - (NSArray *)externalModelsReferenced { NSEnumerator *e; EORelationship *relship; NSMutableArray *result; EOModel *thisModel; thisModel = [self model]; result = nil; e = [self->relationships objectEnumerator]; while ((relship = [e nextObject]) != nil) { EOEntity *targetEntity; EOModel *extModel; targetEntity = [relship destinationEntity]; extModel = [targetEntity model]; if (extModel != thisModel) { if (result == nil) result = [NSMutableArray array]; [result addObject:extModel]; } } return result != nil ? (id)result : [NSArray array]; } /* fetch specs */ - (EOFetchSpecification *)fetchSpecificationNamed:(NSString *)_name { return nil; } - (NSArray *)fetchSpecificationNames { return nil; } /* names */ - (void)beautifyName { [self setName:[[self name] _beautifyEntityName]]; } @end /* EOEntity(EOF2Additions) */ @implementation EOEntity(PropertyListCoding) static inline void _addToPropList(NSMutableDictionary *propertyList, id _value, NSString *key) { if (_value) [propertyList setObject:_value forKey:key]; } - (void)encodeIntoPropertyList:(NSMutableDictionary *)_plist { int i, count; _addToPropList(_plist, self->name, @"name"); _addToPropList(_plist, self->className, @"className"); _addToPropList(_plist, self->externalName, @"externalName"); _addToPropList(_plist, self->externalQuery, @"externalQuery"); _addToPropList(_plist, self->userDictionary, @"userDictionary"); if ((count = [self->attributes count])) { id attributesPList; attributesPList = [NSMutableArray array]; for (i = 0; i < count; i++) { NSMutableDictionary *attributePList; attributePList = [[NSMutableDictionary alloc] init]; [[self->attributes objectAtIndex:i] encodeIntoPropertyList:attributePList]; [attributesPList addObject:attributePList]; RELEASE(attributePList); } _addToPropList(_plist, attributesPList, @"attributes"); } if ((count = [self->attributesUsedForLocking count])) { id attributesUsedForLockingPList; attributesUsedForLockingPList = [NSMutableArray array]; for (i = 0; i < count; i++) { id attributePList; attributePList = [(EOAttribute*)[self->attributesUsedForLocking objectAtIndex:i] name]; [attributesUsedForLockingPList addObject:attributePList]; } _addToPropList(_plist, attributesUsedForLockingPList, @"attributesUsedForLocking"); } if ((count = [self->classProperties count])) { id classPropertiesPList = nil; classPropertiesPList = [NSMutableArray array]; for (i = 0; i < count; i++) { id classPropertyPList; classPropertyPList = [(EOAttribute*)[self->classProperties objectAtIndex:i] name]; [classPropertiesPList addObject:classPropertyPList]; } _addToPropList(_plist, classPropertiesPList, @"classProperties"); } if ((count = [self->primaryKeyAttributes count])) { id primaryKeyAttributesPList; primaryKeyAttributesPList = [NSMutableArray array]; for (i = 0; i < count; i++) { id attributePList; attributePList = [(EOAttribute*)[self->primaryKeyAttributes objectAtIndex:i] name]; [primaryKeyAttributesPList addObject:attributePList]; } _addToPropList(_plist, primaryKeyAttributesPList, @"primaryKeyAttributes"); } if ((count = [self->relationships count])) { id relationshipsPList; relationshipsPList = [NSMutableArray array]; for (i = 0; i < count; i++) { NSMutableDictionary *relationshipPList; relationshipPList = [NSMutableDictionary dictionary]; [[self->relationships objectAtIndex:i] encodeIntoPropertyList:relationshipPList]; [relationshipsPList addObject:relationshipPList]; } _addToPropList(_plist, relationshipsPList, @"relationships"); } } @end /* EOEntity(PropertyListCoding) */ @implementation NSString(EntityBeautify) - (NSString *)_beautifyEntityName { if ([self length] == 0) return @""; else { unsigned clen = 0; char *s = NULL; unsigned cnt, cnt2; clen = [self cStringLength]; s = malloc(clen + 4); [self getCString:s maxLength:clen]; for (cnt = cnt2 = 0; cnt < clen; cnt++, cnt2++) { if ((s[cnt] == '_') && (s[cnt + 1] != '\0')) { s[cnt2] = toupper(s[cnt + 1]); cnt++; } else if ((s[cnt] == '2') && (s[cnt + 1] != '\0')) { s[cnt2] = s[cnt]; cnt++; cnt2++; s[cnt2] = toupper(s[cnt]); } else s[cnt2] = tolower(s[cnt]); } s[cnt2] = '\0'; s[0] = toupper(s[0]); #if !LIB_FOUNDATION_LIBRARY { NSString *os; os = [NSString stringWithCString:s]; free(s); return os; } #else return [NSString stringWithCStringNoCopy:s freeWhenDone:YES]; #endif } } @end SOPE/sope-gdl1/GDLAccess/EOExpressionArray.h0000644000000000000000000000641715004363604017411 0ustar rootroot/* EOExpressionArray.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: September 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOExpressionArray_h__ #define __EOExpressionArray_h__ #import @class EOAttribute, EOEntity, EOExpressionArray; @protocol EOExpressionContext - (NSString *)expressionValueForAttribute:(EOAttribute *)anAttribute; - (NSString *)expressionValueForAttributePath:(NSArray *)path; @end /* Notes In LSExtendedSearchCommand this is bound to the 'content' of EOSQLQualifier and contains an array like: "(", "(", "(", LOWER, "(", { allowsNull=Y; columnName=name; width=50;...}, ... " = ", 0, ")", ")" so it seems to be a stream of tokens and an EOAttribute mixed in for column keys. Apparently only EOSQLExpression supports the 'EOExpressionContext'? */ @interface EOExpressionArray : NSObject < NSMutableCopying > { @protected NSMutableArray *array; NSString *prefix; NSString *infix; NSString *suffix; } /* Initializing instances */ - (id)initWithPrefix:(NSString*)prefix infix:(NSString*)infix suffix:(NSString*)suffix; /* Accessing the components */ - (void)setPrefix:(NSString*)prefix; - (NSString*)prefix; - (void)setInfix:(NSString*)infix; - (NSString*)infix; - (void)setSuffix:(NSString*)suffix; - (NSString*)suffix; /* Checking contents */ - (BOOL)referencesObject:(id)anObject; - (NSString *)expressionValueForContext:(id)ctx; + (EOExpressionArray *)parseExpression:(NSString *)expression entity:(EOEntity *)entity replacePropertyReferences:(BOOL)flag; + (EOExpressionArray *)parseExpression:(NSString *)expression entity:(EOEntity *)entity replacePropertyReferences:(BOOL)flag relationshipPaths:(NSMutableArray *)relationshipPaths; // array compatibility - (void)addObjectsFromExpressionArray:(EOExpressionArray *)_array; - (void)insertObject:(id)_obj atIndex:(NSUInteger)_idx; - (void)addObjectsFromArray:(NSArray *)_array; - (void)addObject:(id)_object; - (NSUInteger)indexOfObject:(id)_object; - (id)objectAtIndex:(NSUInteger)_idx; - (id)lastObject; - (NSUInteger)count; - (NSEnumerator *)objectEnumerator; - (NSEnumerator *)reverseObjectEnumerator; @end /* EOExpressionArray */ @interface NSObject (EOExpression) - (NSString *)expressionValueForContext:(id)context; @end #endif /* __EOExpressionArray_h__ */ /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/EODatabaseChannel.h0000644000000000000000000001512015004363604017237 0ustar rootroot/* EODatabaseChannel.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EODatabaseChannel_h__ #define __EODatabaseChannel_h__ #import @class NSArray, NSMutableArray, NSDictionary, NSMutableDictionary; @class NSString, NSMutableString, NSNotificationCenter; @class EOAdaptor, EOAdaptorContext, EOAdaptorChannel; @class EOEntity, EOSQLQualifier, EORelationship; @class EOObjectUniquer, EODatabase, EODatabaseContext; @class EOGlobalID; extern NSString *EODatabaseChannelWillOpenNotificationName; extern NSString *EODatabaseChannelDidOpenNotificationName; extern NSString *EODatabaseChannelCouldNotOpenNotificationName; extern NSString *EODatabaseChannelWillCloseNotificationName; extern NSString *EODatabaseChannelDidCloseNotificationName; extern NSString *EODatabaseChannelWillInsertObjectName; extern NSString *EODatabaseChannelDidInsertObjectName; extern NSString *EODatabaseChannelWillUpdateObjectName; extern NSString *EODatabaseChannelDidUpdateObjectName; extern NSString *EODatabaseChannelWillDeleteObjectName; extern NSString *EODatabaseChannelDidDeleteObjectName; extern NSString *EODatabaseChannelWillLockObjectName; extern NSString *EODatabaseChannelDidLockObjectName; @interface EODatabaseChannel : NSObject { @private NSNotificationCenter *notificationCenter; EOAdaptorChannel *adaptorChannel; EODatabaseContext *databaseContext; id delegate; EOEntity *currentEntity; Class currentClass; NSArray *currentAttributes; NSArray *currentRelations; BOOL currentReady; id currentEditingContext; /* statistics */ unsigned int successfulOpenCount; unsigned int failedOpenCount; unsigned int closeCount; unsigned int insertCount; unsigned int updateCount; unsigned int deleteCount; unsigned int lockCount; } // Initializing a new instance - (id)initWithDatabaseContext:(EODatabaseContext*)aDatabaseContext; // Getting the adaptor channel - (EOAdaptorChannel*)adaptorChannel; // Getting the database context - (EODatabaseContext*)databaseContext; // Setting the delegate - (void)setDelegate:(id)aDelegate; - (id)delegate; // Opening and closing a channel - (BOOL)isOpen; - (BOOL)openChannel; - (void)closeChannel; // Modifying objects - (BOOL)insertObject:(id)anObj; - (BOOL)updateObject:(id)anObj; - (BOOL)deleteObject:(id)anObj; - (BOOL)lockObject:(id)anObj; - (BOOL)refetchObject:(id)anObj; - (id)allocateObjectForRow:(NSDictionary*)row entity:(EOEntity*)anEntity zone:(NSZone*)zone; - (id)initializedObjectForRow:(NSDictionary*)row entity:(EOEntity*)anEntity zone:(NSZone*)zone; // Fetching objects - (BOOL)selectObjectsDescribedByQualifier:(EOSQLQualifier*)qualifier fetchOrder:(NSArray*)fetchOrder; - (id)fetchWithZone:(NSZone*)zone; - (BOOL)isFetchInProgress; - (void)cancelFetch; - (void)setCurrentEntity:(EOEntity*)anEntity; @end /* EODatabaseChannel */ /* statistics */ @interface EODatabaseChannel(Statistics) - (unsigned int)successfulOpenCount; - (unsigned int)failedOpenCount; - (unsigned int)closeCount; - (unsigned int)insertCount; - (unsigned int)updateCount; - (unsigned int)deleteCount; - (unsigned int)lockCount; @end /* * Delegate methods */ @interface NSObject(EODatabaseChannelDelegateProtocol) - (id)databaseChannel:aChannel willInsertObject:anObj; - (void)databaseChannel:aChannel didInsertObject:anObj; - (id)databaseChannel:aChannel willDeleteObject:anObj; - (void)databaseChannel:aChannel didDeleteObject:anObj; - (id)databaseChannel:aChannel willUpdateObject:anObj; - (void)databaseChannel:aChannel didUpdateObject:anObj; - (NSDictionary*)databaseChannel:aChannel willRefetchObject:anObj; - (NSDictionary*)databaseChannel:aChannel didRefetchObject:anObj; - (NSDictionary*)databaseChannel:aChannel willRefetchObject:anObj fromSnapshot:(NSDictionary*)snapshot; - (NSDictionary*)databaseChannel:aChannel willRefetchConflictingObject:anObj withSnapshot:(NSMutableDictionary*)snapshot; - (BOOL)databaseChannel:aChannel willSelectObjectsDescribedByQualifier:(EOSQLQualifier*)qualifier fetchOrder:(NSArray*)fetchOrder; - (void)databaseChannel:aChannel didSelectObjectsDescribedByQualifier:(EOSQLQualifier*)qualifier fetchOrder:(NSArray*)fetchOrder; - (void)databaseChannel:aChannel willFetchObjectOfClass:(Class)class withZone:(NSZone*)zone; - (void)databaseChannel:aChannel didFetchObject:anObj; - databaseChannel:aChannel willLockObject:anObj; - (void)databaseChannel:aChannel didLockObject:anObj; - (Class)databaseChannel:aChannel failedToLookupClassNamed:(const char*)name; - (EORelationship*)databaseChannel:aChannel relationshipForRow:(NSDictionary*)row relationship:(EORelationship*)relationship; @end @interface NSObject(EODatabaseChannelEONotifications) - (BOOL)prepareForDeleteInChannel:(EODatabaseChannel *)_channel context:(EODatabaseContext *)_ctx; - (void)wasDeletedInChannel:(EODatabaseChannel *)_channel context:(EODatabaseContext *)_ctx; - (BOOL)prepareForInsertInChannel:(EODatabaseChannel *)_channel context:(EODatabaseContext *)_ctx; - (void)wasInsertedInChannel:(EODatabaseChannel *)_channel context:(EODatabaseContext *)_ctx; - (BOOL)prepareForUpdateInChannel:(EODatabaseChannel *)_channel context:(EODatabaseContext *)_ctx; - (void)wasUpdatedInChannel:(EODatabaseChannel *)_channel context:(EODatabaseContext *)_ctx; - (BOOL)prepareForLockInChannel:(EODatabaseChannel *)_channel context:(EODatabaseContext *)_ctx; - (void)wasLockedInChannel:(EODatabaseChannel *)_channel context:(EODatabaseContext *)_ctx; @end /* * Object Awaking (EODatabaseChannelNotification protocol) */ @interface NSObject(EODatabaseChannelNotification) - (void)awakeForDatabaseChannel:(EODatabaseChannel*)channel; @end #endif /* __EODatabaseChannel_h__ */ SOPE/sope-gdl1/GDLAccess/EOEntityClassDescription.m0000644000000000000000000001410715004363604020721 0ustar rootroot/* EOAttributeOrdering.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOEntityClassDescription.m 1 2004-08-20 10:38:46Z znek $ #import "common.h" #import "EOEntity.h" #import "EOAttribute.h" #import "EORelationship.h" #import #import @interface EOClassDescription(ClassDesc) /* TODO: check, whether this can be removed */ + (NSClassDescription *)classDescriptionForEntityName:(NSString *)_entityName; @end @implementation EOEntityClassDescription - (id)initWithEntity:(EOEntity *)_entity { self->entity = RETAIN(_entity); return self; } - (void)dealloc { RELEASE(self->entity); [super dealloc]; } /* creating instances */ - (id)createInstanceWithEditingContext:(id)_ec globalID:(EOGlobalID *)_oid zone:(NSZone *)_zone { Class eoClass; id eo; eoClass = NSClassFromString([self->entity className]); eo = [eoClass allocWithZone:_zone]; if ([eo respondsToSelector: @selector(initWithEditingContext:classDescription:globalID:)]) eo = [eo initWithEditingContext:_ec classDescription:self globalID:_oid]; else eo = [eo init]; return AUTORELEASE(eo); } /* accessors */ - (EOEntity *)entity { return self->entity; } /* model */ - (NSString *)entityName { return [self->entity name]; } - (NSArray *)attributeKeys { NSArray *attrs = [self->entity attributes]; unsigned int attrCount = [attrs count]; id keys[attrCount]; unsigned int i; for (i = 0; i < attrCount; i++) { EOAttribute *attribute; attribute = [attrs objectAtIndex:i]; keys[i] = [attribute name]; } return [NSArray arrayWithObjects:keys count:attrCount]; } - (NSArray *)toManyRelationshipKeys { NSArray *relships = [self->entity relationships]; unsigned int attrCount = [relships count]; id keys[attrCount]; unsigned int i, j; for (i = 0, j = 0; i < attrCount; i++) { EORelationship *relship; relship = [relships objectAtIndex:i]; if ([relship isToMany]) { keys[j] = [relship name]; } } return [NSArray arrayWithObjects:keys count:j]; } - (NSArray *)toOneRelationshipKeys { NSArray *relships = [self->entity relationships]; unsigned int attrCount = [relships count]; id keys[attrCount]; unsigned int i, j; for (i = 0, j = 0; i < attrCount; i++) { EORelationship *relship; relship = [relships objectAtIndex:i]; if (![relship isToMany]) { keys[j] = [relship name]; } } return [NSArray arrayWithObjects:keys count:j]; } - (NSClassDescription *)classDescriptionForDestinationKey:(NSString *)_key { /* TODO: is this used anywhere?, maybe remove? */ EORelationship *relship; NSString *targetEntityName; if ((relship = [self->entity relationshipNamed:_key]) == nil) return nil; if ([relship isToMany]) return nil; targetEntityName = [[relship entity] name]; return [EOClassDescription classDescriptionForEntityName:targetEntityName]; } /* validation */ - (NSException *)validateObjectForSave:(id)_object { NSMutableArray *exceptions; NSArray *attrs; unsigned int count, i; exceptions = nil; /* validate attributes */ attrs = [self->entity attributes]; count = [attrs count]; for (i = 0; i < count; i++) { EOAttribute *attribute; NSException *exception; id oldValue, newValue; attribute = [attrs objectAtIndex:i]; oldValue = [_object storedValueForKey:[attribute name]]; newValue = oldValue; if ((exception = [attribute validateValue:&newValue])) { /* validation failed */ if (exceptions == nil) exceptions = [NSMutableArray array]; [exceptions addObject:exception]; } else if (oldValue != newValue) { /* apply new value to object (value was changed by val-method) */ [_object takeStoredValue:newValue forKey:[attribute name]]; } } /* validate relationships */ attrs = [self->entity relationships]; count = [attrs count]; for (i = 0; i < count; i++) { EORelationship *relationship; NSException *exception; id oldValue, newValue; relationship = [attrs objectAtIndex:i]; oldValue = [_object storedValueForKey:[relationship name]]; newValue = oldValue; if ((exception = [relationship validateValue:&newValue])) { /* validation failed */ if (exceptions == nil) exceptions = [NSMutableArray array]; [exceptions addObject:exception]; } else if (oldValue != newValue) { /* apply new value to object (value was changed by val-method) */ [_object takeStoredValue:newValue forKey:[relationship name]]; } } /* process exceptions */ if ((count = [exceptions count]) == 0) return nil; if (count == 1) return [exceptions objectAtIndex:0]; { NSException *master; NSMutableDictionary *ui; master = [exceptions objectAtIndex:0]; ui = [[master userInfo] mutableCopy]; if (ui == nil) ui = [[NSMutableDictionary alloc] init]; [ui setObject:exceptions forKey:@"EOAdditionalExceptions"]; master = [NSException exceptionWithName:[master name] reason:[master reason] userInfo:ui]; [ui release]; ui = nil; return master; } } @end /* EOEntityClassDescription */ SOPE/sope-gdl1/GDLAccess/EOAdaptorChannel.h0000644000000000000000000001610515004363604017131 0ustar rootroot/* EOAdaptorChannel.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOAdaptorChannel_h__ #define __EOAdaptorChannel_h__ #import @class NSArray, NSMutableArray, NSDictionary, NSMutableDictionary, NSString; @class NSMutableString, NSCalendarDate, NSException; @class EOModel, EOEntity, EOAttribute, EOSQLQualifier, EOAdaptorContext; /* The EOAdaptorChannel class can be subclassed in a database adaptor. You have to override only those methods marked in this header with `override'. */ @interface EOAdaptorChannel : NSObject { @protected EOAdaptorContext *adaptorContext; id delegate; // not retained /* Flags that determine the state of the adaptor */ BOOL isFetchInProgress; BOOL isOpen; BOOL debugEnabled; /* Flags used to check if the delegate responds to several messages */ struct { BOOL willInsertRow:1; BOOL didInsertRow:1; BOOL willUpdateRow:1; BOOL didUpdateRow:1; BOOL willDeleteRows:1; BOOL didDeleteRows:1; BOOL willSelectAttributes:1; BOOL didSelectAttributes:1; BOOL willFetchAttributes:1; BOOL didFetchAttributes:1; BOOL didChangeResultSet:1; BOOL didFinishFetching:1; BOOL willEvaluateExpression:1; BOOL didEvaluateExpression:1; } delegateRespondsTo; } + (NSCalendarDate*)dateForAttribute:(EOAttribute*)attr year:(int)year month:(unsigned)month day:(unsigned)day hour:(unsigned)hour minute:(unsigned)minute second:(unsigned)second zone:(NSZone*)zone; /* Initializing an adaptor context */ - (id)initWithAdaptorContext:(EOAdaptorContext*)adaptorContext; /* Getting the adaptor context */ - (EOAdaptorContext*)adaptorContext; /* Opening and closing a channel */ - (BOOL)isOpen; - (BOOL)openChannel; - (void)closeChannel; /* Modifying rows, new world methods */ - (NSException *)insertRowX:(NSDictionary *)_row forEntity:(EOEntity *)_entity; - (NSException *)updateRowX:(NSDictionary*)aRow describedByQualifier:(EOSQLQualifier*)aQualifier; - (NSException *)deleteRowsDescribedByQualifierX:(EOSQLQualifier*)aQualifier; /* Modifying rows, old world methods (DEPRECATED) */ - (BOOL)insertRow:(NSDictionary *)aRow forEntity:(EOEntity *)anEntity; - (BOOL)updateRow:(NSDictionary *)aRow describedByQualifier:(EOSQLQualifier *)aQualifier; - (BOOL)deleteRowsDescribedByQualifier:(EOSQLQualifier *)aQualifier; /* Fetching rows */ - (BOOL)selectAttributes:(NSArray *)attributes describedByQualifier:(EOSQLQualifier *)aQualifier fetchOrder:(NSArray *)aFetchOrder lock:(BOOL)aLockFlag; - (NSException *)selectAttributesX:(NSArray *)attributes describedByQualifier:(EOSQLQualifier *)aQualifier fetchOrder:(NSArray *)aFetchOrder lock:(BOOL)aLockFlag; - (NSArray *)describeResults:(BOOL)_beautifyNames; // override - (NSArray *)describeResults; - (NSMutableDictionary*)fetchAttributes:(NSArray *)attributes withZone:(NSZone *)zone; - (BOOL)isFetchInProgress; - (void)cancelFetch; // override - (NSMutableDictionary *)dictionaryWithObjects:(id *)objects forAttributes:(NSArray *)attributes zone:(NSZone *)zone; - (NSMutableDictionary *)primaryFetchAttributes:(NSArray *)attributes withZone:(NSZone *)zone; // override /* Sending SQL to the server */ - (BOOL)evaluateExpression:(NSString *)_anExpression; // override - (NSException *)evaluateExpressionX:(NSString*)_sql; /* Getting schema information */ - (EOModel*)describeModelWithTableNames:(NSArray*)tableNames; // override - (NSArray*)describeTableNames; // override - (BOOL)readTypesForEntity:(EOEntity*)anEntity; // override - (BOOL)readTypeForAttribute:(EOAttribute*)anAttribute; // override /* Debugging */ - (void)setDebugEnabled:(BOOL)flag; - (BOOL)isDebugEnabled; /* Setting the channel's delegate */ - (id)delegate; - (void)setDelegate:aDelegate; @end /* EOAdaptorChannel*/ @interface EOAdaptorChannel(PrimaryKeyGeneration) // new in EOF2 - (NSDictionary *)primaryKeyForNewRowWithEntity:(EOEntity *)_entity; @end @class EOEntity, EOFetchSpecification; @interface EOAdaptorChannel(EOF2Additions) - (void)selectAttributes:(NSArray *)_attributes fetchSpecification:(EOFetchSpecification *)_fspec lock:(BOOL)_flag entity:(EOEntity *)_entity; - (void)setAttributesToFetch:(NSArray *)_attributes; - (NSArray *)attributesToFetch; - (NSMutableDictionary *)fetchRowWithZone:(NSZone *)_zone; @end #import @interface NSObject(EOAdaptorChannelDelegation) - (EODelegateResponse)adaptorChannel:aChannel willInsertRow:(NSMutableDictionary*)aRow forEntity:(EOEntity*)anEntity; - (void)adaptorChannel:channel didInsertRow:(NSDictionary*)aRow forEntity:(EOEntity*)anEntity; - (EODelegateResponse)adaptorChannel:aChannel willUpdateRow:(NSMutableDictionary*)aRow describedByQualifier:(EOSQLQualifier*)aQualifier; - (void)adaptorChannel:aChannel didUpdateRow:(NSDictionary*)aRow describedByQualifier:(EOSQLQualifier*)aQualifier; - (EODelegateResponse)adaptorChannel:aChannel willDeleteRowsDescribedByQualifier:(EOSQLQualifier*)aQualifier; - (void)adaptorChannel:aChannel didDeleteRowsDescribedByQualifier:(EOSQLQualifier*)aQualifier; - (EODelegateResponse)adaptorChannel:aChannel willSelectAttributes:(NSMutableArray*)attributes describedByQualifier:(EOSQLQualifier*)aQualifier fetchOrder:(NSMutableArray*)aFetchOrder lock:(BOOL)aLockFlag; - (void)adaptorChannel:aChannel didSelectAttributes:(NSArray*)attributes describedByQualifier:(EOSQLQualifier*)aQualifier fetchOrder:(NSArray*)aFetchOrder lock:(BOOL)aLockFlag; - (NSMutableDictionary*)adaptorChannel:aChannel willFetchAttributes:(NSArray*)attributes withZone:(NSZone*)zone; - (NSMutableDictionary*)adaptorChannel:aChannel didFetchAttributes:(NSMutableDictionary*)attributes withZone:(NSZone*)zone; - (void)adaptorChannelDidChangeResultSet:aChannel; - (void)adaptorChannelDidFinishFetching:aChannel; - (EODelegateResponse)adaptorChannel:aChannel willEvaluateExpression:(NSMutableString*)anExpression; - (void)adaptorChannel:aChannel didEvaluateExpression:(NSString*)anExpression; @end /* NSObject(EOAdaptorChannelDelegation) */ #endif /* __EOAdaptorChannel_h__ */ SOPE/sope-gdl1/GDLAccess/EODatabaseFault.m0000644000000000000000000001747715004363604016770 0ustar rootroot/* EODatabaseFault.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 Author: Helge Hess Date: 1999 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "EODatabaseFault.h" #import "EODatabase.h" #import "EODatabaseChannel.h" #import "EOEntity.h" #import "EOFExceptions.h" #import "EODatabaseFaultResolver.h" #import "EOArrayProxy.h" #import "common.h" #import "NGExtensions/NSException+misc.h" #if NeXT_RUNTIME || APPLE_RUNTIME # include #endif typedef struct { Class isa; } *my_objc_object; #define object_is_instance(object) \ ((object!=nil)&&CLS_ISCLASS(((my_objc_object)object)->isa)) /* * EODatabaseFault class */ @implementation EODatabaseFault // Fault class methods + (id)objectFaultWithPrimaryKey:(NSDictionary *)key entity:(EOEntity *)entity databaseChannel:(EODatabaseChannel *)channel zone:(NSZone *)zone { EODatabaseFault *fault = nil; fault = [channel allocateObjectForRow:key entity:entity zone:zone]; if (fault == nil) return nil; #if defined(APPLE_RUNTIME) || defined(__GNUSTEP_RUNTIME__) || (__GNU_LIBOBJC__ >= 20100911) if (class_getInstanceSize([fault class]) < class_getInstanceSize([self class])) { #else if ([fault class]->instance_size < ((Class)self)->instance_size) { #endif [fault autorelease]; [NSException raise:NSInvalidArgumentException format: @"Instances from class %@ must be at least %d in size " @"to fault", NSStringFromClass([fault class]), #if defined(APPLE_RUNTIME) || defined(__GNUSTEP_RUNTIME__) || (__GNU_LIBOBJC__ >= 20100911) (int)class_getInstanceSize([self class])]; #else ((Class)self)->instance_size]; #endif } fault->faultResolver = [[EOObjectFault alloc] initWithPrimaryKey:key entity:entity databaseChannel:channel zone:zone targetClass:object_getClass(fault)]; object_setClass(fault, self); return (EODatabaseFault *)AUTORELEASE(fault); } + (NSArray*)arrayFaultWithQualifier:(EOSQLQualifier*)qualifier fetchOrder:(NSArray*)fetchOrder databaseChannel:(EODatabaseChannel*)channel zone:(NSZone*)zone { return [EOArrayProxy arrayProxyWithQualifier:qualifier fetchOrder:fetchOrder channel:channel]; #if 0 EODatabaseFault* fault; fault = [NSMutableArray allocWithZone:zone]; if ([fault class]->instance_size < ((Class)(self))->instance_size) { (void)AUTORELEASE(fault); THROW([[InvalidArgumentException alloc] initWithFormat: @"Instances from class %s must be at least %d " @"in size to fault", NSStringFromClass([fault class]), ((Class)self)->instance_size]); } fault->faultResolver = [[EOArrayFault alloc] initWithQualifier:qualifier fetchOrder:fetchOrder databaseChannel:channel zone:zone targetClass:fault->isa fault:fault]; fault->isa = self; return (NSArray*)AUTORELEASE(fault); #endif } // no more garbage collecting + (NSArray *)gcArrayFaultWithQualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder databaseChannel:(EODatabaseChannel *)channel zone:(NSZone *)zone { EODatabaseFault *fault; fault = (EODatabaseFault*)[NSMutableArray allocWithZone:zone]; #if defined(APPLE_RUNTIME) || defined(__GNUSTEP_RUNTIME__) || (__GNU_LIBOBJC__ >= 20100911) if (class_getInstanceSize([fault class]) < class_getInstanceSize([self class])) { #else if ([fault class]->instance_size < ((Class)(self))->instance_size) { #endif (void)[fault autorelease]; [NSException raise:NSInvalidArgumentException format: @"Instances from class %@ must be at least %d " @"in size to fault", NSStringFromClass([fault class]), #if defined(APPLE_RUNTIME) || defined(__GNUSTEP_RUNTIME__) || (__GNU_LIBOBJC__ >= 20100911) (int)class_getInstanceSize([self class])]; #else ((Class)self)->instance_size]; #endif } fault->faultResolver = [[EOArrayFault alloc] initWithQualifier:qualifier fetchOrder:fetchOrder databaseChannel:channel zone:zone targetClass:object_getClass(fault)]; object_setClass(fault, self); return (NSArray *)AUTORELEASE(fault); } + (NSDictionary *)primaryKeyForFault:(id)fault { EODatabaseFault *aFault = (EODatabaseFault *)fault; // Check that argument is fault if (object_getClass(aFault) != self) return nil; return [(EODatabaseFaultResolver *)aFault->faultResolver primaryKey]; } + (EOEntity *)entityForFault:(id)fault { EODatabaseFault *aFault = (EODatabaseFault *)fault; // Check that argument is fault if (object_getClass(aFault) != self) return nil; return [(EODatabaseFaultResolver *)aFault->faultResolver entity]; } + (EOSQLQualifier *)qualifierForFault:(id)fault { EODatabaseFault *aFault = (EODatabaseFault *)fault; // Check that argument is fault if (object_getClass(aFault) != self) return nil; return [(EODatabaseFaultResolver *)aFault->faultResolver qualifier]; } + (NSArray *)fetchOrderForFault:(id)fault { EODatabaseFault *aFault = (EODatabaseFault *)fault; // Check that argument is fault if (object_getClass(aFault) != self) return nil; return [(EODatabaseFaultResolver *)aFault->faultResolver fetchOrder]; } + (EODatabaseChannel *)databaseChannelForFault:fault { EODatabaseFault *aFault = (EODatabaseFault *)fault; // Check that argument is fault if (object_getClass(aFault) != self) return nil; return [(EODatabaseFaultResolver *)aFault->faultResolver databaseChannel]; } - (void)dealloc { [EODatabase forgetObject:self]; [super dealloc]; } // Forwarding stuff + (void)initialize { // Must be here as initialize is called for each root class // without asking if it responds to it ! } - (EOEntity *)entity { return [EODatabaseFault entityForFault:self]; } @end /* EODatabaseFault */ /* * Informal protocol that informs an instance that a to-one * relationship could not be resoved to get data for self. * Its implementation in NSObject raises NSObjectNotAvailableException. */ @implementation NSObject(EOUnableToFaultToOne) - (void)unableToFaultWithPrimaryKey:(NSDictionary*)key entity:(EOEntity*)entity databaseChannel:(EODatabaseChannel*)channel { // TODO - throw exception form derived class [[[ObjectNotAvailableException alloc] initWithFormat:@"cannot fault to-one for primary key %@ entity %@", [key description], [entity name]] raise]; } @end /* NSObject(EOUnableToFaultToOne) */ @implementation EOFault(EOUnableToFaultToOne) - (void)unableToFaultWithPrimaryKey:(NSDictionary*)key entity:(EOEntity *)entity databaseChannel:(EODatabaseChannel*)channel { // TODO - throw exception from derived class [[[ObjectNotAvailableException alloc] initWithFormat:@"cannot fault to-one for primary key %@ entity %@", [key description], [entity name]] raise]; } @end /* EOFault(EOUnableToFaultToOne) */ SOPE/sope-gdl1/GDLAccess/EOQuotedExpression.m0000644000000000000000000000442715004363604017600 0ustar rootroot/* EOQuotedExpression.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #import #import "common.h" #import "EOQuotedExpression.h" @implementation EOQuotedExpression - (id)expressionValueForContext:(id)_context { NSMutableString *result; NSArray *components; id expr; expr = [(EOExpressionArray *)self->expression expressionValueForContext:_context]; components = [expr componentsSeparatedByString:quote]; result = [NSMutableString stringWithCapacity:[expr length] + 10]; [result appendString:quote]; [result appendString:[components componentsJoinedByString:escape]]; [result appendString:quote]; return result; } - (id)initWithExpression:(id)_expression quote:(NSString *)_quote escape:(NSString *)_escape { if ((self = [super init])) { ASSIGN(self->expression, _expression); ASSIGN(self->quote, _quote); ASSIGN(self->escape, _escape); } return self; } - (void)dealloc { RELEASE(self->expression); RELEASE(self->quote); RELEASE(self->escape); [super dealloc]; } // NSCopying - (id)copyWithZone:(NSZone*)zone { return [[[self class] allocWithZone:zone] initWithExpression:expression quote:quote escape:escape]; } - (id)copy { return [self copyWithZone:NSDefaultMallocZone()]; } @end /* EOQuotedExpression */ SOPE/sope-gdl1/GDLAccess/EOEntity.h0000644000000000000000000001414515004363604015524 0ustar rootroot/* EOEntity.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: August 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOEntity_h__ #define __EOEntity_h__ #import @class EOModel, EOAttribute, EORelationship; @class EOSQLQualifier, EOExpressionArray; @class NSMutableDictionary; @interface EOEntity : NSObject { NSString *name; NSString *className; NSString *externalName; NSString *externalQuery; NSDictionary *userDictionary; NSArray *primaryKeyAttributeNames; /* sorted array of names */ NSArray *attributesNamesUsedForInsert; NSArray *classPropertyNames; /* Garbage collectable objects */ EOModel *model; /* non-retained */ EOSQLQualifier *qualifier; NSArray *attributes; NSMutableDictionary *attributesByName; NSArray *relationships; NSMutableDictionary *relationshipsByName; // name/EORelationship NSArray *primaryKeyAttributes; NSArray *classProperties; // EOAttribute/EORelationship NSArray *attributesUsedForLocking; /* Cached properties */ NSArray *attributesUsedForInsert; // cache from classProperties NSArray *attributesUsedForFetch; // cache from classProperties NSArray *relationsUsedForFetch; // cache from classProperties struct { BOOL isReadOnly:1; BOOL createsMutableObjects:1; BOOL isPropertiesCacheValid:1; } flags; } /* Initializing instances */ - (id)initWithName:(NSString *)name; /* Accessing the name */ - (NSString *)name; - (BOOL)setName:(NSString *)name; + (BOOL)isValidName:(NSString *)name; /* Accessing the model */ - (void)setModel:(EOModel *)model; - (EOModel *)model; - (void)resetModel; - (BOOL)hasModel; /* Getting the qualifier */ - (EOSQLQualifier *)qualifier; /* Accessing attributes */ - (BOOL)addAttribute:(EOAttribute *)attribute; - (void)removeAttributeNamed:(NSString *)name; - (EOAttribute *)attributeNamed:(NSString *)attributeName; - (NSArray *)attributes; /* Accessing relationships */ - (BOOL)addRelationship:(EORelationship *)relationship; - (void)removeRelationshipNamed:(NSString *)name; - (EORelationship *)relationshipNamed:(NSString *)relationshipName; - (NSArray *)relationships; /* Accessing primary key attributes */ - (BOOL)setPrimaryKeyAttributes:(NSArray *)keys; - (NSArray *)primaryKeyAttributes; - (NSArray *)primaryKeyAttributeNames; - (BOOL)isValidPrimaryKeyAttribute:(EOAttribute *)anAttribute; /* Getting primary keys and snapshot for row */ - (NSDictionary *)primaryKeyForRow:(NSDictionary *)row; - (NSDictionary *)snapshotForRow:(NSDictionary *)aRow; /* Getting attributes used for fetch/insert/update operations */ - (NSArray *)attributesUsedForInsert; - (NSArray *)attributesUsedForFetch; - (NSArray *)relationsUsedForFetch; - (NSArray *)attributesNamesUsedForInsert; /* Accessing class properties */ - (BOOL)setClassProperties:(NSArray *)properties; - (NSArray *)classProperties; - (NSArray *)classPropertyNames; - (BOOL)isValidClassProperty:(id)aProp; - (id)propertyNamed:(NSString *)name; - (NSArray *)relationshipsNamed:(NSString *)_relationshipPath; /* Accessing locking attributes */ - (BOOL)setAttributesUsedForLocking:(NSArray *)attributes; - (NSArray *)attributesUsedForLocking; - (BOOL)isValidAttributeUsedForLocking:(EOAttribute *)anAttribute; /* Accessing the enterprise object class */ - (void)setClassName:(NSString *)name; - (NSString *)className; /* Accessing external information */ - (void)setExternalName:(NSString *)name; - (NSString *)externalName; /* Accessing the external query */ - (void)setExternalQuery:(NSString *)query; - (NSString *)externalQuery; /* Accessing read-only status */ - (void)setReadOnly:(BOOL)flag; - (BOOL)isReadOnly; /* Accessing the user dictionary */ - (void)setUserDictionary:(NSDictionary *)dictionary; - (NSDictionary *)userDictionary; - (BOOL)referencesProperty:property; @end @interface EOEntity (EOEntityPrivate) + (EOEntity *)entityFromPropertyList:(id)propertyList model:(EOModel *)model; - (void)replaceStringsWithObjects; - (id)propertyList; - (void)setCreateMutableObjects:(BOOL)flag; - (BOOL)createsMutableObjects; - (void)validatePropertiesCache; - (void)invalidatePropertiesCache; @end @interface EOEntity(ValuesConversion) - (NSDictionary *)convertValuesToModel:(NSDictionary *)aRow; @end /* EOAttribute (ValuesConversion) */ @class EOGlobalID, EOFetchSpecification; @interface EOEntity(EOF2Additions) - (BOOL)isAbstractEntity; /* ids */ - (EOGlobalID *)globalIDForRow:(NSDictionary *)_row; - (BOOL)isPrimaryKeyValidInObject:(id)_object; /* refs to other models */ - (NSArray *)externalModelsReferenced; /* fetch specs */ - (EOFetchSpecification *)fetchSpecificationNamed:(NSString *)_name; - (NSArray *)fetchSpecificationNames; /* names */ - (void)beautifyName; @end @class NSMutableDictionary; @interface EOEntity(PropertyListCoding) - (void)encodeIntoPropertyList:(NSMutableDictionary *)_plist; @end #import @interface EOEntityClassDescription : EOClassDescription { EOEntity *entity; } - (id)initWithEntity:(EOEntity *)_entity; - (EOEntity *)entity; @end #endif /* __EOEntity_h__ */ SOPE/sope-gdl1/GDLAccess/EOModel.h0000644000000000000000000000652515004363604015313 0ustar rootroot/* EOModel.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: August 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOModel_h__ #define __EOModel_h__ #import @class EOEntity; @interface EOModel : NSObject { NSString *name; NSString *path; NSString *adaptorName; NSString *adaptorClassName; NSDictionary *connectionDictionary; NSDictionary *pkeyGeneratorDictionary; NSDictionary *userDictionary; NSArray *entities; // values with EOEntities NSMutableDictionary *entitiesByName; // name/value with EOEntity NSMutableDictionary *entitiesByClassName; // class name/value with EOEntity struct { BOOL createsMutableObjects:1; BOOL errors:1; } flags; } /* Searching for a model file */ + (NSString*)findPathForModelNamed:(NSString*)name; /* Initializing instances */ - (id)initWithContentsOfFile:(NSString*)filename; - (id)initWithPropertyList:propertyList; - (id)initWithName:(NSString*)name; /* Getting the filename */ - (NSString*)path; /* Getting a property list representation */ - (id)modelAsPropertyList; /* Getting the name */ - (NSString*)name; /* Using entities */ - (BOOL)addEntity:(EOEntity *)entity; - (void)removeEntityNamed:(NSString *)name; - (EOEntity *)entityNamed:(NSString *)name; - (NSArray *)entities; /* Checking references */ - (NSArray *)referencesToProperty:(id)property; /* Getting an object's entity */ - (EOEntity *)entityForObject:(id)object; /* Adding model information */ - (BOOL)incorporateModel:(EOModel *)model; /* Accessing the adaptor bundle */ - (void)setAdaptorName:(NSString *)adaptorName; - (NSString *)adaptorName; /* Setting and getting the adaptor class name. */ - (void)setAdaptorClassName:(NSString *)adaptorClassName; - (NSString *)adaptorClassName; /* Accessing the connection dictionary */ - (void)setConnectionDictionary:(NSDictionary *)connectionDictionary; - (NSDictionary *)connectionDictionary; /* Accessing the pkey generator dictionary */ - (void)setPkeyGeneratorDictionary:(NSDictionary *)connectionDictionary; - (NSDictionary *)pkeyGeneratorDictionary; /* Accessing the user dictionary */ - (void)setUserDictionary:(NSDictionary *)dictionary; - (NSDictionary *)userDictionary; @end @interface EOModel (EOModelPrivate) - (void)setCreateMutableObjects:(BOOL)flag; - (BOOL)createsMutableObjects; - (void)errorInReading; @end /* EOModel (EOModelPrivate) */ @interface EOModel(NewInEOF2) - (void)loadAllModelObjects; @end #endif /* __EOModel_h__ */ SOPE/sope-gdl1/GDLAccess/EOAdaptor.m0000644000000000000000000003167515004363604015656 0ustar rootroot/* EOAttributeOrdering.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOAdaptor.h" #include "EOAdaptorChannel.h" #include "EOAdaptorContext.h" #include "EOAttribute.h" #include "EOFExceptions.h" #include "EOModel.h" #include "EOSQLExpression.h" #include "NGExtensions/NSException+misc.h" #include "common.h" @implementation EOAdaptor + (id)adaptorWithModel:(EOModel*)_model { /* Check first to see if the adaptor class exists in the running program by testing the existence of [_model adaptorClassName]. */ NSString *adaptorName = [_model adaptorName]; Class adaptorClass = NSClassFromString([_model adaptorClassName]); id adaptor; adaptor = adaptorClass ? AUTORELEASE([[adaptorClass alloc] initWithName:adaptorName]) : [self adaptorWithName:adaptorName]; [adaptor setModel:_model]; return adaptor; } + (NSArray *)adaptorSearchPathes { // TODO: add support for Cocoa static NSArray *searchPathes = nil; NSMutableArray *ma; id tmp; if (searchPathes != nil) return searchPathes; ma = [NSMutableArray arrayWithCapacity:8]; #if GNUSTEP_BASE_LIBRARY NSEnumerator *libraryPaths; NSString *directory, *suffix; suffix = [self libraryDriversSubDir]; libraryPaths = [NSStandardLibraryPaths() objectEnumerator]; while ((directory = [libraryPaths nextObject])) [ma addObject: [directory stringByAppendingPathComponent: suffix]]; #else NSDictionary *env; env = [[NSProcessInfo processInfo] environment]; if ((tmp = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"]) == nil) tmp = [env objectForKey:@"GNUSTEP_PATHLIST"]; tmp = [tmp componentsSeparatedByString:@":"]; if ([tmp count] > 0) { NSEnumerator *e; e = [tmp objectEnumerator]; while ((tmp = [e nextObject])) { if (![tmp hasSuffix:@"/"]) tmp = [tmp stringByAppendingString:@"/"]; tmp = [tmp stringByAppendingFormat:@"Library/GDLAdaptors-%i.%i", GDL_MAJOR_VERSION, GDL_MINOR_VERSION]; if ([ma containsObject:tmp] || tmp == nil) continue; [ma addObject:tmp]; } } #endif tmp = [NSString stringWithFormat: #ifdef CGS_LIBDIR_NAME [CGS_LIBDIR_NAME stringByAppendingString:@"/sope-%i.%i/dbadaptors"], #else @"/lib/sope-%i.%i/dbadaptors", #endif SOPE_MAJOR_VERSION, SOPE_MINOR_VERSION]; #ifdef FHS_INSTALL_ROOT [ma addObject:[FHS_INSTALL_ROOT stringByAppendingPathComponent:tmp]]; #endif [ma addObject:[@"/usr/local/" stringByAppendingString:tmp]]; [ma addObject:[@"/usr/" stringByAppendingString:tmp]]; searchPathes = [ma copy]; if ([searchPathes count] == 0) NSLog(@"%s: empty library search path !", __PRETTY_FUNCTION__); return searchPathes; } + (id)adaptorWithName:(NSString *)adaptorName { int i, count; NSBundle *bundle; NSString *adaptorBundlePath = nil; Class adaptorClass = Nil; bundle = [NSBundle mainBundle]; /* Check error */ if ((adaptorName == nil) || [adaptorName isEqual:@""]) return nil; /* Look in application bundle */ bundle = [NSBundle mainBundle]; adaptorBundlePath = [bundle pathForResource:adaptorName ofType:@"gdladaptor"]; /* Look in standard paths */ if (adaptorBundlePath == nil) { NSFileManager *fm; NSString *dirname; NSArray *paths; fm = [NSFileManager defaultManager]; paths = [self adaptorSearchPathes]; dirname = [adaptorName stringByAppendingPathExtension:@"gdladaptor"]; /* Loop through the paths and check each one */ for (i = 0, count = [paths count]; i < count; i++) { NSString *p; BOOL isDir; p = [[paths objectAtIndex:i] stringByAppendingPathComponent:dirname]; if (![fm fileExistsAtPath:p isDirectory:&isDir]) continue; if (!isDir) continue; adaptorBundlePath = p; break; } } /* Make adaptor bundle */ bundle = adaptorBundlePath ? [NSBundle bundleWithPath:adaptorBundlePath] : (NSBundle *)nil; /* Check bundle */ if (bundle == nil) { NSLog(@"EOAdaptor: cannot find adaptor bundle: '%@'", adaptorName); #if 0 [[[[CannotFindAdaptorBundleException alloc] initWithFormat:@"Cannot find adaptor bundle '%@'", adaptorName] autorelease] raise]; #endif return nil; } /* load bundle */ if (![bundle load]) { NSLog(@"Cannot load adaptor bundle '%@'", adaptorName); #if 1 [[[[InvalidAdaptorBundleException alloc] initWithFormat:@"Cannot load adaptor bundle '%@'", adaptorName] autorelease] raise]; #endif return nil; } /* Get the adaptor bundle "infoDictionary", and pricipal class, ie. the adaptor class. Other info about the adaptor should be put in the bundle's "Info.plist" file (property list format - see NSBundle class documentation for details about reserved keys in this dictionary property list containing one entry whose key is adaptorClassName. It identifies the actual adaptor class from the bundle. */ adaptorClass = [bundle principalClass]; if (adaptorClass == Nil) { NSLog(@"The adaptor bundle '%@' at '%@' doesn't contain " @"a principal class (infoDict=%@)", adaptorName, [bundle bundlePath], [bundle infoDictionary]); [[[InvalidAdaptorBundleException alloc] initWithFormat:@"The adaptor bundle '%@' doesn't contain " @"a principal class (infoDict=%@)", adaptorName, [bundle infoDictionary]] raise]; } return AUTORELEASE([[adaptorClass alloc] initWithName:adaptorName]); } + (NSString *)adaptorNameForURLScheme:(NSString *)_scheme { // TODO: map scheme to adaptors (eg 'postgresql://' to PostgreSQL // TODO: hack in some known names if ([_scheme isEqualToString:@"postgresql"]) return @"PostgreSQL"; if ([_scheme isEqualToString:@"sybase"]) return @"Sybase10"; if ([_scheme isEqualToString:@"sqlite"]) return @"SQLite3"; if ([_scheme isEqualToString:@"oracle"]) return @"Oracle8"; if ([_scheme isEqualToString:@"mysql"]) return @"MySQL"; if ([_scheme isEqualToString:@"http"]) { NSLog(@"WARNING(%s): asked for 'http' URL, " @"please fix the URLs to 'postgresql'!", __PRETTY_FUNCTION__); return @"PostgreSQL"; } return _scheme; } + (NSString *)libraryDriversSubDir { return [NSString stringWithFormat:@"GDLAdaptors-%i.%i", GDL_MAJOR_VERSION, GDL_MINOR_VERSION]; } - (NSDictionary *)connectionDictionaryForNSURL:(NSURL *)_url { /* "Database URLs" We use the schema: postgresql://[user]:[password]@[host]:[port]/[dbname]/[tablename] */ NSMutableDictionary *md; id tmp; md = [NSMutableDictionary dictionaryWithCapacity:8]; if ((tmp = [_url host]) != nil) [md setObject:tmp forKey:@"hostName"]; if ((tmp = [_url port]) != nil) [md setObject:tmp forKey:@"port"]; if ((tmp = [_url user]) != nil) [md setObject:tmp forKey:@"userName"]; if ((tmp = [_url password]) != nil) [md setObject:tmp forKey:@"password"]; /* extract dbname */ tmp = [_url path]; if ([tmp hasPrefix:@"/"]) tmp = [tmp substringFromIndex:1]; if ([tmp length] > 0) { NSRange r; r = [tmp rangeOfString:@"/"]; if (r.length > 0) tmp = [tmp substringToIndex:r.location]; if ([tmp length] > 0) [md setObject:tmp forKey:@"databaseName"]; } return md; } + (id)adaptorForNSURL:(NSURL *)_url { EOAdaptor *adaptor; NSString *adaptorName; NSDictionary *condict; if (_url == nil) return nil; adaptorName = [self adaptorNameForURLScheme:[_url scheme]]; adaptor = [self adaptorWithName:adaptorName]; if ((condict = [adaptor connectionDictionaryForNSURL:_url]) != nil) [adaptor setConnectionDictionary:condict]; return adaptor; } + (id)adaptorForURL:(id)_url { NSURL *url; if (_url == nil) return nil; if ([_url isKindOfClass:[NSURL class]]) url = _url; else if ((url = [NSURL URLWithString:[_url stringValue]]) == nil) { NSLog(@"ERROR(%s): could not parse URL: '%@'", __PRETTY_FUNCTION__, _url); return nil; } return [self adaptorForNSURL:url]; } - (id)initWithName:(NSString*)_name { ASSIGN(self->name, _name); self->contexts = [[NSMutableArray allocWithZone:[self zone]] init]; return self; } - (void)dealloc { RELEASE(self->model); RELEASE(self->name); RELEASE(self->connectionDictionary); RELEASE(self->pkeyGeneratorDictionary); RELEASE(self->contexts); [super dealloc]; } /* accessors */ - (void)setConnectionDictionary:(NSDictionary*)_dictionary { if([self hasOpenChannels]) { [NSException raise:NSInvalidArgumentException format:@"Cannot set the connection dictionary " @"while the adaptor is connected!"]; } ASSIGN(self->connectionDictionary, _dictionary); [self->model setConnectionDictionary:_dictionary]; } - (NSDictionary *)connectionDictionary { return self->connectionDictionary; } - (BOOL)hasValidConnectionDictionary { return NO; } - (EOAdaptorContext*)createAdaptorContext { return AUTORELEASE([[[self adaptorContextClass] alloc] initWithAdaptor:self]); } - (NSArray *)contexts { NSMutableArray *ma; unsigned i, count; if ((count = [self->contexts count]) == 0) return nil; ma = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) [ma addObject:[[self->contexts objectAtIndex:i] nonretainedObjectValue]]; return ma; } /* Setting pkey generation info */ - (void)setPkeyGeneratorDictionary:(NSDictionary*)aDictionary { ASSIGN(self->pkeyGeneratorDictionary, aDictionary); [self->model setPkeyGeneratorDictionary:aDictionary]; } - (NSDictionary*)pkeyGeneratorDictionary { return self->pkeyGeneratorDictionary; } // notifications - (void)contextDidInit:aContext { [self->contexts addObject:[NSValue valueWithNonretainedObject:aContext]]; } - (void)contextWillDealloc:aContext { int i; for (i = [contexts count]-1; i >= 0; i--) { if ([[contexts objectAtIndex:i] nonretainedObjectValue] == aContext) { [contexts removeObjectAtIndex:i]; break; } } } - (BOOL)hasOpenChannels { int i; for (i = [contexts count] - 1; i >= 0; i--) { EOAdaptorContext* ctx = [[contexts objectAtIndex:i] nonretainedObjectValue]; if ([ctx hasOpenChannels]) return YES; } return NO; } - (id)formatAttribute:(EOAttribute *)_attribute { return [_attribute expressionValueForContext:nil]; } - (id)formatValue:(id)_value forAttribute:(EOAttribute *)attribute { if (_value == nil) _value = [NSNull null]; return [_value expressionValueForContext:nil]; } - (void)reportError:(NSString*)error { if(delegateWillReportError) { if([delegate adaptor:self willReportError:error] == NO) return; } NSLog(@"%@ adaptor error: %@", name, error); } - (void)setDelegate:(id)_delegate { self->delegate = _delegate; self->delegateWillReportError = [self->delegate respondsToSelector: @selector(adaptor:willReportError:)]; } - (void)setModel:(EOModel *)_model { ASSIGN(self->model, _model); [self setConnectionDictionary:[_model connectionDictionary]]; [self setPkeyGeneratorDictionary:[_model pkeyGeneratorDictionary]]; } - (EOModel *)model { return self->model; } - (NSString *)name { return self->name; } - (Class)expressionClass { return [EOSQLExpression class]; } - (Class)adaptorContextClass { return [EOAdaptorContext class]; } - (Class)adaptorChannelClass { return [EOAdaptorChannel class]; } - (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr { return YES; } - (BOOL)isValidQualifierType:(NSString*)typeName { return NO; } - (id)delegate { return self->delegate; } // description - (NSString *)description { return [NSString stringWithFormat: @"<%@[0x%p]: name=%@ " @"model=%s connection-dict=%s>", NSStringFromClass([self class]), self, [self name], [self model] ? "yes" : "no", [self connectionDictionary] ? "yes" : "no"]; } @end /* EOAdaptor */ @implementation EOAdaptor(EOF2Additions) - (BOOL)canServiceModel:(EOModel *)_model { return YES; } @end SOPE/sope-gdl1/GDLAccess/EODatabase.h0000644000000000000000000001044115004363604015747 0ustar rootroot/* EODatabase.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __eoaccess_EODatabase_h__ #define __eoaccess_EODatabase_h__ #import #import @class NSArray; @class NSMutableArray; @class NSDictionary; @class NSMutableDictionary; @class NSString; @class NSMutableString; @class EOAdaptor; @class EOModel; @class EOEntity; @class EOObjectUniquer; @class EODatabase, EODatabaseContext, EODatabaseChannel; @protocol EOObjectRegistry - (void)forgetObject:(id)anObj; - (id)objectForPrimaryKey:(NSDictionary *)aKey entity:(EOEntity *)anEntity; /* retrieving snapshots and primary keys */ - (NSDictionary *)snapshotForObject:(id)anObj; - (NSDictionary *)primaryKeyForObject:(id)anObj; - (void)primaryKey:(NSDictionary **)aKey andSnapshot:(NSDictionary **)aSnapshot forObject:(id)anObj; /* recording objects */ - (void)recordObject:(id)anObj primaryKey:(NSDictionary *)aKey snapshot:(NSDictionary *)aSnapshot; - (void)recordObject:(id)anObj primaryKey:(NSDictionary *)aKey entity:(EOEntity *)anEntity snapshot:(NSDictionary *)aSnapshot; @end @interface EODatabase : NSObject < EOObjectRegistry > { @private EOAdaptor *adaptor; EOObjectUniquer *objectsDictionary; NSMutableArray *contexts; struct { BOOL isUniquingObjects:1; BOOL isKeepingSnapshots:1; BOOL isLoggingWarnings:1; } flags; } // Initializing new instances - (id)initWithAdaptor:(EOAdaptor *)anAdaptor; - (id)initWithModel:(EOModel *)aModel; // Getting the adaptor - (EOAdaptor*)adaptor; // Getting the database contexts - (id)createContext; - (NSArray*)contexts; // Checking connection status - (BOOL)hasOpenChannels; // Uniquing/snapshotting - (void)setUniquesObjects:(BOOL)yn; - (BOOL)uniquesObjects; - (void)setKeepsSnapshots:(BOOL)yn; - (BOOL)keepsSnapshots; // Handle Objects + (void)forgetObject:(id)anObj; - (void)forgetAllObjects; - (void)forgetAllSnapshots; - (BOOL)isObject:(id)anObj updatedOutsideContext:(EODatabaseContext *)aContext; // Error messages - (BOOL)logsErrorMessages; - (void)setLogsErrorMessages:(BOOL)yn; - (void)reportError:(NSString*)error; - (void)reportErrorFormat:(NSString*)format, ...; - (void)reportErrorFormat:(NSString*)format arguments:(va_list)arguments; @end /* EODatabase */ /* * Methods used by database classes internally */ @interface EODatabase(Private) - (void)contextDidInit:(id)aContext; - (void)contextWillDealloc:(id)aContext; - (EOObjectUniquer*)objectUniquer; @end @class EOGlobalID; extern NSTimeInterval NSDistantPastTimeInterval; @interface EODatabase(EOF2Additions) /* models */ - (NSArray *)models; - (void)addModel:(EOModel *)_model; - (BOOL)addModelIfCompatible:(EOModel *)_model; /* entities */ - (EOEntity *)entityForObject:(id)_object; - (EOEntity *)entityNamed:(NSString *)_name; /* snapshots */ - (void)recordSnapshot:(NSDictionary *)_snapshot forGlobalID:(EOGlobalID *)_gid; - (void)recordSnapshots:(NSDictionary *)_snapshots; - (void)recordSnapshot:(NSArray *)_gids forSourceGlobalID:(EOGlobalID *)_gid relationshipName:(NSString *)_name; - (void)recordToManySnapshots:(NSDictionary *)_snapshots; - (NSDictionary *)snapshotForGlobalID:(EOGlobalID *)_gid after:(NSTimeInterval)_duration; - (NSDictionary *)snapshotForGlobalID:(EOGlobalID *)_gid; - (void)forgetSnapshotsForGlobalIDs:(NSArray *)_gids; - (void)forgetSnapshotsForGlobalID:(EOGlobalID *)_gid; @end #endif /* __eoaccess_EODatabase_h__ */ SOPE/sope-gdl1/GDLAccess/EOAdaptorDataSource.m0000644000000000000000000012662215004363604017626 0ustar rootroot/* EOAdaptorDataSource.m Copyright (C) SKYRIX Software AG and Helge Hess Date: 1999-2005 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* column-names must have small letterso hints: EOPrimaryKeyAttributeNamesHint - name of primary key attributes EOPrimaryKeyAttributesHint - primary key attributes EOFetchResultTimeZone - NSTimeZone object for dates */ #define EOAdaptorDataSource_DEBUG 0 #include #include #include #include "common.h" NSString *EOPrimaryKeyAttributeNamesHint = @"EOPrimaryKeyAttributeNamesHint"; NSString *EOPrimaryKeyAttributesHint = @"EOPrimaryKeyAttributesHint"; NSString *EOFetchResultTimeZone = @"EOFetchResultTimeZoneHint"; @interface NSObject(Private) - (NSString *)newKeyExpression; - (NSArray *)_primaryKeyAttributesForTableName:(NSString *)_entityName channel:(EOAdaptorChannel *)_adChannel; - (NSArray *)_primaryKeyAttributeNamesForTableName:(NSString *)_entityName channel:(EOAdaptorChannel *)_adChannel; @end static EONull *null = nil; @interface EOAdaptorChannel(Internals) - (NSArray *)_sortAttributesForSelectExpression:(NSArray *)_attrs; @end /* EOAdaptorChannel(Internals) */ @interface EOQualifier(SqlExpression) - (NSString *)sqlExpressionWithAdaptor:(EOAdaptor *)_adaptor attributes:(NSArray *)_attrs; @end /* EOQualifier(SqlExpression) */ @interface EOAdaptorDataSource(Private) - (NSMutableString *)_selectListWithChannel:(EOAdaptorChannel *)_adChan; - (NSString *)_whereExprWithChannel:(EOAdaptorChannel *)_adChan; - (NSString *)_whereClauseForGlobaID:(EOKeyGlobalID *)_gid adaptor:(EOAdaptor *)_adaptor channel:(EOAdaptorChannel *)_adChan; - (NSString *)_orderByExprForAttributes:(NSArray *)_attrs andPatchSelectList:(NSMutableString *)selectList withChannel:(EOAdaptorChannel *)_adChan; - (NSDictionary *)_mapAttrsWithValues:(NSDictionary *)_keyValues tableName:(NSString *)_tableName channel:(EOAdaptorChannel *)_adChan; @end /* EOAdaptorDataSource(Private) */ @interface EOAdaptorDataSource(Internals) - (id)initWithAdaptorChannel:(EOAdaptorChannel *)_channel connectionDictionary:(NSDictionary *)_connDict; @end /* EOAdaptorDataSource(Internals) */ @interface EODataSource(Notificiations) - (void)postDataSourceChangedNotification; @end @implementation EOAdaptorDataSource static Class NSCalendarDateClass = nil; static NSNotificationCenter *nc = nil; static NSNotificationCenter *getNC(void ) { if (nc == nil) nc = [[NSNotificationCenter defaultCenter] retain]; return nc; } + (void)initialize { null = [[EONull null] retain]; NSCalendarDateClass = [NSCalendarDate class]; } - (id)initWithAdaptorName:(NSString *)_adName connectionDictionary:(NSDictionary *)_dict primaryKeyGenerationDictionary:(NSDictionary *)_pkGen { EOAdaptor *ad = nil; EOAdaptorContext *ctx = nil; EOAdaptorChannel *adc = nil; ad = [EOAdaptor adaptorWithName:_adName]; [ad setConnectionDictionary:_dict]; [ad setPkeyGeneratorDictionary:_pkGen]; ctx = [ad createAdaptorContext]; adc = [ctx createAdaptorChannel]; return [self initWithAdaptorChannel:adc connectionDictionary:_dict]; } - (id)initWithAdaptorChannel:(EOAdaptorChannel *)_channel { return [self initWithAdaptorChannel:_channel connectionDictionary:nil]; } - (id)initWithAdaptorChannel:(EOAdaptorChannel *)_channel connectionDictionary:(NSDictionary *)_connDict { if ((self = [super init])) { self->adChannel = [_channel retain]; self->connectionDictionary = [_connDict copy]; self->commitTransaction = NO; [getNC() addObserver:self selector:@selector(_adDataSourceChanged:) name:@"EOAdaptorDataSourceChanged" object:nil]; } return self; } - (void)dealloc { [getNC() removeObserver:self]; [self->fetchSpecification release]; [self->connectionDictionary release]; [self->adChannel release]; [self->__attributes release]; [self->__qualifier release]; [super dealloc]; } /* notifications */ - (void)postDataSourceItselfChangedNotification { [super postDataSourceChangedNotification]; } - (void)postDataSourceChangedNotification { [getNC() postNotificationName:@"EOAdaptorDataSourceChanged" object:self]; [self postDataSourceItselfChangedNotification]; } - (void)_adDataSourceChanged:(NSNotification *)_notification { EOAdaptorDataSource *ads; if ((ads = [_notification object]) == self) return; if (ads == nil) return; [self postDataSourceItselfChangedNotification]; #if 0 if (![ads->connectionDictionary isEqual:self->connectionDictionary]) /* different database ... */ return; if ((ads->fetchSpecification == nil) || (self->fetchSpecification == nil)) { [self postDataSourceChangedNotification]; return; } /* check fspecs for entity ... */ if ([[ads->fetchSpecification entityName] isEqualToString: [self->fetchSpecification entityName]]) { [self postDataSourceChangedNotification]; return; } #endif } /* fetching */ - (EOAdaptorChannel *)beginTransaction { EOAdaptorContext *ctx = nil; [self openChannel]; ctx = [self->adChannel adaptorContext]; if ([ctx hasOpenTransaction] == NO) { [ctx beginTransaction]; self->commitTransaction = YES; } return self->adChannel; } - (void)commitTransaction { if (self->commitTransaction) { [[self->adChannel adaptorContext] commitTransaction]; // [self->adChannel closeChannel]; self->commitTransaction = NO; } } - (void)rollbackTransaction { [[self->adChannel adaptorContext] rollbackTransaction]; // [self->adChannel closeChannel]; self->commitTransaction = NO; } - (void)openChannel { if (![self->adChannel isOpen]) { [self->adChannel openChannel]; } } - (void)closeChannel { if (![self->adChannel isOpen]) return; if ([[self->adChannel adaptorContext] transactionNestingLevel]) { NSLog(@"%s was called while transaction in progress, rollback will called", __PRETTY_FUNCTION__); [self rollbackTransaction]; } [self->adChannel closeChannel]; } - (NSArray *)fetchObjects { // TODO: split up this HUGE method! // TODO: all the SQL gen code should be moved to an appropriate object NSString *entityName = nil; NSString *whereExpr = nil; NSString *orderByExpr = nil; NSMutableString *selectList = nil; NSMutableString *expression = nil; NSMutableArray *result = nil; NSArray *attrs = nil; NSArray *pKeys = nil; EOQualifier *qual = nil; EOAdaptorChannel *adChan = nil; int pKeyCnt = 0; NSTimeZone *tz = nil; BOOL localComTrans; if (self->fetchSpecification == nil) { // TODO: make that a lastException and just return nil [NSException raise:NSInvalidArgumentException format:@"fetchSpecification required for table name"]; return nil; } entityName = [self->fetchSpecification entityName]; if (entityName == nil || [entityName length] == 0) { [NSException raise:NSInvalidArgumentException format:@"missing entity name"]; } localComTrans = [[self->adChannel adaptorContext] hasOpenTransaction] ? NO : YES; adChan = [self beginTransaction]; pKeys = [self _primaryKeyAttributeNamesForTableName:entityName channel:adChan]; if ((pKeyCnt = [pKeys count]) == 0) { NSLog(@"ERROR[%s]: missing primary keys for table %@", __PRETTY_FUNCTION__, entityName); return nil; } qual = [self->fetchSpecification qualifier]; if (qual == nil) qual = [EOQualifier qualifierWithQualifierFormat:@"1=1"]; ASSIGN(self->__qualifier, qual); attrs = [adChan attributesForTableName:entityName]; if (attrs == nil) { RELEASE(self->__qualifier); self->__qualifier = nil; NSLog(@"ERROR[%s]: could not find table '%@' in database.", __PRETTY_FUNCTION__, entityName); [self rollbackTransaction]; return nil; } if ([attrs count] == 0) { RELEASE(self->__qualifier); self->__qualifier = nil; NSLog(@"ERROR[%s]: missing columns in table '%@'.", __PRETTY_FUNCTION__, entityName); [self rollbackTransaction]; return nil; } tz = [[self->fetchSpecification hints] objectForKey:EOFetchResultTimeZone]; ASSIGN(self->__attributes, attrs); { NSArray *a; NSSet *tableKeys = nil; NSSet *qualifierKeys = nil; a = [[[qual allQualifierKeys] allObjects] map:@selector(lowercaseString)]; qualifierKeys = [[NSSet alloc] initWithArray:a]; a = [[attrs map:@selector(columnName)] map:@selector(lowercaseString)]; tableKeys = [[NSSet alloc] initWithArray:a]; if ([qualifierKeys isSubsetOfSet:tableKeys] == NO) { NSString *format = nil; format = [NSString stringWithFormat: @"EOAdaptorDataSource: using unmapped key in " @"qualifier tableKeys <%@> qualifierKeys <%@> " @"qualifier <%@>", tableKeys, qualifierKeys, qual]; RELEASE(self->__attributes); self->__attributes = nil; RELEASE(self->__qualifier); self->__qualifier = nil; RELEASE(tableKeys); tableKeys = nil; [self rollbackTransaction]; [[[InvalidQualifierException alloc] initWithFormat:format] raise]; } RELEASE(tableKeys); tableKeys = nil; RELEASE(qualifierKeys); qualifierKeys = nil; } whereExpr = [self _whereExprWithChannel:adChan]; selectList = [self _selectListWithChannel:adChan]; orderByExpr = [self _orderByExprForAttributes:attrs andPatchSelectList:selectList withChannel:adChan]; expression = [[NSMutableString alloc] initWithCapacity:256]; [expression appendString:@"SELECT "]; if ([self->fetchSpecification usesDistinct]) [expression appendString:@"DISTINCT "]; [expression appendString:selectList]; [expression appendString:@" FROM "]; [expression appendString:entityName]; if ([whereExpr length] > 0) { [expression appendString:@" WHERE "]; [expression appendString:whereExpr]; } if (orderByExpr != nil && [orderByExpr length] > 0) { [expression appendString:@" ORDER BY "]; [expression appendString:orderByExpr]; } if (![adChan evaluateExpression:expression]) { RELEASE(self->__attributes); self->__attributes = nil; RELEASE(self->__qualifier); self->__qualifier = nil; AUTORELEASE(expression); [adChan cancelFetch]; [self rollbackTransaction]; [[[EOAdaptorException alloc] initWithFormat:@"evaluateExpression of %@ failed", expression] raise]; } result = [NSMutableArray arrayWithCapacity:64]; { NSMutableDictionary *row = nil; unsigned fetchCnt = 0; unsigned fetchLimit = 0; unsigned attrCnt = 0; id *values = NULL; id *keys = NULL; /* Note: those are reused in the inner loop */ attrCnt = [attrs count]; values = calloc(attrCnt + 2, sizeof(id)); keys = calloc(attrCnt + 2, sizeof(id)); fetchLimit = [self->fetchSpecification fetchLimit]; while ((row = [adChan fetchAttributes:attrs withZone:NULL]) != nil) { NSEnumerator *enumerator = nil; id attr = nil; int rowCnt = 0; NSDictionary *r = nil; id *pKeyVs = NULL; int pKeyVCnt = 0; pKeyVs = calloc(pKeyCnt, sizeof(id)); enumerator = [attrs objectEnumerator]; while ((attr = [enumerator nextObject]) != nil) { id obj; NSString *cn; obj = [row objectForKey:[(EOAttribute *)attr name]]; if (obj == nil) continue; if (tz != nil && [obj isKindOfClass:NSCalendarDateClass]) [obj setTimeZone:tz]; cn = [[attr columnName] lowercaseString]; values[rowCnt] = obj; keys[rowCnt] = cn; rowCnt++; if ([pKeys containsObject:cn]) { int idx; idx = [pKeys indexOfObject:cn]; NSAssert4(idx <= (pKeyCnt - 1) && pKeyVs[idx] == nil, @"internal inconsistency in EOAdaptorDataSource " @"while fetch idx[%d] > (pKeyCnt - 1)[%d] " @"pKeyVs[idx] (%@[%d]);", idx, (pKeyCnt - 1), pKeyVs[idx], idx); pKeyVs[idx] = obj; pKeyVCnt++; } } if (pKeyCnt != pKeyVCnt) NSAssert(NO, @"internal inconsistency in EOAdaptorDataSource " @"while fetch"); { EOGlobalID *gid; gid = [EOKeyGlobalID globalIDWithEntityName:entityName keys:pKeyVs keyCount:pKeyVCnt zone:NULL]; if (self->connectionDictionary) { gid = [[EOAdaptorGlobalID alloc] initWithGlobalID:gid connectionDictionary: self->connectionDictionary]; AUTORELEASE(gid); } values[rowCnt] = gid; keys[rowCnt] = @"globalID"; rowCnt++; } fetchCnt++; r = [[NSMutableDictionary alloc] initWithObjects:values forKeys:keys count:rowCnt]; [result addObject:r]; [r release]; r = nil; if (pKeyVs) free(pKeyVs); pKeyVs = NULL; if (fetchLimit == fetchCnt) break; } if (values) free(values); values = NULL; if (keys) free(keys); keys = NULL; } [adChan cancelFetch]; if (localComTrans) [self commitTransaction]; [expression release]; expression = nil; [self->__qualifier release]; self->__qualifier = nil; [self->__attributes release]; self->__attributes = nil; return result; } - (id)createObject { return [NSMutableDictionary dictionary]; } - (void)insertObject:(id)_obj { NSString *key = nil; NSString *tableName = nil; NSMutableString *expression = nil; EOAdaptor *adaptor = nil; NSArray *pKeys = nil; id obj = nil; EOAdaptorChannel *adChan = nil; int oVCnt = 0; NSString **objectKeyAttrValue = NULL; NSEnumerator *enumerator = nil; id pKey = nil; BOOL localComTrans; if ([[self->adChannel adaptorContext] hasOpenTransaction]) localComTrans = NO; else localComTrans = YES; adChan = [self beginTransaction]; adaptor = [[adChan adaptorContext] adaptor]; if ((tableName = [self->fetchSpecification entityName]) == nil) { [self rollbackTransaction]; [NSException raise:NSInvalidArgumentException format:@"couldn`t insert obj %@ missing entityName in " @"fetchSpecification", _obj]; } /* create or apply primary keys */ #if EOAdaptorDataSource_DEBUG NSLog(@"insert obj %@", _obj); #endif pKeys = [self _primaryKeyAttributeNamesForTableName:tableName channel:adChan]; #if EOAdaptorDataSource_DEBUG NSLog(@"got primary keys %@", pKeys); #endif objectKeyAttrValue = calloc([pKeys count], sizeof(id)); enumerator = [pKeys objectEnumerator]; while ((pKey = [enumerator nextObject])) { id pKeyObj; pKeyObj = [_obj valueForKey:pKey]; #if EOAdaptorDataSource_DEBUG NSLog(@"pk in obj %@:<%@> ", pKey, pKeyObj); #endif if (![pKeyObj isNotNull]) { /* try to build primary key */ NSString *newKeyExpr = nil; NSDictionary *row = nil; #if EOAdaptorDataSource_DEBUG NSLog(@"pKeyObj !isNotNull"); #endif if ([pKeys count] != 1) { [self rollbackTransaction]; [NSException raise:NSInternalInconsistencyException format:@"more than one primary key, " @"and primary key for %@ is not set", pKey]; } if (![adaptor respondsToSelector:@selector(newKeyExpression)]) { [self rollbackTransaction]; [NSException raise:NSInternalInconsistencyException format:@"got no newkey expression, insert failed"]; } newKeyExpr = [(id)adaptor newKeyExpression]; if (newKeyExpr == nil) { [self rollbackTransaction]; [NSException raise:NSInternalInconsistencyException format:@"missing newKeyExpression for adaptor[%@] %@...", NSStringFromClass([adaptor class]), adaptor]; } if (![adChan evaluateExpression:newKeyExpr]) { [adChan cancelFetch]; [self rollbackTransaction]; [[[EOAdaptorException alloc] initWithFormat:@"couldn`t evaluate new key expression %@", newKeyExpr] raise]; } row = [adChan fetchAttributes:[adChan describeResults] withZone:NULL]; [adChan cancelFetch]; if ((key = [[row objectEnumerator] nextObject]) == nil) { [self rollbackTransaction]; [[[EOAdaptorException alloc] initWithFormat:@"couldn`t fetch primary key"] raise];; } objectKeyAttrValue[oVCnt++] = key; [_obj takeValue:key forKey:pKey]; #if EOAdaptorDataSource_DEBUG NSLog(@"_obj %@ after takeValue:%@ forKey:%@", _obj, key, pKey); #endif } else { objectKeyAttrValue[oVCnt++] = pKeyObj; #if EOAdaptorDataSource_DEBUG NSLog(@"objectKeyAttrValue takeValue %@ for idx %d", pKeyObj, oVCnt); #endif } } /* construct SQL INSERT expression .. */ expression = [[NSMutableString alloc] initWithCapacity:256]; [expression appendString:@"INSERT INTO "]; [expression appendString:tableName]; [expression appendString:@"("]; { NSDictionary *objects = nil; NSEnumerator *enumerator = nil; NSArray *allKeys = nil; BOOL isFirst = YES; objects = [self _mapAttrsWithValues:_obj tableName:tableName channel:adChan]; allKeys = [objects allKeys]; enumerator = [allKeys objectEnumerator]; while ((obj = [enumerator nextObject])) { if (isFirst) isFirst = NO; else [expression appendString:@", "]; [expression appendString:[adaptor formatAttribute:obj]]; } [expression appendString:@") VALUES ("]; enumerator = [allKeys objectEnumerator]; isFirst = YES; while ((obj = [enumerator nextObject])) { id value; if (isFirst) isFirst = NO; else [expression appendString:@", "]; value = [objects objectForKey:obj]; if (value == nil) value = null; [expression appendString:[adaptor formatValue:value forAttribute:obj]]; } } [expression appendString:@")"]; /* execute insert in SQL server .. */ if (![adChan evaluateExpression:expression]) { [adChan cancelFetch]; enumerator = [pKeys objectEnumerator]; while ((pKey = [enumerator nextObject])) { [_obj takeValue:[EONull null] forKey:pKey]; } [self rollbackTransaction]; AUTORELEASE(expression); [[[EOAdaptorException alloc] initWithFormat:@"evaluateExpression %@ failed", expression] raise]; } [adChan cancelFetch]; if (localComTrans) [self commitTransaction]; /* construct new global id for record */ { EOGlobalID *gid; gid = [EOKeyGlobalID globalIDWithEntityName:tableName keys:objectKeyAttrValue keyCount:oVCnt zone:NULL]; if (self->connectionDictionary != nil) { EOAdaptorGlobalID *agid = nil; agid = [[EOAdaptorGlobalID alloc] initWithGlobalID:gid connectionDictionary: self->connectionDictionary]; AUTORELEASE(agid); gid = agid; } [_obj takeValue:gid forKey:@"globalID"]; } RELEASE(expression); expression = NULL; /* mark datasource as changed */ [self postDataSourceChangedNotification]; } - (void)updateObject:(id)_obj { NSString *whereClause = nil; NSMutableString *expression = nil; EOAdaptor *adaptor = nil; EOKeyGlobalID *gid = nil; NSEnumerator *enumerator = nil; NSString *tableName = nil; EOAttribute *attr = nil; BOOL isFirst = YES; NSDictionary *objects = nil; EOAdaptorChannel *adChan = nil; BOOL localComTrans; if ((gid = [_obj valueForKey:@"globalID"]) == nil) { [NSException raise:NSInvalidArgumentException format:@"missing globalID, couldn`t update"]; } if ([gid isKindOfClass:[EOAdaptorGlobalID class]]) { NSDictionary *conD = nil; conD = [(EOAdaptorGlobalID *)gid connectionDictionary]; if (![conD isEqualToDictionary:self->connectionDictionary]) { [NSException raise:NSInvalidArgumentException format:@"try to update object %@ in " @"wrong AdaptorDataSource %@", _obj, self]; } gid = (EOKeyGlobalID *)[(EOAdaptorGlobalID *)gid globalID]; } if ([[self->adChannel adaptorContext] hasOpenTransaction]) localComTrans = NO; else localComTrans = YES; adChan = [self beginTransaction]; tableName = [gid entityName]; adaptor = [[adChan adaptorContext] adaptor]; whereClause = [self _whereClauseForGlobaID:gid adaptor:adaptor channel:adChan]; if (whereClause == nil) { [self rollbackTransaction]; return; } expression = [[NSMutableString alloc] initWithCapacity:256]; [expression appendString:@"UPDATE "]; [expression appendString:[gid entityName]]; [expression appendString:@" SET "]; objects = [self _mapAttrsWithValues:_obj tableName:tableName channel:adChan]; enumerator = [objects keyEnumerator]; while ((attr = [enumerator nextObject])) { id value; if (isFirst) isFirst = NO; else [expression appendString:@", "]; [expression appendString:[adaptor formatAttribute:attr]]; [expression appendString:@"="]; value = [objects objectForKey:attr]; if (value == nil) value = null; [expression appendString:[adaptor formatValue:value forAttribute:attr]]; } [expression appendString:@" WHERE "]; [expression appendString:whereClause]; if (![adChan evaluateExpression:expression]) { [adChan cancelFetch]; [self rollbackTransaction]; AUTORELEASE(expression); [[[EOAdaptorException alloc] initWithFormat:@"evaluate expression %@ failed", expression] raise]; } [adChan cancelFetch]; if (localComTrans) [self commitTransaction]; RELEASE(expression); expression = nil; { EOGlobalID *newGID; NSArray *attrs; NSEnumerator *enumerator; id *objs; int objCnt; NSString *attr; attrs = [self _primaryKeyAttributeNamesForTableName:[gid entityName] channel:adChan]; enumerator = [attrs objectEnumerator]; objCnt = 0; objs = calloc([attrs count], sizeof(id)); while ((attr = [enumerator nextObject])) { objs[objCnt] = [_obj valueForKey:attr]; objCnt++; } newGID = [EOKeyGlobalID globalIDWithEntityName:[gid entityName] keys:objs keyCount:objCnt zone:NULL]; if (self->connectionDictionary != nil) { newGID = [[EOAdaptorGlobalID alloc] initWithGlobalID:newGID connectionDictionary: self->connectionDictionary]; [newGID autorelease]; } [(NSMutableDictionary *)_obj setObject:newGID forKey:@"globalID"]; } [self postDataSourceChangedNotification]; } - (void)deleteObject:(id)_obj { NSString *whereClause = nil; NSMutableString *expression = nil; EOKeyGlobalID *gid = nil; EOAdaptorChannel *adChan = nil; BOOL localComTrans; if ((gid = [_obj valueForKey:@"globalID"]) == nil) { [NSException raise:NSInvalidArgumentException format:@"missing globalID, could not delete"]; } if ([gid isKindOfClass:[EOAdaptorGlobalID class]]) { NSDictionary *conD = nil; conD = [(EOAdaptorGlobalID *)gid connectionDictionary]; if (![conD isEqualToDictionary:self->connectionDictionary]) { [NSException raise:NSInvalidArgumentException format:@"try to delete object %@ in wrong " @"AdaptorDataSource %@", _obj, self]; } gid = (EOKeyGlobalID *)[(EOAdaptorGlobalID *)gid globalID]; } if ([[self->adChannel adaptorContext] hasOpenTransaction]) localComTrans = NO; else localComTrans = YES; adChan = [self beginTransaction]; whereClause = [self _whereClauseForGlobaID:gid adaptor:[[adChan adaptorContext] adaptor] channel:adChan]; if (whereClause == nil) { [self rollbackTransaction]; return; } expression = [[NSMutableString alloc] initWithCapacity:256]; [expression appendString:@"DELETE FROM "]; [expression appendString:[gid entityName]]; [expression appendString:@" WHERE "]; [expression appendString:whereClause]; if (![adChan evaluateExpression:expression]) { [adChan cancelFetch]; [self rollbackTransaction]; AUTORELEASE(expression); [[[EOAdaptorException alloc] initWithFormat:@"couldn`t evaluate expression %@ failed", expression] raise]; } [adChan cancelFetch]; if (localComTrans) [self commitTransaction]; RELEASE(expression); expression = nil; [self postDataSourceChangedNotification]; } - (void)setFetchSpecification:(EOFetchSpecification *)_fs { if (![self->fetchSpecification isEqual:_fs]) { #if DEBUG && 0 NSLog(@"%s: 0x%p: fetch-spec mismatch:\n%@\n%@", __PRETTY_FUNCTION__, self, self->fetchSpecification, _fs); #endif ASSIGNCOPY(self->fetchSpecification, _fs); [self postDataSourceItselfChangedNotification]; } #if DEBUG && 0 else { NSLog(@"%s: 0x%p: no fetch-spec mismatch:\n%@\n%@\n", __PRETTY_FUNCTION__, self, self->fetchSpecification, _fs); } #endif } - (EOFetchSpecification *)fetchSpecification { /* Note: the copy is intended, since the fetchspec is mutable, the consumer could otherwise modify it "behind the scenes" */ return [[self->fetchSpecification copy] autorelease]; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<%@[0x%p]:", NSStringFromClass([self class]), self]; if (self->fetchSpecification != nil) [ms appendFormat:@" fspec=%@", self->fetchSpecification]; if (self->adChannel != nil) [ms appendFormat:@" channel=%@", self->adChannel]; [ms appendString:@">"]; return ms; } @end /* EOAdaptorDataSource */ @implementation EOAdaptorDataSource(Private) - (NSArray *)_primaryKeyAttributeNamesForTableName:(NSString *)_entityName channel:(EOAdaptorChannel *)_adChannel { NSDictionary *hints; NSArray *attrs; hints = [self->fetchSpecification hints]; attrs = [hints objectForKey:EOPrimaryKeyAttributeNamesHint]; if (attrs) return attrs; attrs = [hints objectForKey:EOPrimaryKeyAttributesHint]; if (attrs == nil) { if (!(attrs = [_adChannel primaryKeyAttributesForTableName:_entityName])) { attrs = [_adChannel attributesForTableName:_entityName]; } } attrs = [[attrs map:@selector(columnName)] map:@selector(lowercaseString)]; attrs = [attrs sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; return attrs; } - (NSArray *)_primaryKeyAttributesForTableName:(NSString *)_entityName channel:(EOAdaptorChannel *)_adChannel { NSArray *attrs; NSDictionary *hints; hints = [self->fetchSpecification hints]; attrs = [hints objectForKey:EOPrimaryKeyAttributesHint]; if (attrs != nil) return attrs; attrs = [hints objectForKey:EOPrimaryKeyAttributeNamesHint]; if (attrs != nil) { NSArray *allAttrs; NSEnumerator *enumerator; id *objs; int objCnt; id obj; allAttrs = [_adChannel attributesForTableName:_entityName]; objs = malloc(sizeof(id) * [allAttrs count]); enumerator = [allAttrs objectEnumerator]; objCnt = 0; while ((obj = [enumerator nextObject])) { if ([attrs containsObject:[[obj columnName] lowercaseString]]) { objs[objCnt++] = obj; } } attrs = [NSArray arrayWithObjects:objs count:objCnt]; free(objs); objs = NULL; return attrs; } if (!(attrs = [_adChannel primaryKeyAttributesForTableName:_entityName])) { attrs = [_adChannel attributesForTableName:_entityName]; } return attrs; } - (NSString *)_whereExprWithChannel:(EOAdaptorChannel *)_adChan { EOQualifier *qual = nil; NSArray *attrs = nil; NSString *entityName = nil; EOAdaptor *adaptor; entityName = [self->fetchSpecification entityName]; if ((attrs = self->__attributes) == nil) attrs = [_adChan attributesForTableName:entityName]; if ((qual = self->__qualifier) == nil) qual = [self->fetchSpecification qualifier]; if (qual == nil) return nil; adaptor = [[_adChan adaptorContext] adaptor]; return [qual sqlExpressionWithAdaptor:adaptor attributes:attrs]; } - (NSException *)_couldNotFindSortAttributeInAttributes:(NSArray *)_attrs forSortOrdering:(EOSortOrdering *)_so { return [[InvalidAttributeException alloc] initWithFormat:@"could not find EOAttribute for SortOrdering" @" %@ Attributes %@", _so, _attrs]; } - (EOAttribute *)findAttributeForKey:(NSString *)key inAttributes:(NSArray *)_attrs { NSEnumerator *en; EOAttribute *obj; key = [key lowercaseString]; en = [_attrs objectEnumerator]; while ((obj = [en nextObject]) != nil) { if ([[[obj columnName] lowercaseString] isEqualToString:key]) break; } return obj; } - (NSString *)_orderByExprForAttributes:(NSArray *)_attrs andPatchSelectList:(NSMutableString *)selectList withChannel:(EOAdaptorChannel *)_adChan { NSMutableString *orderByExpr; NSEnumerator *enumerator = nil; EOSortOrdering *sortOrdering = nil; int orderCnt = 0; EOAdaptor *adaptor; adaptor = [[_adChan adaptorContext] adaptor]; orderByExpr = nil; enumerator = [[self->fetchSpecification sortOrderings] objectEnumerator]; while ((sortOrdering = [enumerator nextObject]) != nil) { SEL selector = NULL; NSString *key = nil; EOAttribute *keyAttr = nil; int order = 0; /* 0 - not used; 1 - asc; 2 - desc */ BOOL inSensitive = NO; NSString *orderTmp = nil; if (orderByExpr == nil) orderByExpr = [NSMutableString stringWithCapacity:64]; else [orderByExpr appendString:@", "]; if ((selector = [sortOrdering selector])) { if (sel_isEqual(selector, EOCompareAscending)) order = 1; else if (sel_isEqual(selector, EOCompareDescending)) order = 2; else if (sel_isEqual(selector, EOCompareCaseInsensitiveAscending)) { order = 1; inSensitive = YES; } else if (sel_isEqual(selector, EOCompareCaseInsensitiveDescending)) { order = 2; inSensitive = YES; } } key = [sortOrdering key]; if (key == nil || [key length] == 0) { NSLog(@"WARNING[%s]: no key in sortordering %@", __PRETTY_FUNCTION__, key); continue; } { EOAttribute *obj; key = [key lowercaseString]; obj = [self findAttributeForKey:key inAttributes:_attrs]; if (obj == nil) { [self->__attributes release]; self->__attributes = nil; [self->__qualifier release]; self->__qualifier = nil; #if 0 // TODO: memleak in error case [expression release]; expression = nil; #endif [self rollbackTransaction]; [[self _couldNotFindSortAttributeInAttributes:_attrs forSortOrdering:sortOrdering] raise]; return nil; } keyAttr = obj; } key = [adaptor formatAttribute:keyAttr]; orderTmp = [NSString stringWithFormat:@"order%d", orderCnt]; orderCnt++; [orderByExpr appendString:orderTmp]; if (order == 1) [orderByExpr appendString:@" ASC"]; else if (order == 2) [orderByExpr appendString:@" DESC"]; /* manipulate select expr */ if (inSensitive) { if ([[keyAttr valueClassName] isEqualToString:@"NSString"]) { key = [NSString stringWithFormat:@"LOWER(%@)", key]; } else NSLog(@"WARNING[%s]: inSensitive expression for no text attribute", __PRETTY_FUNCTION__); } { NSString *str = nil; str = [key stringByAppendingString:@" AS "]; str = [str stringByAppendingString:orderTmp]; str = [str stringByAppendingString:@", "]; [selectList insertString:str atIndex:0]; } } return orderByExpr; } - (NSMutableString *)_selectListWithChannel:(EOAdaptorChannel *)_adChan { NSArray *attrs = nil; NSEnumerator *enumerator = nil; EOAttribute *attribute = nil; BOOL first = YES; NSMutableString *select = nil; EOAdaptor *adaptor = nil; NSString *entityName = nil; adaptor = [[_adChan adaptorContext] adaptor]; entityName = [self->fetchSpecification entityName]; if ((attrs = self->__attributes) == nil) attrs = [_adChan attributesForTableName:entityName]; attrs = [_adChan _sortAttributesForSelectExpression:attrs]; select = [NSMutableString stringWithCapacity:128]; enumerator = [attrs objectEnumerator]; while ((attribute = [enumerator nextObject])) { if (first) first = NO; else [select appendString:@", "]; [select appendString:[adaptor formatAttribute:attribute]]; } return select; } - (NSString *)_whereClauseForGlobaID:(EOKeyGlobalID *)_gid adaptor:(EOAdaptor *)_adaptor channel:(EOAdaptorChannel *)_adChan { NSEnumerator *enumerator; NSMutableString *result; NSArray *pKeys; NSArray *pkAttrs; NSString *pKey; int pkCnt; pKeys = [self _primaryKeyAttributeNamesForTableName:[_gid entityName] channel:_adChan]; pkAttrs = [self _primaryKeyAttributesForTableName:[_gid entityName] channel:_adChan]; if ([pKeys count] != [_gid keyCount]) { NSLog(@"ERROR[%s]: internal inconsitency pkeys %@ gid %@", __PRETTY_FUNCTION__, pKeys, _gid); return nil; } enumerator = [pKeys objectEnumerator]; pkCnt = 0; result = nil; while ((pKey = [enumerator nextObject])) { EOAttribute *attr; id value; if (result == nil) result = [NSMutableString stringWithCapacity:128]; else [result appendString:@" AND "]; { NSEnumerator *enumerator; enumerator = [pkAttrs objectEnumerator]; while ((attr = [enumerator nextObject])) { if ([[[attr columnName] lowercaseString] isEqual:pKey]) break; } NSAssert2(attr != nil, @"missing attribute for pkName %@ attrs %@", pKey, pkAttrs); } [result appendString:[_adaptor formatAttribute:attr]]; value = [(EOKeyGlobalID *)_gid keyValues][pkCnt++]; if (value == nil) value = null; [result appendString:[value isNotNull] ? @"=" : @" IS "]; [result appendString:[_adaptor formatValue:value forAttribute:attr]]; } return result; } - (NSDictionary *)_mapAttrsWithValues:(NSDictionary *)_keyValues tableName:(NSString *)_tableName channel:(EOAdaptorChannel *)_adChan { id *keys, *values; int mapCnt; NSEnumerator *en; EOAttribute *attr; NSDictionary *result; NSArray *attrs; attrs = [_adChan attributesForTableName:_tableName]; mapCnt = [attrs count]; keys = calloc(mapCnt + 1, sizeof(id)); values = calloc(mapCnt + 1, sizeof(id)); en = [attrs objectEnumerator]; mapCnt = 0; while ((attr = [en nextObject])) { id v; v = (v = [_keyValues valueForKey:[[attr columnName] lowercaseString]]) ? v : (id)null; keys[mapCnt] = attr; values[mapCnt] = v; mapCnt++; } result = [[NSDictionary alloc] initWithObjects:values forKeys:keys count:mapCnt]; free(keys); keys = NULL; free(values); values = NULL; return [result autorelease]; } @end /* EOAdaptorDataSource(Private) */ @implementation EOAndQualifier(SqlExpression) - (NSString *)sqlExpressionWithAdaptor:(EOAdaptor *)_adaptor attributes:(NSArray *)_attributes { NSMutableString *str = nil; NSEnumerator *enumerator = nil; EOQualifier *qual = nil; BOOL isFirst = YES; NSString *result = nil; str = [[NSMutableString alloc] initWithCapacity:128]; enumerator = [self->qualifiers objectEnumerator]; while ((qual = [enumerator nextObject])) { NSString *s; s = [qual sqlExpressionWithAdaptor:_adaptor attributes:_attributes]; if (isFirst) { [str appendFormat:@"(%@)", s]; isFirst = NO; } else [str appendFormat:@" AND (%@)", s]; } result = [str copy]; [str release]; str = nil; return [result autorelease]; } @end /* EOAndQualifier(SqlExpression) */ @implementation EOOrQualifier(SqlExpression) - (NSString *)sqlExpressionWithAdaptor:(EOAdaptor *)_adaptor attributes:(NSArray *)_attributes { NSMutableString *str = nil; NSEnumerator *enumerator = nil; EOQualifier *qual = nil; BOOL isFirst = YES; NSString *result = nil; str = [[NSMutableString alloc] initWithCapacity:128]; enumerator = [self->qualifiers objectEnumerator]; while ((qual = [enumerator nextObject])) { NSString *s; s = [qual sqlExpressionWithAdaptor:_adaptor attributes:_attributes]; if (isFirst) { [str appendFormat:@"(%@)", s]; isFirst = NO; } else [str appendFormat:@" OR (%@)", s]; } result = [str copy]; [str release]; str = nil; return [result autorelease]; } @end /* EOOrQualifier(SqlExpression) */ @implementation EOKeyValueQualifier(SqlExpression) + (NSString *)sqlStringForOperatorSelector:(SEL)_sel { static NSMapTable *selectorToOperator = NULL; NSString *s, *ss; if ((s = NSStringFromSelector(_sel)) == nil) return nil; if (selectorToOperator == NULL) { selectorToOperator = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 10); NSMapInsert(selectorToOperator, NSStringFromSelector(EOQualifierOperatorEqual), @"="); NSMapInsert(selectorToOperator, NSStringFromSelector(EOQualifierOperatorNotEqual), @"<>"); NSMapInsert(selectorToOperator, NSStringFromSelector(EOQualifierOperatorLessThan), @"<"); NSMapInsert(selectorToOperator, NSStringFromSelector(EOQualifierOperatorGreaterThan), @">"); NSMapInsert(selectorToOperator, NSStringFromSelector(EOQualifierOperatorLessThanOrEqualTo), @"<="); NSMapInsert(selectorToOperator, NSStringFromSelector(EOQualifierOperatorGreaterThanOrEqualTo), @">="); } if ((ss = NSMapGet(selectorToOperator, s))) return ss; return nil; } - (NSString *)sqlExpressionWithAdaptor:(EOAdaptor *)_adaptor attributes:(NSArray *)_attributes { EOAttribute *attr = nil; NSEnumerator *en = nil; NSString *k = nil; NSString *sql = nil; NSString *sqlKey, *sqlValue; k = [self->key lowercaseString]; en = [_attributes objectEnumerator]; while ((attr = [en nextObject])) { if ([[[attr columnName] lowercaseString] isEqualToString:k]) { break; } } if (!attr) { en = [_attributes objectEnumerator]; while ((attr = [en nextObject])) { if ([[attr name] isEqualToString:self->key]) break; } } if (!attr) { NSLog(@"WARNING[%s]: missing attribute [%@] for qualifier %@", __PRETTY_FUNCTION__, _attributes, self); return @"1=2"; } sqlKey = [_adaptor formatAttribute:attr]; sqlValue = [_adaptor formatValue:(self->value ? self->value : (id)null) forAttribute:attr]; sql = nil; if (sel_isEqual(EOQualifierOperatorEqual, self->operator)) { if ([self->value isNotNull]) sql = [NSString stringWithFormat:@"%@ = %@", sqlKey, sqlValue]; else sql = [NSString stringWithFormat:@"%@ IS NULL", sqlKey]; } else if (sel_isEqual(EOQualifierOperatorNotEqual, self->operator)) { if ([self->value isNotNull]) sql = [NSString stringWithFormat:@"NOT (%@ = %@)", sqlKey, sqlValue]; else sql = [NSString stringWithFormat:@"%@ IS NOT NULL", sqlKey]; } else if (sel_isEqual(EOQualifierOperatorLessThan, self->operator)) { sql = [NSString stringWithFormat:@"%@ < %@", sqlKey, sqlValue]; } else if (sel_isEqual(EOQualifierOperatorLessThanOrEqualTo, self->operator)) { sql = [NSString stringWithFormat:@"%@ <= %@", sqlKey, sqlValue]; } else if (sel_isEqual(EOQualifierOperatorGreaterThan, self->operator)) { sql = [NSString stringWithFormat:@"%@ > %@", sqlKey, sqlValue]; } else if (sel_isEqual(EOQualifierOperatorGreaterThanOrEqualTo, self->operator)) { sql = [NSString stringWithFormat:@"%@ >= %@", sqlKey, sqlValue]; } else if (sel_isEqual(EOQualifierOperatorLike, self->operator)) { sqlValue = [[self->value stringValue] stringByReplacingString:@"*" withString:@"%"]; sqlValue = [_adaptor formatValue:sqlValue forAttribute:attr]; sql = [NSString stringWithFormat:@"%@ LIKE %@", sqlKey, sqlValue]; } else if (sel_isEqual(EOQualifierOperatorCaseInsensitiveLike, self->operator)) { sqlValue = [[self->value stringValue] stringByReplacingString:@"*" withString:@"%"]; sqlValue = [sqlValue lowercaseString]; sqlValue = [_adaptor formatValue:sqlValue forAttribute:attr]; sql = [NSString stringWithFormat:@"LOWER(%@) LIKE %@", sqlKey, sqlValue]; } #if 0 else if (sel_isEqual(EOQualifierOperatorLessThanOrEqualTo, self->operator)) { } else if (sel_isEqual(EOQualifierOperatorGreaterThanOrEqualTo, self->operator)) { } #endif else { NSLog(@"ERROR(%s): unsupported SQL operator: %@", __PRETTY_FUNCTION__, [EOQualifier stringForOperatorSelector:self->operator]); [self notImplemented:_cmd]; return nil; } return sql; } @end /* EOKeyValueQualifier(SqlExpression) */ @implementation EONotQualifier(SqlExpression) - (NSString *)sqlExpressionWithAdaptor:(EOAdaptor *)_adaptor attributes:(NSArray *)_attributes { NSString *s; s = [self->qualifier sqlExpressionWithAdaptor:_adaptor attributes:_attributes]; return [NSString stringWithFormat:@"NOT(%@)", s]; } @end /* EONotQualifier(SqlExpression) */ @implementation EOKeyComparisonQualifier(SqlExpression) - (NSString *)sqlExpressionWithAdaptor:(EOAdaptor *)_adaptor attributes:(NSArray *)_attributes { NSLog(@"ERROR(%s): subclass needs to override this method!", __PRETTY_FUNCTION__); return nil; } @end /* EOKeyComparisonQualifier(SqlExpression) */ SOPE/sope-gdl1/GDLAccess/EODatabaseContext.m0000644000000000000000000006064415004363604017333 0ustar rootroot/* EODatabaseContext.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 Author: Helge Hess Date: 1999 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "EODatabaseContext.h" #import "EOAdaptor.h" #import "EOAdaptorContext.h" #import "EODatabase.h" #import "EODatabaseChannel.h" #import "EOEntity.h" #import "EODatabaseFault.h" #import "EOGenericRecord.h" #import "EOModel.h" #import "EOObjectUniquer.h" #include "EOModelGroup.h" #include #include NSString *EODatabaseContextWillBeginTransactionName = @"EODatabaseContextWillBeginTransaction"; NSString *EODatabaseContextDidBeginTransactionName = @"EODatabaseContextDidBeginTransaction"; NSString *EODatabaseContextWillRollbackTransactionName = @"EODatabaseContextWillRollbackTransaction"; NSString *EODatabaseContextDidRollbackTransactionName = @"EODatabaseContextDidRollbackTransaction"; NSString *EODatabaseContextWillCommitTransactionName = @"EODatabaseContextWillCommitTransaction"; NSString *EODatabaseContextDidCommitTransactionName = @"EODatabaseContextDidCommitTransaction"; struct EODatabaseContextModificationQueue { struct EODatabaseContextModificationQueue *next; enum { update, delete, insert } op; id object; }; /* * Transaction scope */ typedef struct _EOTransactionScope { struct _EOTransactionScope *previous; EOObjectUniquer *objectsDictionary; NSMutableArray *objectsUpdated; NSMutableArray *objectsDeleted; NSMutableArray *objectsLocked; } EOTransactionScope; static inline EOTransactionScope *_newTxScope(NSZone *_zone) { EOTransactionScope *newScope; newScope = NSZoneMalloc(_zone, sizeof(EOTransactionScope)); newScope->objectsDictionary = [[EOObjectUniquer allocWithZone:_zone] init]; newScope->objectsUpdated = [[NSMutableArray allocWithZone:_zone] init]; newScope->objectsDeleted = [[NSMutableArray allocWithZone:_zone] init]; newScope->objectsLocked = [[NSMutableArray allocWithZone:_zone] init]; return newScope; } static inline void _freeTxScope(NSZone *_zone, EOTransactionScope *_txScope) { RELEASE(_txScope->objectsDictionary); _txScope->objectsDictionary = nil; RELEASE(_txScope->objectsUpdated); _txScope->objectsUpdated = nil; RELEASE(_txScope->objectsDeleted); _txScope->objectsDeleted = nil; RELEASE(_txScope->objectsLocked); _txScope->objectsLocked = nil; NSZoneFree(_zone, _txScope); _txScope = NULL; } @implementation EODatabaseContext #if 0 // no such callback! + (void)initialize { static BOOL isInitialized = NO; if (!isInitialized) { isInitialized = YES; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_objectStoreNeeded:) name:@"EOCooperatingObjectStoreNeeded" object:nil]; } } #endif static inline void _checkTxInProgress(EODatabaseContext *self, const char *_function) { if (self->transactionNestingLevel == 0) { [NSException raise:NSInternalInconsistencyException format: @"EODatabaseContext:%@: No transaction in progress " @"in %s", self, _function]; } } // init - (id)initWithDatabase:(EODatabase *)aDatabase { static int reuseAdaptorCtx = -1; if (reuseAdaptorCtx == -1) { reuseAdaptorCtx = [[[NSUserDefaults standardUserDefaults] objectForKey:@"EOReuseAdaptorContext"] boolValue] ? 1 : 0; } if (reuseAdaptorCtx) { NSEnumerator *contexts; EOAdaptorContext *actx; contexts = [[[aDatabase adaptor] contexts] objectEnumerator]; while ((actx = [contexts nextObject])) { if (![actx hasOpenTransaction]) { #if DEBUG NSLog(@"reuse adaptor context: %@", actx); #endif self->adaptorContext = actx; break; } } if (self->adaptorContext == nil) self->adaptorContext = [[aDatabase adaptor] createAdaptorContext]; } else self->adaptorContext = [[aDatabase adaptor] createAdaptorContext]; if ((aDatabase == nil) || (adaptorContext == nil)) { NSLog(@"EODatabaseContext could not create adaptor context"); AUTORELEASE(self); return nil; } RETAIN(self->adaptorContext); self->database = RETAIN(aDatabase); self->channels = [[NSMutableArray allocWithZone:[self zone]] init]; self->transactionStackTop = NULL; self->transactionNestingLevel = 0; self->updateStrategy = EOUpdateWithOptimisticLocking; self->isKeepingSnapshots = YES; self->isUniquingObjects = [self->database uniquesObjects]; [database contextDidInit:self]; return self; } - (void)dealloc { [database contextWillDealloc:self]; if (self->ops) { struct EODatabaseContextModificationQueue *q; while ((q = self->ops)) { self->ops = q->next; RELEASE(q->object); free(q); } } while (self->transactionNestingLevel) { if (![self rollbackTransaction]) break; } while (self->transactionStackTop) [self privateRollbackTransaction]; RELEASE(self->adaptorContext); self->adaptorContext = nil; RELEASE(self->database); self->database = nil; RELEASE(self->channels); self->channels = nil; [super dealloc]; } /* accessors */ - (void)setDelegate:(id)_delegate { self->delegate = _delegate; } - (id)delegate { return self->delegate; } - (EODatabase *)database { return self->database; } - (EOAdaptorContext *)adaptorContext { return self->adaptorContext; } // channels - (BOOL)hasBusyChannels { int i; for (i = [channels count]-1; i >= 0; i--) { if ([[[channels objectAtIndex:i] nonretainedObjectValue] isFetchInProgress]) return YES; } return NO; } - (BOOL)hasOpenChannels { int i; for (i = [channels count]-1; i >= 0; i--) { if ([[[channels objectAtIndex:i] nonretainedObjectValue] isOpen]) return YES; } return NO; } - (NSArray *)channels { return [self registeredChannels]; } - (id)createChannel { return AUTORELEASE([[EODatabaseChannel alloc] initWithDatabaseContext:self]); } - (void)channelDidInit:(id)aChannel { [self registerChannel:aChannel]; } - (void)channelWillDealloc:(id)aChannel { [self unregisterChannel:aChannel]; } /* * Controlling transactions */ - (BOOL)beginTransaction { NSNotificationCenter *nc; if ([adaptorContext transactionNestingLevel] != (unsigned)transactionNestingLevel) { [NSException raise:NSInternalInconsistencyException format: @"EODatabaseContext:%@:transaction nesting levels do not match: " @"database has %d, adaptor has %d, " @"in [EODatabaseContext beginTransaction]", self, transactionNestingLevel, [adaptorContext transactionNestingLevel]]; } nc = [NSNotificationCenter defaultCenter]; [nc postNotificationName:EODatabaseContextWillBeginTransactionName object:self]; if (![self->adaptorContext beginTransaction]) return NO; [self privateBeginTransaction]; txBeginCount++; [nc postNotificationName:EODatabaseContextDidBeginTransactionName object:self]; return YES; } - (BOOL)commitTransaction { NSNotificationCenter *nc; _checkTxInProgress(self, __PRETTY_FUNCTION__); if ([adaptorContext transactionNestingLevel] != (unsigned)self->transactionNestingLevel) { [NSException raise:NSInternalInconsistencyException format: @"EODatabaseContext:%@:transaction nesting levels do not match: " @"database has %d, adaptor has %d, " @"in [EODatabaseContext commitTransaction]", self, transactionNestingLevel, [adaptorContext transactionNestingLevel]]; } nc = [NSNotificationCenter defaultCenter]; [nc postNotificationName:EODatabaseContextWillCommitTransactionName object:self]; if (![adaptorContext commitTransaction]) return NO; [self privateCommitTransaction]; self->txCommitCount++; [nc postNotificationName:EODatabaseContextDidCommitTransactionName object:self]; return YES; } - (BOOL)rollbackTransaction { NSNotificationCenter *nc; _checkTxInProgress(self, __PRETTY_FUNCTION__); if ([self->adaptorContext transactionNestingLevel] != (unsigned)self->transactionNestingLevel) { [NSException raise:NSInternalInconsistencyException format: @"EODatabaseContext:%@:transaction nesting levels do not match: " @"database has %d, adaptor has %d, " @"in [EODatabaseContext rollbackTransaction]", self, transactionNestingLevel, [adaptorContext transactionNestingLevel]]; } nc = [NSNotificationCenter defaultCenter]; [nc postNotificationName:EODatabaseContextWillRollbackTransactionName object:self]; if (![self->adaptorContext rollbackTransaction]) return NO; [self privateRollbackTransaction]; self->txRollbackCount++; [nc postNotificationName:EODatabaseContextDidRollbackTransactionName object:self]; return YES; } // ******************** notifications ******************** - (void)transactionDidBegin { [self->adaptorContext transactionDidBegin]; [self privateBeginTransaction]; } - (void)transactionDidCommit { _checkTxInProgress(self, __PRETTY_FUNCTION__); [self->adaptorContext transactionDidCommit]; [self privateCommitTransaction]; } - (void)transactionDidRollback { _checkTxInProgress(self, __PRETTY_FUNCTION__); [adaptorContext transactionDidRollback]; [self privateRollbackTransaction]; } /* * Nesting transactions */ - (BOOL)canNestTransactions { return [adaptorContext canNestTransactions]; } - (unsigned)transactionNestingLevel { return transactionNestingLevel; } /* * Setting the update strategy */ - (void)setUpdateStrategy:(EOUpdateStrategy)aStrategy { if ([self transactionNestingLevel]) { [NSException raise:NSInvalidArgumentException format: @"EODatabaseContext:%@: Cannot change update strategy " @"when context has a transaction open, " @"in [EODatabaseContext setUpdateStrategy]", self]; } updateStrategy = aStrategy; isKeepingSnapshots = (updateStrategy == EOUpdateWithNoLocking) ? NO : YES; isUniquingObjects = [database uniquesObjects]; } - (EOUpdateStrategy)updateStrategy { return self->updateStrategy; } - (BOOL)keepsSnapshots { return self->isKeepingSnapshots; } /* * Processing transactions internally */ - (void)privateBeginTransaction { EOTransactionScope *newScope = NULL; newScope = _newTxScope([self zone]); newScope->previous = transactionNestingLevel ? transactionStackTop : NULL; transactionStackTop = newScope; transactionNestingLevel++; if (transactionNestingLevel == 1) self->isUniquingObjects = [database uniquesObjects]; } - (void)privateCommitTransaction { EOTransactionScope *newScope = transactionStackTop; transactionStackTop = newScope->previous; transactionNestingLevel--; // In nested transaction fold updated and deleted objects // into the parent transaction; locked objects are forgotten // deleted objects are deleted form the parent transaction if (transactionNestingLevel) { // Keep updated objects [transactionStackTop->objectsUpdated addObjectsFromArray:newScope->objectsUpdated]; // Keep deleted objects [transactionStackTop->objectsDeleted addObjectsFromArray:newScope->objectsDeleted]; // Register objects in parent transaction scope [newScope->objectsDictionary transferTo:transactionStackTop->objectsDictionary objects:YES andSnapshots:YES]; } // If this was the first transaction then fold the changes // into the database; locked and updateted objects are forgotten else { int i, n; for (i = 0, n = [newScope->objectsDeleted count]; i < n; i++) [database forgetObject:[newScope->objectsDeleted objectAtIndex:i]]; // Register objects into the database if (self->isUniquingObjects || [database keepsSnapshots]) { [newScope->objectsDictionary transferTo:[database objectUniquer] objects:self->isUniquingObjects andSnapshots:[database keepsSnapshots]]; } } // Kill transaction scope _freeTxScope([self zone], newScope); } - (void)privateRollbackTransaction { EOTransactionScope *newScope = transactionStackTop; transactionStackTop = newScope->previous; transactionNestingLevel--; // Forget snapshots, updated, deleted and locked objects // in current transaction // Kill transaction scope _freeTxScope([self zone], newScope); } // Handle Objects - (void)forgetObject:(id)_object { EOTransactionScope *scope = NULL; _checkTxInProgress(self, __PRETTY_FUNCTION__); if (_object == nil) { [NSException raise:NSInvalidArgumentException format: @"EODatabaseContext:%@: Cannot forget null object, " @"in [EODatabaseContext forgetObject]", self]; } if ([EOFault isFault:_object]) { [NSException raise:NSInvalidArgumentException format: @"EODatabaseContext:%@: Cannot forget forget a fault object, " @"in [EODatabaseContext forgetObject]", self]; } [transactionStackTop->objectsDeleted addObject:_object]; for (scope = transactionStackTop; scope; scope = scope->previous) { [scope->objectsDictionary forgetObject:_object]; } } - (id)objectForPrimaryKey:(NSDictionary *)_key entity:(EOEntity *)_entity { EOTransactionScope *scope = NULL; id _object = nil; if (!self->isUniquingObjects || (_key == nil) || (_entity == nil)) return nil; _key = [_entity primaryKeyForRow:_key]; if (_key == nil) return nil; for (scope = transactionStackTop; scope; scope = scope->previous) { _object = [scope->objectsDictionary objectForPrimaryKey:_key entity:_entity]; if (_object) return _object; } return [self->database objectForPrimaryKey:_key entity:_entity]; } - (void)recordObject:(id)_object primaryKey:(NSDictionary *)_key entity:(EOEntity *)_entity snapshot:(NSDictionary *)snapshot { _checkTxInProgress(self, __PRETTY_FUNCTION__); if (_object == nil) { [NSException raise:NSInvalidArgumentException format: @"EODatabaseContext:%@: Cannot record null object, " @"in [EODatabaseContext recordObject:primaryKey:entity:snapshot:]", self]; } if ((_entity == nil) && self->isUniquingObjects) { [NSException raise:NSInvalidArgumentException format: @"EODatabaseContext:%@: Cannot record object with null entity " @"when uniquing objects, " @"in [EODatabaseContext recordObject:primaryKey:entity:snapshot:]", self]; } _key = [_entity primaryKeyForRow:_key]; if ((_key == nil) && self->isUniquingObjects) { [NSException raise:NSInvalidArgumentException format: @"EODatabaseContext:%@: Cannot record object with null key " @"when uniquing objects, " @"in [EODatabaseContext recordObject:primaryKey:entity:snapshot:]", self]; } if ((snapshot == nil) && isKeepingSnapshots && ![EOFault isFault:_object]) { [NSException raise:NSInvalidArgumentException format: @"EODatabaseContext:%@: Cannot record object with null snapshot " @"when keeping snapshots, " @"in [EODatabaseContext recordObject:primaryKey:entity:snapshot:]" @": snapshot=%s keepsSnapshots=%s isFault=%s", self, snapshot ? "yes" : "no", isKeepingSnapshots ? "yes" : "no", [EOFault isFault:_object] ? "yes" : "no"]; } if (self->isKeepingSnapshots || self->isUniquingObjects) { EOObjectUniquer *cache = transactionStackTop->objectsDictionary; [cache recordObject:_object primaryKey: self->isUniquingObjects ? _key : (NSDictionary *)nil entity: self->isUniquingObjects ? _entity : (EOEntity *)nil snapshot:self->isKeepingSnapshots ? snapshot : (NSDictionary *)nil]; } } - (void)recordObject:(id)_object primaryKey:(NSDictionary *)_key snapshot:(NSDictionary *)_snapshot { EOEntity *entity = nil; entity = [_object respondsToSelector:@selector(entity)] ? [_object entity] : [[[database adaptor] model] entityForObject:_object]; [self recordObject:_object primaryKey:_key entity:entity snapshot:_snapshot]; } - (NSDictionary *)snapshotForObject:(id)_object { EOTransactionScope *scope = NULL; EOUniquerRecord *rec = NULL; if (!isKeepingSnapshots) return nil; for (scope = transactionStackTop; scope; scope = scope->previous) { rec = [scope->objectsDictionary recordForObject:_object]; if (rec) return rec->snapshot; } rec = [[self->database objectUniquer] recordForObject:_object]; if (rec) return rec->snapshot; return nil; } - (NSDictionary*)primaryKeyForObject:(id)_object { EOTransactionScope *scope = NULL; EOUniquerRecord *rec = NULL; if ([self->database uniquesObjects]) return nil; for (scope = transactionStackTop; scope; scope = scope->previous) { rec = [scope->objectsDictionary recordForObject:_object]; if (rec) return rec->pkey; } rec = [[self->database objectUniquer] recordForObject:_object]; if (rec) return rec->pkey; return nil; } - (void)primaryKey:(NSDictionary **)_key andSnapshot:(NSDictionary **)_snapshot forObject:_object { EOTransactionScope *scope = NULL; EOUniquerRecord *rec = NULL; if (!self->isKeepingSnapshots && ![self->database uniquesObjects]) { *_key = *_snapshot = nil; return; } for (scope = transactionStackTop; scope; scope = scope->previous) { rec = [scope->objectsDictionary recordForObject:_object]; if (rec) { if (_key) *_key = rec->pkey; if (_snapshot) *_snapshot = rec->snapshot; return; } } rec = [[self->database objectUniquer] recordForObject:_object]; if (rec) { if (_key) *_key = rec->pkey; if (_snapshot) *_snapshot = rec->snapshot; return; } if (_key) *_key = nil; if (_snapshot) *_snapshot = nil; } - (void)recordLockedObject:(id)_object { _checkTxInProgress(self, __PRETTY_FUNCTION__); if (_object == nil) { [NSException raise:NSInvalidArgumentException format: @"EODatabaseContext:%@: Cannot record null object as locked, " @"in [EODatabaseContext recordLockedObject:]", self]; } if ([EOFault isFault:_object]) { [NSException raise:NSInvalidArgumentException format: @"EODatabaseContext:%@: Cannot record a fault object as locked, " @"in [EODatabaseContext recordLockedObject:]", self]; } [transactionStackTop->objectsLocked addObject:_object]; } - (BOOL)isObjectLocked:(id)_object { EOTransactionScope *scope; for (scope = transactionStackTop; scope; scope = scope->previous) { if ([scope->objectsLocked indexOfObjectIdenticalTo:_object]!=NSNotFound) return YES; } return NO; } - (void)recordUpdatedObject:(id)_object { _checkTxInProgress(self, __PRETTY_FUNCTION__); if (_object == nil) { [NSException raise:NSInvalidArgumentException format: @"EODatabaseContext:%@: Cannot record null object as updatetd, " @"in [EODatabaseContext recordUpdatedObject:]", self]; } if ([EOFault isFault:_object]) { [NSException raise:NSInvalidArgumentException format: @"EODatabaseContext:%@: Cannot record fault object as updated, " @"in [EODatabaseContext recordUpdatedObject:]", self]; } [transactionStackTop->objectsUpdated addObject:_object]; } - (BOOL)isObjectUpdated:(id)_object { EOTransactionScope *scope; for (scope = transactionStackTop; scope; scope = scope->previous) { if ([scope->objectsUpdated indexOfObjectIdenticalTo:_object] != NSNotFound) return YES; if ([scope->objectsDeleted indexOfObjectIdenticalTo:_object] != NSNotFound) return YES; } return NO; } /* description */ - (NSString *)description { return [NSString stringWithFormat: @"<%@[0x%p]: #channels=%i tx-nesting=%i>", NSStringFromClass([self class]), self, (int)[self->channels count], [self transactionNestingLevel]]; } @end /* EODatabaseContext */ @implementation EODatabaseContext(Statistics) - (unsigned int)transactionBeginCount { return self->txBeginCount; } - (unsigned int)transactionCommitCount { return self->txCommitCount; } - (unsigned int)transactionRollbackCount { return self->txRollbackCount; } @end /* EODatabaseContext(Statistics) */ @implementation EODatabaseContext(NewInEOF2) // THREAD static Class EODatabaseContextClass = Nil; + (void)setContextClassToRegister:(Class)_cclass { EODatabaseContextClass = _cclass; } + (Class)contextClassToRegister { return EODatabaseContextClass ? EODatabaseContextClass : (Class)self; } - (EODatabaseChannel *)availableChannel { int i; for (i = [self->channels count] - 1; i >= 0; i--) { EODatabaseChannel *channel; channel = [[self->channels objectAtIndex:i] nonretainedObjectValue]; if (![channel isFetchInProgress]) return channel; } [[NSNotificationCenter defaultCenter] postNotificationName:@"EODatabaseChannelNeeded" object:self]; /* recheck for channel */ for (i = [self->channels count] - 1; i >= 0; i--) { EODatabaseChannel *channel; channel = [[self->channels objectAtIndex:i] nonretainedObjectValue]; if (![channel isFetchInProgress]) return channel; } return nil; } - (NSArray *)registeredChannels { NSMutableArray *array; int i, n; array = [NSMutableArray array]; for (i=0, n=[channels count]; i < n; i++) { EODatabaseChannel *channel = [[channels objectAtIndex:i] nonretainedObjectValue]; [array addObject:channel]; } return array; } - (void)registerChannel:(EODatabaseChannel *)_channel { [self->channels addObject:[NSValue valueWithNonretainedObject:_channel]]; } - (void)unregisterChannel:(EODatabaseChannel *)_channel { int i; for (i = [self->channels count] - 1; i >= 0; i--) { EODatabaseChannel *channel; channel = [[self->channels objectAtIndex:i] nonretainedObjectValue]; if (channel == _channel) { [channels removeObjectAtIndex:i]; break; } } } /* cooperating object store */ - (void)commitChanges { [self commitTransaction]; } - (void)rollbackChanges { [self rollbackTransaction]; } - (void)performChanges { [self notImplemented:_cmd]; } /* store specific properties */ - (NSDictionary *)valuesForKeys:(NSArray *)_keys object:(id)_object { return [_object valuesForKeys:_keys]; } /* capability */ - (BOOL)handlesFetchSpecification:(EOFetchSpecification *)_fspec { EOEntity *entity; entity = [[self database] entityNamed:[_fspec entityName]]; return entity ? YES : NO; } /* graph */ - (BOOL)ownsObject:(id)_object { EOEntity *entity; entity = [[self database] entityNamed:[_object entityName]]; return entity ? YES : NO; } - (BOOL)ownsGlobalID:(EOGlobalID *)_oid { EOEntity *entity; if (![_oid respondsToSelector:@selector(entityName)]) return NO; entity = [[self database] entityNamed:[(id)_oid entityName]]; return entity ? YES : NO; } @end /* EODatabaseContext(NewInEOF2) */ SOPE/sope-gdl1/GDLAccess/GNUmakefile0000644000000000000000000000660315004363604015725 0ustar rootroot# GNUstep makefile include ../../config.make include ../common.make -include ../Version -include ./Version ifneq ($(frameworks),yes) LIBRARY_NAME = libGDLAccess else FRAMEWORK_NAME = GDLAccess endif libGDLAccess_PCH_FILE = common.h libGDLAccess_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION) libGDLAccess_INSTALL_DIR=$(SOPE_SYSLIBDIR) libGDLAccess_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION) libGDLAccess_DLL_DEF = libGDLAccess.def libGDLAccess_HEADER_FILES = \ GDLAccess.h \ EODelegateResponse.h \ EOJoinTypes.h \ EOAdaptor.h \ EOAdaptorChannel.h \ EOAdaptorContext.h \ EOArrayProxy.h \ EOAttribute.h \ EOAttributeOrdering.h \ EOCustomValues.h \ EODatabase.h \ EODatabaseChannel.h \ EODatabaseContext.h \ EOEntity.h \ EOExpressionArray.h \ EOFExceptions.h \ EODatabaseFault.h \ EODatabaseFaultResolver.h \ EOModel.h \ EOObjectUniquer.h \ EOPrimaryKeyDictionary.h \ EOSQLQualifier.h \ EOQuotedExpression.h \ EORelationship.h \ EOSQLExpression.h \ EOGenericRecord.h \ EOModelGroup.h \ EONull.h \ EOKeySortOrdering.h \ EOAdaptorDataSource.h \ EOAdaptorChannel+Attributes.h \ EOAdaptorOperation.h \ EOAdaptorGlobalID.h \ NSObject+EONullInit.h \ EOEntity+Factory.h \ EORecordDictionary.h \ EOFault.h \ EOFaultHandler.h \ libGDLAccess_OBJC_FILES = \ eoaccess.m \ EOAdaptor.m \ EOAdaptorChannel.m \ EOAdaptorContext.m \ EOArrayProxy.m \ EOAttribute.m \ EOAttributeOrdering.m \ EOCustomValues.m \ EODatabase.m \ EODatabaseChannel.m \ EODatabaseContext.m \ EOEntity.m \ EOExpressionArray.m \ EOFExceptions.m \ EODatabaseFault.m \ EODatabaseFaultResolver.m \ EOKeySortOrdering.m \ EOModel.m \ EOObjectUniquer.m \ EOPrimaryKeyDictionary.m \ EORelationship.m \ EOGenericRecord.m \ EOModelGroup.m \ EOEntityClassDescription.m \ EOAdaptorDataSource.m \ EOAdaptorChannel+Attributes.m \ EOAdaptorOperation.m \ EOAdaptorGlobalID.m \ NSObject+EONullInit.m \ EOEntity+Factory.m \ EORecordDictionary.m \ EOFault.m \ EOFaultHandler.m \ \ EOAndQualifier+SQL.m \ EOKeyComparisonQualifier+SQL.m \ EOKeyValueQualifier+SQL.m \ EONotQualifier+SQL.m \ EOOrQualifier+SQL.m \ EOQualifier+SQL.m \ \ EOSQLQualifier.m \ EOSQLExpression.m \ EOSelectSQLExpression.m \ EOQuotedExpression.m \ EOQualifierScanner.m \ ifneq ($(FOUNDATION_LIB),fd) libGDLAccess_SUBPROJECTS += FoundationExt endif libGDLAccess_HEADER_FILES_DIR = . libGDLAccess_HEADER_FILES_INSTALL_DIR = /GDLAccess # adaptor load test TOOL_NAME = load-EOAdaptor connect-EOAdaptor load-EOAdaptor_OBJC_FILES = load-EOAdaptor.m connect-EOAdaptor_OBJC_FILES = connect-EOAdaptor.m load-EOAdaptor_PCH_FILE = common.h connect-EOAdaptor_PCH_FILE = common.h load-EOAdaptor_INSTALL_DIR = $(SOPE_TOOLS)/ connect-EOAdaptor_INSTALL_DIR = $(SOPE_TOOLS)/ # framework support GDLAccess_PCH_FILE = $(libGDLAccess_PCH_FILE) GDLAccess_HEADER_FILES = $(libGDLAccess_HEADER_FILES) GDLAccess_OBJC_FILES = $(libGDLAccess_OBJC_FILES) GDLAccess_SUBPROJECTS = $(libGDLAccess_SUBPROJECTS) # building -include GNUmakefile.preamble ifneq ($(FHS_INSTALL_ROOT),) GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include endif ifneq ($(frameworks),yes) include $(GNUSTEP_MAKEFILES)/library.make else include $(GNUSTEP_MAKEFILES)/framework.make endif include $(GNUSTEP_MAKEFILES)/tool.make -include GNUmakefile.postamble SOPE/sope-gdl1/GDLAccess/EOOrQualifier+SQL.m0000644000000000000000000000400515004363604017124 0ustar rootroot/* EOAdaptorChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOOrQualifier+SQL.m 1 2004-08-20 10:38:46Z znek $ #import "EOSQLQualifier.h" #include "common.h" @implementation EOOrQualifier(SQLQualifier) /* SQL qualifier generation */ - (EOSQLQualifier *)sqlQualifierForEntity:(EOEntity *)_entity { unsigned cc = [self->qualifiers count]; if (cc == 0) return nil; else if (cc == 1) return [[self->qualifiers objectAtIndex:0] sqlQualifierForEntity:_entity]; else if (cc == 2) { id left; id right; left = [[self->qualifiers objectAtIndex:0] sqlQualifierForEntity:_entity]; right = [[self->qualifiers objectAtIndex:1] sqlQualifierForEntity:_entity]; [left disjoinWithQualifier:right]; return left; } else { EOSQLQualifier *masterQ; unsigned i; for (i = 0, masterQ = nil; i < cc; i++) { EOSQLQualifier *q; q = [[self->qualifiers objectAtIndex:i] sqlQualifierForEntity:_entity]; if (masterQ == nil) masterQ = q; else [masterQ disjoinWithQualifier:q]; } return masterQ; } } @end /* EOOrQualifier */ SOPE/sope-gdl1/GDLAccess/EOAdaptorContext.h0000644000000000000000000000725115004363604017207 0ustar rootroot/* EOAdaptorContext.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOAdaptorContext_h__ #define __EOAdaptorContext_h__ #import @class NSArray, NSMutableArray; @class EOAdaptor; @class EOAdaptorChannel; /* The EOAdaptorContext class could be overriden for a concrete database adaptor. You have to override only those methods marked in this header with `override'. */ @interface EOAdaptorContext : NSObject { EOAdaptor *adaptor; NSMutableArray *channels; // values with channels id delegate; // not retained int transactionNestingLevel; /* Flags used to check if the delegate responds to several messages */ struct { BOOL willBegin:1; BOOL didBegin:1; BOOL willCommit:1; BOOL didCommit:1; BOOL willRollback:1; BOOL didRollback:1; } delegateRespondsTo; } /* Initializing an adaptor context */ - (id)initWithAdaptor:(EOAdaptor*)adaptor; /* Setting and getting the adaptor */ - (EOAdaptor*)adaptor; /* Creating a new channel */ - (EOAdaptorChannel*)createAdaptorChannel; // override - (NSArray *)channels; /* Checking connection status */ - (BOOL)hasOpenChannels; /* Finding open channels */ - (BOOL)hasBusyChannels; /* Controlling transactions */ - (BOOL)beginTransaction; - (BOOL)commitTransaction; - (BOOL)rollbackTransaction; /* Notifying of other transactions */ - (void)transactionDidBegin; - (void)transactionDidCommit; - (void)transactionDidRollback; /* Nesting transactions */ - (BOOL)canNestTransactions; // override, deprecated - (unsigned)transactionNestingLevel; // deprecated - (BOOL)hasOpenTransaction; // new in WO 4.5 /* Setting the delegate */ - (id)delegate; - (void)setDelegate:(id)aDelegate; /* Primary methods that control the transactions. This methods dont't call the delegate. You should implement these methods instead of the similar ones but without the `primary' prefix. */ - (BOOL)primaryBeginTransaction; // override - (BOOL)primaryCommitTransaction; // override - (BOOL)primaryRollbackTransaction; // override @end /* EOAdaptorContext*/ @interface EOAdaptorContext(Private) - (void)channelDidInit:(id)aChannel; - (void)channelWillDealloc:(id)aChannel; @end #import @interface NSObject(EOAdaptorContextDelegate) - (EODelegateResponse)adaptorContextWillBegin:(id)aContext; - (void)adaptorContextDidBegin:(id)aContext; - (EODelegateResponse)adaptorContextWillCommit:(id)aContext; - (void)adaptorContextDidCommit:(id)aContext; - (EODelegateResponse)adaptorContextWillRollback:(id)aContext; - (void)adaptorContextDidRollback:(id)aContext; @end /* NSObject(EOAdaptorContextDelegate) */ #endif /* __EOAdaptorContext_h__*/ SOPE/sope-gdl1/GDLAccess/ChangeLog0000644000000000000000000002356415004363604015432 0ustar rootroot2009-03-24 Wolfgang Sourdeau * EOAdaptor: invoke MySQL adaptor using the 'mysql' URL scheme (v4.7.63) 2007-08-29 Helge Hess * EOAdaptor.m: invoke new Oracle8 adaptor for the 'oracle' URL scheme (v4.7.62) 2007-06-10 Helge Hess * v4.7.61 * EOAttribute.m: minor code cleanups * EOExpressionArray.m: copy prefix/suffix/infix strings in accessor methods 2007-06-01 Helge Hess * EOEntity.m, EOAttribute.m: minor improvements/comments on value encoding (v4.7.60) 2007-04-17 Helge Hess * EOSQLExpression.m: fixed a gcc4 warning (v4.7.59) 2006-08-15 Helge Hess * EOCustomValues.m: added special support for lF NSTemporaryString to fix OGo bug #1701 (v4.5.58) 2006-07-05 Helge Hess * EOAdaptor.m: changed to find SAX drivers on 64bit systems in lib64, added FHS_INSTALL_ROOT to lookup path (v4.5.57) 2006-07-04 Helge Hess * use %p for pointer formats, fixed gcc 4.1 warnings (v4.5.56) 2005-10-13 Helge Hess * EOArrayProxy.m, EOPrimaryKeyDictionary.m, EOExpressionArray.m, EORecordDictionary.m: added -isNotEmpty methods (v4.5.55) 2005-08-16 Helge Hess * GNUmakefile, GNUmakefile.preamble: added OSX framework compilation (v4.5.54) 2005-08-05 Helge Hess * EOAdaptorContext.m, common.h: do not include NSUtilities.h on Cocoa (v4.5.53) 2005-06-02 Helge Hess * EOJoinTypes.h: properly protect header against multiple inclusion (fixes a compilation issue) (v4.5.52) 2005-05-05 Helge Hess * fixed gcc 4.0 warnings (v4.5.51) 2005-04-21 Helge Hess * EOAdaptorChannel.[hm]: added -describeResults: as a public method, implemented -describeResults based on that (adaptors now need to override -describeResults:) (v4.5.50) 2005-04-12 Helge Hess * v4.5.49 * fixed various gcc 3.4.3 warnings * removed support for unused EOAttribute features like flattened, derived, read-only, insert/update formats, definition 2005-03-15 Helge Hess * FoundationExt/GNUmakefile: properly include config.make (v4.5.48) 2005-02-20 Helge Hess * EOAdaptor.m: added +adaptorForURL: method to create EOAdaptor objects from JDBC style URLs (eg PostgreSQL://OGo:OGo@localhost/OGo") (v4.5.47) 2005-01-14 Helge Hess * EOAdaptorDataSource.m: fixed a bug in the sorting code, the "AS" was missing in the SQL rename statement (v4.5.46) 2005-01-13 Helge Hess * EOAdaptorDataSource.m: improved -description (v4.5.45) 2005-01-04 Helge Hess * EOAttribute.m, EOFaultHandler.m, EODatabaseFaultResolver.m: added casts to avoid compile warnings with Xcode (v4.5.44) 2004-12-14 Marcus Mueller * v4.5.43 * GDLAccess.xcode: minor fixes and updated * EOAttribute.m: changed usage of -timeZoneName (deprecated) to -name for Foundations different to libFoundation. 2004-11-13 Helge Hess * EOAdaptor.m: fixed a bug in the lookup of GDL adaptor bundles (v4.5.42) 2004-11-11 Marcus Mueller * GDLAccess.xcode: fixed Xcode build by providing all necessary major/minor numbers and bumped the framework revision 2004-11-09 Helge Hess * v4.5.41 * bumped version from 1.3 to 4.5 to be consistent with the remaining SOPE versions (the "super major version" is still gdl1) * EOAdaptor.m: fixed adaptor lookup path 2004-09-22 Marcus Mueller * GDLAccess.xcode: new Xcode project 2004-09-11 Marcus Mueller * GNUmakefile.preamble, FoundationExt/GNUmakefile: minor changes for inline compilation with GNUSTEP_BUILD_DIR set elsewhere (v1.1.40) 2004-09-06 Helge Hess * EOSQLQualifier.m: fixed a compile warning related to scanner handler and NSArray argument instead of va_list (v1.1.39) 2004-09-06 Helge Hess * EOAdaptorChannel.m: added -selectAttributesX:describedByQualifier:fetchOrder:lock: for selects which return, not raise, exceptions (v1.1.38) 2004-08-31 Helge Hess * GNUmakefile.preamble: added library search pathes for FHS install (v1.1.37) 2004-08-30 Helge Hess * v1.1.36 * EOAdaptor.m: also look for adaptors in /usr/lib/sope-4.3/dbadaptors and /usr/local/lib/sope-4.3/dbadaptors * added hack to install the project in FHS locations - the library, its headers, the tools and the resources will be installed in FHS_INSTALL_ROOT if specified (eg make FHS_INSTALL_ROOT=/usr/local) 2004-08-27 Helge Hess * EOAdaptor.m: look for adaptor bundles in Library/GDLAdaptors-1.1/ (v1.1.35) * increased version to v1.1 because it depends on libEOControl v4.3 (v1.1.34) 2004-08-21 Helge Hess * v1.0.33 * fixed for SOPE 3.3 directory layout * removed GDLExtensions * moved headers files from EOAccess subdirectory to main directory 2004-08-20 Helge Hess * moved from ThirdParty to SOPE/sope-gdl1 (v1.0.32) 2004-06-29 Helge Hess * v1.0.31 * EOAdaptorChannel.m: fixed a bug in the transaction check introduced in v1.0.29 - resulted in OGo bug #824, #825 * EODatabaseChannel.m: use new "X" adaptor methods * GNUmakefile.preamble: added include path to SOPE/skyrix-core for "inline" compilation (v1.0.30) 2004-06-28 Helge Hess * EOAdaptorChannel.[hm]: added more "X" methods which do not raise exceptions (v1.0.29) * EOAdaptorChannel.m: added new method -evaluateExpressionX: which returns the exception instead of raising it. It returns @"EOEvaluationError" if the -evaluateExpression: returned NO without raising an exception. It is recommended that adaptor classes implement -evaluateExpression: using -evaluateExpressionX:, not the other way around (v1.0.28) 2004-06-27 Helge Hess * EOModel.m: minor code cleanups (v1.0.27) 2004-06-21 Helge Hess * EOModel.m: some code cleanups, improved description (v1.0.26) 2004-06-06 Helge Hess * fixed Xcode compilation with embedded FoundationExt classes (v1.0.25) 2004-05-14 Helge Hess * EOAdaptorDataSource.m: removed some ==YES comparisons, minor cleanups (v1.0.24) 2004-03-14 Helge Hess * v1.0.23 * EOSQLQualifier.m: improved -description method * EOSQLExpression.m: moved EOSelectSQLExpression to separate file, added a -description method, various minor code cleanups * EOExpressionArray.m: added a -description method, minor cleanups * EOAdaptorChannel.m: minor code cleanups * EODatabaseContext.m: removed registration for EOCooperatingObjectStoreNeeded notification (solves an issue with gstep-base) 2004-03-09 Helge Hess * EOAdaptorChannel.m, EOAdaptorDataSource.m, EOAttribute.m, EODatabase.m, EOEntity.m, EOEntityClassDescription.m, EOQualifier+SQL.m, EOSQLExpression.m, common.h, EOQualifierScanner.h: various subminor fixes for compilation against gstep-base (v1.0.22) 2004-02-12 Helge Hess * EODatabaseChannel.m: only check for GC objects on libFoundation (v1.0.21) 2004-01-29 Helge Hess * EORecordDictionary.m: disabled a profiling log (v1.0.20) 2004-01-07 Helge Hess * some tweaks for Xcode compilation (v1.0.19) 2004-01-04 Helge Hess * v1.0.18 * more tweaks to makefiles and source, now seems to compile fine on MacOSX * added FoundationExt subproject containing the necessary classes from the extensions library, that is, the FormatScanner, PrintfFormatScanner and DefaultScannerHandler 2004-01-03 Helge Hess * v1.0.17 * EORecordDictionary.m: cache -hash and -isEqual selector in objectForKey: * various changes to make gnustep-db compile on MacOSX (eg do not use InvalidArgumentException class but rather NSInvalidArgumentException exception name, etc) 2003-12-29 Helge Hess * EORecordDictionary.m(dealloc): cache release method of dict key, which is basically always an NSString, also cache empty dictionary (v1.0.16) 2003-10-20 Helge Hess * v1.0.15 * common.h: do not use zones for memory allocation (read: speedup) * removed support for Boehm GC, makes code much more readable and shorter (and isn't used in OGo anyway ...) * removed some warnings, some FoundationExt cleanups * EOExpressionArray.h: does not inherit from GCObject and use GCMutableArray anymore (replaced with NSObject and NSMutableArray) * EODatabaseContext.m: removed some unused methods * removed some GCObject dependency * EODatabaseChannel.m: removed some unused methods Wed Oct 15 16:26:50 2003 Jan Reichmann * EOModel.m: initialize model name with the filename which contains the model (*.eomodel) (v1.0.14) Sun Sep 07 00:30:59 2003 Marcus Mueller * GNUmakefile: reordered autodoc target Mon Jul 14 14:07:22 2003 Jan Reichmann * fixed license entries (v1.0.13) Fri Jul 4 19:15:35 2003 Helge Hess * imported into OpenGroupware.org (v1.0.11) SOPE/sope-gdl1/GDLAccess/common.h0000644000000000000000000001254715004363604015320 0ustar rootroot/* EOAdaptorChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __common_h__ #define __common_h__ #include #include #ifndef __WIN32__ # include # include #endif #include #include #include #import #import #if !(COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY || GNUSTEP_BASE_LIBRARY) # import #endif #import #if LIB_FOUNDATION_LIBRARY # import #else # include # include #endif // ******************** common functions ******************** static inline void *Malloc(int) __attribute__((unused)); static inline void *Calloc(int, int) __attribute__((unused)); static inline void *Realloc(void*, int) __attribute__((unused)); static inline void Free(void*) __attribute__((unused)); static inline int Strlen(const char*) __attribute__((unused)); static inline char* Strdup(const char*) __attribute__((unused)); static inline char* Strcpy (char*, const char*) __attribute__((unused)); static inline char* Strncpy (char*, const char*, unsigned) __attribute__((unused)); static inline char* Strcat (char*, const char*) __attribute__((unused)); static inline char* Strncat (char*, const char*, unsigned) __attribute__((unused)); static inline int Strcmp(const char*, const char*) __attribute__((unused)); static inline int Strncmp(const char*, const char*, unsigned) __attribute__((unused)); static inline int Atoi(const char*) __attribute__((unused)); static inline long Atol(const char*) __attribute__((unused)); static inline void *Malloc(int size) { return malloc(size); } static inline void *MallocAtomic(int size) { return malloc(size); } static inline void Free(void* p) { if (p) free(p); } static inline void *Calloc(int elem, int size) { return calloc(elem, size); } static inline void *CallocAtomic(int elem, int size) { return calloc(elem, size); } static inline void *Realloc(void* p, int size) { return realloc(p, size); } static inline int Strlen(const char* s) { return s ? strlen(s) : 0; } static inline char* Strdup(const char* s) { return s ? strcpy(Malloc(strlen(s) + 1), s) : NULL; } static inline char* Strcpy (char* d, const char* s) { return s && d ? strcpy(d, s) : d; } static inline char* Strncpy (char* d, const char* s, unsigned size) { return s && d ? strncpy(d, s, size) : d; } static inline char* Strcat (char* d, const char* s) { return s && d ? strcat(d, s) : d; } static inline char* Strncat (char* d, const char* s , unsigned size) { return s && d ? strncat(d, s , size) : d; } static inline int Strcmp(const char* p, const char* q) { if(!p) { if(!q) return 0; else return -1; } else { if(!q) return 1; else return strcmp(p, q); } } static inline int Strncmp(const char* p, const char* q, unsigned size) { if(!p) { if(!q) return 0; else return -1; } else { if(!q) return 1; else return strncmp(p, q, size); } } static inline int Atoi(const char* str) { return str ? atoi(str) : 0; } static inline long Atol(const char *str) { return str ? atol(str) : 0; } #ifndef MAX #define MAX(a, b) \ ({typedef _ta = (a), _tb = (b); \ _ta _a = (a); _tb _b = (b); \ _a > _b ? _a : _b; }) #endif #ifndef MIN #define MIN(a, b) \ ({typedef _ta = (a), _tb = (b); \ _ta _a = (a); _tb _b = (b); \ _a < _b ? _a : _b; }) #endif #if !LIB_FOUNDATION_LIBRARY #ifndef CREATE_AUTORELEASE_POOL #define CREATE_AUTORELEASE_POOL(pool) \ id pool = [[NSAutoreleasePool alloc] init] #endif #endif /* ! LIB_FOUNDATION_LIBRARY */ #if !LIB_FOUNDATION_LIBRARY static inline char *Ltoa(long nr, char *str, int base) { char buff[34], rest, is_negative; int ptr; ptr = 32; buff[33] = '\0'; if(nr < 0) { is_negative = 1; nr = -nr; } else is_negative = 0; while(nr != 0) { rest = nr % base; if(rest > 9) rest += 'A' - 10; else rest += '0'; buff[ptr--] = rest; nr /= base; } if(ptr == 32) buff[ptr--] = '0'; if(is_negative) buff[ptr--] = '-'; Strcpy(str, &buff[ptr+1]); return(str); } #endif #if !LIB_FOUNDATION_LIBRARY @interface NSObject(FoundationExtGDLAccess) - (void)subclassResponsibility:(SEL)sel; - (void)notImplemented:(SEL)sel; @end #endif #endif /* __common_h__ */ SOPE/sope-gdl1/GDLAccess/EOSelectSQLExpression.m0000644000000000000000000000602115004363604020126 0ustar rootroot/* EOSQLExpression.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: September 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOSQLExpression.h" #include "EOAttribute.h" #include "EOAdaptor.h" #include "common.h" #if LIB_FOUNDATION_LIBRARY # include # include #else # include "DefaultScannerHandler.h" # include "PrintfFormatScanner.h" #endif @interface EOSelectScannerHandler : DefaultScannerHandler { EOAttribute *attribute; EOAdaptor *adaptor; NSString *alias; } - (void)setAttribute:(EOAttribute*)attribute adaptor:(EOAdaptor*)adaptor alias:(NSString*)alias; @end @implementation EOSelectSQLExpression - (NSString *)expressionValueForAttribute:(EOAttribute *)attribute context:(id)context { NSString *alias; NSString *columnName; alias = [entitiesAndPropertiesAliases objectForKey:context]; //NSLog(@"entitiesAndPropertiesAliases: %@", entitiesAndPropertiesAliases); columnName = adaptor ? (NSString *)[adaptor formatAttribute:attribute] : [attribute columnName]; if (alias) { return [([[NSString alloc] initWithFormat:@"%@.%@", alias, columnName]) autorelease]; } return columnName; } @end /* EOSelectSQLExpression */ @implementation EOSelectScannerHandler - (id)init { if ((self = [super init]) != nil) { specHandler['A'] = [self methodForSelector:@selector(convertAttribute:scanner:)]; } return self; } - (void)dealloc { [self->attribute release]; [self->adaptor release]; [self->alias release]; [super dealloc]; } - (void)setAttribute:(EOAttribute*)_attribute adaptor:(EOAdaptor*)_adaptor alias:(NSString*)_alias { ASSIGN(self->attribute, _attribute); ASSIGN(self->adaptor, _adaptor); ASSIGN(self->alias, _alias); } - (NSString *)convertAttribute:(va_list *)pString scanner:(FormatScanner *)scanner { NSString *columnName; columnName = (adaptor) ? (NSString *)[adaptor formatAttribute:self->attribute] : [self->attribute columnName]; if (alias) return [NSString stringWithFormat:@"%@.%@", alias, columnName]; return columnName; } @end /* EOSelectScannerHandler */ SOPE/sope-gdl1/GDLAccess/EOModelGroup.m0000644000000000000000000001343215004363604016330 0ustar rootroot/* EOAdaptorChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOModelGroup.m 1 2004-08-20 10:38:46Z znek $ #include "EOModelGroup.h" #include "EOModel.h" #include "EOEntity.h" #import #include "common.h" @implementation EOModelGroup static EOModelGroup *defaultGroup = nil; static id classDelegate = nil; + (void)setDefaultGroup:(EOModelGroup *)_group { ASSIGN(defaultGroup, _group); } + (EOModelGroup *)defaultGroup { EOModelGroup *group; group = defaultGroup; if (group == nil) group = [[self classDelegate] defaultModelGroup]; if (group == nil) group = [self globalModelGroup]; return group; } + (EOModelGroup *)globalModelGroup { static EOModelGroup *globalModelGroup = nil; NSEnumerator *bundles; NSBundle *bundle; if (globalModelGroup) return globalModelGroup; globalModelGroup = [[EOModelGroup alloc] init]; bundles = [[NSBundle allBundles] objectEnumerator]; while ((bundle = [bundles nextObject])) { NSEnumerator *paths; NSString *path; paths = [[bundle pathsForResourcesOfType:@"eomodel" inDirectory:nil] objectEnumerator]; while ((path = [paths nextObject])) { EOModel *model; model = [[EOModel alloc] initWithContentsOfFile:path]; if (model == nil) { NSLog(@"WARNING: couldn't load model %@", path); } else { [globalModelGroup addModel:model]; RELEASE(model); } } } return globalModelGroup; } + (void)setClassDelegate:(id)_delegate { ASSIGN(classDelegate, _delegate); } + (id)classDelegate { return classDelegate; } - (id)init { self->nameToModel = [[NSMutableDictionary allocWithZone:[self zone]] init]; return self; } - (void)dealloc { RELEASE(self->nameToModel); [super dealloc]; } /* instance delegate */ - (void)setDelegate:(id)_delegate { self->delegate = _delegate; } - (id)delegate { return self->delegate; } /* accessors */ - (void)addModel:(EOModel *)_model { NSString *name; name = [_model name]; if (name == nil) name = [[_model path] lastPathComponent]; if ([self->nameToModel objectForKey:name]) { [NSException raise:@"NSInvalidArgumentException" format:@"model group %@ already contains model named %@", self, name]; } [self->nameToModel setObject:_model forKey:name]; [[NSNotificationCenter defaultCenter] postNotificationName:@"EOModelAddedNotification" object:_model]; } - (void)removeModel:(EOModel *)_model { NSArray *allNames; allNames = [self->nameToModel allKeysForObject:_model]; [self->nameToModel removeObjectsForKeys:allNames]; [[NSNotificationCenter defaultCenter] postNotificationName:@"EOModelInvalidatedNotification" object:_model]; } - (EOModel *)addModelWithFile:(NSString *)_path { EOModel *model; model = [[EOModel alloc] initWithContentsOfFile:_path]; if (model == nil) return nil; AUTORELEASE(model); [self addModel:model]; return model; } - (EOModel *)modelNamed:(NSString *)_name { return [self->nameToModel objectForKey:_name]; } - (EOModel *)modelWithPath:(NSString *)_path { NSEnumerator *e; EOModel *m; NSString *p; p = [_path stringByStandardizingPath]; if (p == nil) p = _path; e = [self->nameToModel objectEnumerator]; while ((m = [e nextObject])) { NSString *mp; mp = [[m path] stringByStandardizingPath]; if (mp == nil) mp = [m path]; if ([p isEqual:mp]) return m; } return m; } - (NSArray *)modelNames { return [self->nameToModel allKeys]; } - (NSArray *)models { return [self->nameToModel allValues]; } - (void)loadAllModelObjects { [[self->nameToModel allValues] makeObjectsPerformSelector:_cmd]; } /* entities */ - (EOEntity *)entityForObject:(id)_object { NSEnumerator *e; EOModel *m; e = [self->nameToModel objectEnumerator]; while ((m = [e nextObject])) { EOEntity *entity; if ((entity = [m entityForObject:_object])) return entity; } return nil; } - (EOEntity *)entityNamed:(NSString *)_name { NSEnumerator *e; EOModel *m; e = [self->nameToModel objectEnumerator]; while ((m = [e nextObject])) { EOEntity *entity; if ((entity = [m entityNamed:_name])) return entity; } return nil; } - (EOFetchSpecification *)fetchSpecificationNamed:(NSString *)_name entityNamed:(NSString *)_entityName { return [[self entityNamed:_entityName] fetchSpecificationNamed:_name]; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"<%@[0x%p]: models=%@>", NSStringFromClass([self class]), self, [[self modelNames] componentsJoinedByString:@","]]; } @end /* EOModelGroup */ SOPE/sope-gdl1/GDLAccess/EOAdaptorChannel.m0000644000000000000000000004457215004363604017147 0ustar rootroot/* EOAdaptorChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "EOAdaptorChannel.h" #import "EOAttribute.h" #import "EOAdaptor.h" #import "EOAdaptorContext.h" #import "EOSQLExpression.h" #import "EOFExceptions.h" @interface EOAdaptorChannel(Internals) - (NSArray *)_sortAttributesForSelectExpression:(NSArray *)_attrs; @end /* EOAdaptorChannel(Internals) */ @implementation EOAdaptorChannel + (NSCalendarDate*)dateForAttribute:(EOAttribute*)attr year:(int)year month:(unsigned)month day:(unsigned)day hour:(unsigned)hour minute:(unsigned)minute second:(unsigned)second zone:(NSZone*)zone { NSTimeZone *serverTimeZone = [attr serverTimeZone]; NSTimeZone *clientTimeZone = [attr clientTimeZone]; NSCalendarDate *date; NSString *fmt; if (serverTimeZone == nil) serverTimeZone = [NSTimeZone localTimeZone]; if (clientTimeZone == nil) clientTimeZone = [NSTimeZone localTimeZone]; date = AUTORELEASE([[NSCalendarDate allocWithZone:zone] initWithYear:year month:month day:day hour:hour minute:minute second:second timeZone:serverTimeZone]); [date setTimeZone:clientTimeZone]; fmt = [attr calendarFormat]; [date setCalendarFormat:fmt ? fmt : [EOAttribute defaultCalendarFormat]]; return date; } - (id)initWithAdaptorContext:(EOAdaptorContext*)_adaptorContext { ASSIGN(self->adaptorContext, _adaptorContext); NS_DURING [self->adaptorContext channelDidInit:self]; NS_HANDLER { AUTORELEASE(self); [localException raise]; } NS_ENDHANDLER; return self; } - (void)dealloc { [self->adaptorContext channelWillDealloc:self]; RELEASE(self->adaptorContext); [super dealloc]; } /* open/close channel */ - (BOOL)openChannel { if(self->isOpen) return NO; self->isOpen = YES; return YES; } - (void)closeChannel { if ([self isFetchInProgress]) [self cancelFetch]; self->isOpen = NO; } /* modifications */ - (Class)_adaptorExpressionClass { return [[self->adaptorContext adaptor] expressionClass]; } - (BOOL)_isNoRaiseOnModificationException:(NSException *)_exception { /* for compatibility with non-X methods, translate some errors to a bool */ NSString *n; n = [_exception name]; if ([n isEqualToString:@"EOEvaluationError"]) return YES; if ([n isEqualToString:@"EODelegateRejects"]) return YES; return NO; } - (NSException *)insertRowX:(NSDictionary *)row forEntity:(EOEntity *)entity { EOSQLExpression *sqlexpr; NSMutableDictionary *mrow = (id)row; NSException *ex; if (!isOpen) return [[ChannelIsNotOpenedException new] autorelease]; if ((row == nil) || (entity == nil)) { return [NSException exceptionWithName:NSInvalidArgumentException reason:@"row and entity arguments for " @"insertRow:forEntity: must not be the nil object" userInfo:nil]; } if ([self isFetchInProgress]) return [AdaptorIsFetchingException exceptionWithAdaptor:self]; if ([self->adaptorContext transactionNestingLevel] == 0) return [NoTransactionInProgressException exceptionWithAdaptor:self]; if (delegateRespondsTo.willInsertRow) { EODelegateResponse response; mrow = AUTORELEASE([row mutableCopyWithZone:[row zone]]); response = [delegate adaptorChannel:self willInsertRow:mrow forEntity:entity]; if (response == EODelegateRejects) { return [NSException exceptionWithName:@"EODelegateRejects" reason:@"delegate rejected insert" userInfo:nil]; } if (response == EODelegateOverrides) return nil; } sqlexpr = [[[self->adaptorContext adaptor] expressionClass] insertExpressionForRow:mrow entity:entity channel:self]; ex = [self evaluateExpressionX:[sqlexpr expressionValueForContext:nil]]; if (ex != nil) return ex; if(delegateRespondsTo.didInsertRow) [delegate adaptorChannel:self didInsertRow:mrow forEntity:entity]; return nil; } - (NSException *)updateRowX:(NSDictionary *)row describedByQualifier:(EOSQLQualifier *)qualifier { EOSQLExpression *sqlexpr = nil; NSMutableDictionary *mrow = (id)row; NSException *ex; if (!isOpen) return [[ChannelIsNotOpenedException new] autorelease]; if (row == nil) { return [NSException exceptionWithName:NSInvalidArgumentException reason: @"row argument for updateRow:describedByQualifier: " @"must not be the nil object" userInfo:nil]; } if ([self isFetchInProgress]) return [AdaptorIsFetchingException exceptionWithAdaptor:self]; if ([self->adaptorContext transactionNestingLevel] == 0) return [NoTransactionInProgressException exceptionWithAdaptor:self]; if (delegateRespondsTo.willUpdateRow) { EODelegateResponse response; mrow = AUTORELEASE([row mutableCopyWithZone:[row zone]]); response = [delegate adaptorChannel:self willUpdateRow:mrow describedByQualifier:qualifier]; if (response == EODelegateRejects) { return [NSException exceptionWithName:@"EODelegateRejects" reason:@"delegate rejected update" userInfo:nil]; } if (response == EODelegateOverrides) return nil; } sqlexpr = [[self _adaptorExpressionClass] updateExpressionForRow:mrow qualifier:qualifier channel:self]; ex = [self evaluateExpressionX:[sqlexpr expressionValueForContext:nil]]; if (ex != nil) return ex; if (delegateRespondsTo.didUpdateRow) { [delegate adaptorChannel:self didUpdateRow:mrow describedByQualifier:qualifier]; } return nil; } - (NSException *)deleteRowsDescribedByQualifierX:(EOSQLQualifier *)qualifier { EOSQLExpression *sqlexpr = nil; NSException *ex; if (!isOpen) return [[ChannelIsNotOpenedException new] autorelease]; if ([self isFetchInProgress]) return [AdaptorIsFetchingException exceptionWithAdaptor:self]; if ([self->adaptorContext transactionNestingLevel] == 0) return [NoTransactionInProgressException exceptionWithAdaptor:self]; if (delegateRespondsTo.willDeleteRows) { EODelegateResponse response; response = [delegate adaptorChannel:self willDeleteRowsDescribedByQualifier:qualifier]; if (response == EODelegateRejects) { return [NSException exceptionWithName:@"EODelegateRejects" reason:@"delegate rejected delete" userInfo:nil]; } if (response == EODelegateOverrides) return nil; } sqlexpr = [[self _adaptorExpressionClass] deleteExpressionWithQualifier:qualifier channel:self]; ex = [self evaluateExpressionX:[sqlexpr expressionValueForContext:nil]]; if (ex != nil) return ex; if (delegateRespondsTo.didDeleteRows) [delegate adaptorChannel:self didDeleteRowsDescribedByQualifier:qualifier]; return nil; } /* compatibility methods (DEPRECATED, use the ...X methods */ - (BOOL)selectAttributes:(NSArray *)attributes describedByQualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder lock:(BOOL)lockFlag { NSException *ex; ex = [self selectAttributesX:attributes describedByQualifier:qualifier fetchOrder:fetchOrder lock:lockFlag]; if (ex == nil) return YES; if ([self _isNoRaiseOnModificationException:ex]) return NO; [ex raise]; return NO; } - (BOOL)insertRow:(NSDictionary *)_row forEntity:(EOEntity *)_entity { NSException *ex; ex = [self insertRowX:_row forEntity:_entity]; if (ex == nil) return YES; if ([self _isNoRaiseOnModificationException:ex]) return NO; [ex raise]; return NO; } - (BOOL)updateRow:(NSDictionary *)_row describedByQualifier:(EOSQLQualifier *)_q { NSException *ex; ex = [self updateRowX:_row describedByQualifier:_q]; if (ex == nil) return YES; if ([self _isNoRaiseOnModificationException:ex]) return NO; [ex raise]; return NO; } - (BOOL)deleteRowsDescribedByQualifier:(EOSQLQualifier *)_qualifier { NSException *ex; ex = [self deleteRowsDescribedByQualifierX:_qualifier]; if (ex == nil) return YES; if ([self _isNoRaiseOnModificationException:ex]) return NO; [ex raise]; return NO; } /* fetch operations */ - (NSException *)selectAttributesX:(NSArray *)attributes describedByQualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder lock:(BOOL)lockFlag { NSException *ex; EOSQLExpression *sqlexpr = nil; NSMutableArray *mattrs = (NSMutableArray *)attributes; NSMutableArray *mfetch = (NSMutableArray *)fetchOrder; if (!isOpen) return [[ChannelIsNotOpenedException new] autorelease]; if (attributes == nil) { return [NSException exceptionWithName:NSInvalidArgumentException reason: @"attributes argument for selectAttributes:" @"describedByQualifier:fetchOrder:lock: " @"must not be the nil object" userInfo:nil]; } if ([self isFetchInProgress]) return [AdaptorIsFetchingException exceptionWithAdaptor:self]; if ([self->adaptorContext transactionNestingLevel] == 0) return [NoTransactionInProgressException exceptionWithAdaptor:self]; if (delegateRespondsTo.willSelectAttributes) { EODelegateResponse response; mattrs = [[attributes mutableCopy] autorelease]; mfetch = [[fetchOrder mutableCopy] autorelease]; response = [delegate adaptorChannel:self willSelectAttributes:mattrs describedByQualifier:qualifier fetchOrder:mfetch lock:lockFlag]; if (response == EODelegateRejects) { return [NSException exceptionWithName:@"EODelegateRejects" reason:@"delegate rejected select" userInfo:nil]; } if (response == EODelegateOverrides) return nil; } #if 0 #warning DEBUG LOG, REMOVE! [self logWithFormat:@"fetch qualifier: %@", qualifier]; #endif sqlexpr = [[[self->adaptorContext adaptor] expressionClass] selectExpressionForAttributes:attributes lock:lockFlag qualifier:qualifier fetchOrder:fetchOrder channel:self]; ex = [self evaluateExpressionX:[sqlexpr expressionValueForContext:nil]]; if (ex != nil) return ex; if (delegateRespondsTo.didSelectAttributes) { [delegate adaptorChannel:self didSelectAttributes:mattrs describedByQualifier:qualifier fetchOrder:mfetch lock:lockFlag]; } return nil; } - (NSArray *)describeResults:(BOOL)_beautifyNames { [self subclassResponsibility:_cmd]; return nil; } - (NSArray *)describeResults { return [self describeResults:YES]; } - (NSMutableDictionary *)fetchAttributes:(NSArray *)attributes withZone:(NSZone *)_zone { NSMutableDictionary *row = nil; if (!self->isOpen) [[ChannelIsNotOpenedException new] raise]; if (_zone == NULL) _zone = NSDefaultMallocZone(); if(![self isFetchInProgress]) [[AdaptorIsNotFetchingException exceptionWithAdaptor:self] raise]; if(delegateRespondsTo.willFetchAttributes) { row = [delegate adaptorChannel:self willFetchAttributes:attributes withZone:_zone]; } /* NOTE: primaryFetchAttributes:withZone: have to set the isFetchInProgress status */ if(row == nil) row = [self primaryFetchAttributes:attributes withZone:_zone]; if(row) { if(delegateRespondsTo.didFetchAttributes) row = [delegate adaptorChannel:self didFetchAttributes:row withZone:_zone]; if(delegateRespondsTo.didChangeResultSet) [delegate adaptorChannelDidChangeResultSet:self]; } else { /* Do not set here the isFetchInProgress status since only subclasses can know whether there are more SELECT commands to be executed. Setting the status here to NO will overwrite the adaptor subclass intention. */ if(delegateRespondsTo.didFinishFetching) [delegate adaptorChannelDidFinishFetching:self]; } return row; } - (BOOL)isFetchInProgress { return self->isFetchInProgress; } - (void)cancelFetch { if (!isOpen) [[ChannelIsNotOpenedException new] raise]; self->isFetchInProgress = NO; } - (NSMutableDictionary *)dictionaryWithObjects:(id *)objects forAttributes:(NSArray *)attributes zone:(NSZone *)zone { [self notImplemented:_cmd]; return nil; } - (NSMutableDictionary*)primaryFetchAttributes:(NSArray *)attributes withZone:(NSZone *)zone { [self subclassResponsibility:_cmd]; return nil; } - (BOOL)evaluateExpression:(NSString *)anExpression { [self subclassResponsibility:_cmd]; return NO; } - (NSException *)evaluateExpressionX:(NSString *)_sql { NSException *ex; BOOL ok; ex = nil; ok = NO; NS_DURING ok = [self evaluateExpression:_sql]; NS_HANDLER ex = [localException retain]; NS_ENDHANDLER; if (ex) return [ex autorelease]; if (ok) return nil; return [NSException exceptionWithName:@"EOEvaluationError" reason:@"could not evaluate SQL expression" userInfo:nil]; } - (EOAdaptorContext *)adaptorContext { return self->adaptorContext; } - (EOModel *)describeModelWithTableNames:(NSArray *)tableNames { [self subclassResponsibility:_cmd]; return nil; } - (NSArray *)describeTableNames { [self subclassResponsibility:_cmd]; return nil; } - (BOOL)readTypesForEntity:(EOEntity*)anEntity { [self subclassResponsibility:_cmd]; return NO; } - (BOOL)readTypeForAttribute:(EOAttribute*)anAttribute { [self subclassResponsibility:_cmd]; return NO; } // delegate - (id)delegate { return self->delegate; } - (void)setDelegate:(id)_delegate { self->delegate = _delegate; delegateRespondsTo.willInsertRow = [delegate respondsToSelector: @selector(adaptorChannel:willInsertRow:forEntity:)]; delegateRespondsTo.didInsertRow = [delegate respondsToSelector: @selector(adaptorChannel:didInsertRow:forEntity:)]; delegateRespondsTo.willUpdateRow = [delegate respondsToSelector: @selector(adaptorChannel:willUpdateRow:describedByQualifier:)]; delegateRespondsTo.didUpdateRow = [delegate respondsToSelector: @selector(adaptorChannel:didUpdateRow:describedByQualifier:)]; delegateRespondsTo.willDeleteRows = [delegate respondsToSelector: @selector(adaptorChannel:willDeleteRowsDescribedByQualifier:)]; delegateRespondsTo.didDeleteRows = [delegate respondsToSelector: @selector(adaptorChannel:didDeleteRowsDescribedByQualifier:)]; delegateRespondsTo.willSelectAttributes = [delegate respondsToSelector: @selector(adaptorChannel:willSelectAttributes: describedByQualifier:fetchOrder:lock:)]; delegateRespondsTo.didSelectAttributes = [delegate respondsToSelector: @selector(adaptorChannel:didSelectAttributes: describedByQualifier:fetchOrder:lock:)]; delegateRespondsTo.willFetchAttributes = [delegate respondsToSelector: @selector(adaptorChannel:willFetchAttributes:withZone:)]; delegateRespondsTo.didFetchAttributes = [delegate respondsToSelector: @selector(adaptorChannel:didFetchAttributes:withZone:)]; delegateRespondsTo.didChangeResultSet = [delegate respondsToSelector: @selector(adaptorChannelDidChangeResultSet:)]; delegateRespondsTo.didFinishFetching = [delegate respondsToSelector: @selector(adaptorChannelDidFinishFetching:)]; delegateRespondsTo.willEvaluateExpression = [delegate respondsToSelector: @selector(adaptorChannel:willEvaluateExpression:)]; delegateRespondsTo.didEvaluateExpression = [delegate respondsToSelector: @selector(adaptorChannel:didEvaluateExpression:)]; } - (void)setDebugEnabled:(BOOL)flag { self->debugEnabled = flag; } - (BOOL)isDebugEnabled { return self->debugEnabled; } - (BOOL)isOpen { return self->isOpen; } @end /* EOAdaptorChannel */ #import @implementation EOAdaptorChannel(PrimaryKeyGeneration) // new in EOF2 - (NSDictionary *)primaryKeyForNewRowWithEntity:(EOEntity *)_entity { return nil; } @end /* EOAdaptorChannel(PrimaryKeyGeneration) */ @implementation EOAdaptorChannel(EOF2Additions) - (void)selectAttributes:(NSArray *)_attributes fetchSpecification:(EOFetchSpecification *)_fspec lock:(BOOL)_flag entity:(EOEntity *)_entity { EOSQLQualifier *q; BOOL isOk; q = (EOSQLQualifier *)[_fspec qualifier]; isOk = [self selectAttributes:_attributes describedByQualifier:q fetchOrder:[_fspec sortOrderings] lock:_flag]; if (!isOk) { [NSException raise:@"Select failed" format:@"could not select attributes for fetch spec"]; } } - (void)setAttributesToFetch:(NSArray *)_attributes { [self notImplemented:_cmd]; } - (NSArray *)attributesToFetch { NSLog(@"ERROR(%s): subclasses must override this method!", __PRETTY_FUNCTION__); return nil; } - (NSMutableDictionary *)fetchRowWithZone:(NSZone *)_zone { return [self fetchAttributes:[self attributesToFetch] withZone:_zone]; } @end /* EOAdaptorChannel(EOF2Additions) */ @implementation EOAdaptorChannel(Internals) - (NSArray *)_sortAttributesForSelectExpression:(NSArray *)_attrs { return _attrs; } @end /* EOAdaptorChannel(Internals) */ SOPE/sope-gdl1/GDLAccess/EOEntity+Factory.h0000644000000000000000000000114615004363604017124 0ustar rootroot// $Id: EOEntity+Factory.h 1 2004-08-20 10:38:46Z znek $ #ifndef __GDLAccess_EOEntity_Factory_H__ #define __GDLAccess_EOEntity_Factory_H__ #import @class NSDictionary; @class EOAttribute; @interface EOEntity(AttributeNames) - (NSArray *)attributeNames; @end @interface EOEntity(PrimaryKeys) - (BOOL)isPrimaryKeyAttribute:(EOAttribute *)_attribute; - (unsigned)primaryKeyCount; @end @interface EOEntity(ObjectFactory) - (id)produceNewObjectWithPrimaryKey:(NSDictionary *)_key; - (void)setAttributesOfObjectToEONull:(id)_object; @end #endif /* __GDLAccess_EOEntity_Factory_H__ */ SOPE/sope-gdl1/GDLAccess/EOAttribute.m0000644000000000000000000003637615004363604016232 0ustar rootroot/* EOAttributeOrdering.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "EOAttribute.h" #import "EOModel.h" #import "EOEntity.h" #import "EORelationship.h" #import "EOExpressionArray.h" #import "EOCustomValues.h" #import #import "EOFExceptions.h" @interface NSString(BeautifyAttributeName) - (NSString *)_beautifyAttributeName; @end @implementation EOAttribute static NSString *defaultCalendarFormat = @"%b %d %Y %H:%M"; static EONull *null = nil; + (void)initialize { if (null == nil) null = [[EONull null] retain]; } - (id)initWithName:(NSString*)_name { if ((self = [super init])) { ASSIGN(self->name,_name); self->entity = nil; } return self; } - (id)init { return [self initWithName:nil]; } - (void)dealloc { [self->name release]; [self->calendarFormat release]; [self->clientTimeZone release]; [self->serverTimeZone release]; [self->columnName release]; [self->externalType release]; [self->valueClassName release]; [self->valueType release]; [self->userDictionary release]; self->entity = nil; /* non-retained */ [super dealloc]; } // These methods should be here to let the library work with NeXT foundation - (id)copy { return [self retain]; } - (id)copyWithZone:(NSZone *)_zone { return [self retain]; } // Is equal only if same name; used to make aliasing ordering stable - (NSUInteger)hash { return [self->name hash]; } - (BOOL)setName:(NSString*)_name { if([name isEqual:_name]) return YES; if([entity attributeNamed:_name]) return NO; ASSIGN(name, _name); return YES; } + (BOOL)isValidName:(NSString*)_name { return [EOEntity isValidName:_name]; } - (BOOL)referencesProperty:(id)property { // TODO: still used? return NO; } - (NSString *)expressionValueForContext:(id)context { return (context != nil) ? [context expressionValueForAttribute:self] : columnName; } - (void)setEntity:(EOEntity*)_entity { self->entity = _entity; /* non-retained */ } - (EOEntity *)entity { return self->entity; } - (void)resetEntity { self->entity = nil; } - (BOOL)hasEntity { return (self->entity != nil) ? YES : NO; } - (void)setCalendarFormat:(NSString*)format { ASSIGN(self->calendarFormat, format); } - (NSString *)calendarFormat { return self->calendarFormat; } - (void)setClientTimeZone:(NSTimeZone*)tz { ASSIGN(self->clientTimeZone, tz); } - (NSTimeZone *)clientTimeZone { return self->clientTimeZone; } - (void)setServerTimeZone:(NSTimeZone*)tz { ASSIGN(self->serverTimeZone, tz); } - (NSTimeZone *)serverTimeZone { return self->serverTimeZone; } - (void)setColumnName:(NSString *)_name { ASSIGNCOPY(self->columnName, _name); } - (NSString *)columnName { return self->columnName; } - (void)setExternalType:(NSString *)type { ASSIGNCOPY(self->externalType, type); } - (NSString *)externalType { return self->externalType; } - (void)setValueClassName:(NSString *)_name { ASSIGNCOPY(self->valueClassName, _name); } - (NSString *)valueClassName { return self->valueClassName; } - (void)setValueType:(NSString *)type { ASSIGN(self->valueType, type); } - (NSString *)valueType { return self->valueType; } - (void)setUserDictionary:(NSDictionary *)dict { ASSIGN(self->userDictionary, dict); } - (NSDictionary *)userDictionary { return self->userDictionary; } + (NSString *)defaultCalendarFormat { return defaultCalendarFormat; } - (NSString *)name { return self->name; } /* description */ - (NSString *)description { return [[self propertyList] description]; } /* EOAttributePrivate */ + (EOAttribute*)attributeFromPropertyList:(id)propertyList { NSDictionary *plist = propertyList; EOAttribute *attribute = nil; NSString *timeZoneName; id tmp; attribute = [[[EOAttribute alloc] init] autorelease]; [attribute setName:[plist objectForKey:@"name"]]; [attribute setCalendarFormat:[plist objectForKey:@"calendarFormat"]]; timeZoneName = [plist objectForKey:@"clientTimeZone"]; if (timeZoneName) [attribute setClientTimeZone:[NSTimeZone timeZoneWithName:timeZoneName]]; timeZoneName = [plist objectForKey:@"serverTimeZone"]; if (timeZoneName) [attribute setServerTimeZone:[NSTimeZone timeZoneWithName:timeZoneName]]; [attribute setColumnName: [plist objectForKey:@"columnName"]]; [attribute setExternalType: [plist objectForKey:@"externalType"]]; [attribute setValueClassName:[plist objectForKey:@"valueClassName"]]; [attribute setValueType: [plist objectForKey:@"valueType"]]; [attribute setUserDictionary:[plist objectForKey:@"userDictionary"]]; if ((tmp = [plist objectForKey:@"allowsNull"])) [attribute setAllowsNull:[tmp isEqual:@"Y"]]; else [attribute setAllowsNull:YES]; [attribute setWidth:[[plist objectForKey:@"width"] unsignedIntValue]]; return attribute; } /* WARNING: You should call this method from entity after the relationships were constructed and after the `attributes' array contains the real attributes. */ - (void)replaceStringsWithObjects { } - (id)propertyList { NSMutableDictionary *propertyList; propertyList = [NSMutableDictionary dictionaryWithCapacity:16]; [self encodeIntoPropertyList:propertyList]; return propertyList; } - (int)compareByName:(EOAttribute *)_other { return [[(EOAttribute *)self name] compare:[_other name]]; } /* ValuesConversion */ - (id)convertValue:(id)aValue toClass:(Class)aClass forType:(NSString*)_type { // Check nil/EONull if (aValue == nil) return nil; if (aValue == null) return aValue; // Check if we need conversion; we use is kind of because // a string is not a NSString but some concrete class, so is NSData, // NSNumber and may be other classes if ([aValue isKindOfClass:aClass]) return aValue; // We have to convert the aValue // Try EOCustomValues if ([aValue respondsToSelector:@selector(stringForType:)]) { // Special case if aClass is NSNumber if (aClass == [NSNumber class]) { return [NSNumber numberWithString:[aValue stringForType:_type] type:_type]; } // Even more Special case if aClass is NSCalendar date if (aClass == [NSCalendarDate class]) { /* we enter this section even if the value is a NSDate object, or NSCFDate on Cocoa */ NSCalendarDate *date; NSString *format; format = [self calendarFormat]; if (format == nil) format = [EOAttribute defaultCalendarFormat]; if ([aValue isKindOfClass:[NSDate class]]) { // TBD: this does not catch NSCFDate?! date = [NSCalendarDate dateWithTimeIntervalSince1970: [(NSDate *)aValue timeIntervalSince1970]]; } else { date = [NSCalendarDate dateWithString:[aValue stringForType:_type] calendarFormat:format]; if (date == nil) { NSLog(@"WARN: could not create NSCalendarDate using format %@ " @"from value: %@", format, aValue); } } [date setCalendarFormat:format]; return date; } // See if we can alloc a new aValue and initilize it if ([aClass instancesRespondToSelector: @selector(initWithString:type:)]) { // Note: this is still problematic! Eg NSString instances respond to // initWithString:type:, but NSTemporaryString doesn't. // EOCustomValues contains a lF specific for that situation. return AUTORELEASE([[aClass alloc] initWithString:[aValue stringForType:_type] type:_type]); } } // Try EODatabaseCustomValues if ([aValue respondsToSelector:@selector(dataForType:)]) { // See if we can alloc a new aValue and initilize it if ([aClass instancesRespondToSelector: @selector(initWithData:type:)]) { return AUTORELEASE([[aClass alloc] initWithData:[aValue dataForType:_type] type:_type]); } } // Could not convert if got here return nil; } - (id)convertValueToModel:(id)aValue { id aValueClassName; Class aValueClass; // Check value class from attribute aValueClassName = [self valueClassName]; aValueClass = NSClassFromString(aValueClassName); if (aValueClass == Nil) return aValue; return [self convertValue:aValue toClass:aValueClass forType:[self valueType]]; } @end /* EOAttribute */ @implementation NSString(EOAttributeTypeCheck) - (BOOL)isNameOfARelationshipPath { BOOL result = NO; char buf[[self cStringLength] + 1]; const char *s; s = buf; [self getCString:buf]; if(!isalnum((int)*s) && *s != '@' && *s != '_' && *s != '#') return NO; for(++s; *s; s++) { if(!isalnum((int)*s) && *s != '@' && *s != '_' && *s != '#' && *s != '$' && *s != '.') return NO; if(*s == '.') result = YES; } return result; } @end /* NSString(EOAttributeTypeCheck) */ @implementation EOAttribute(PropertyListCoding) static inline void _addToPropList(NSMutableDictionary *propertyList, id _value, NSString *key) { if (_value != nil) [propertyList setObject:_value forKey:key]; } - (void)encodeIntoPropertyList:(NSMutableDictionary *)_plist { _addToPropList(_plist, self->name, @"name"); _addToPropList(_plist, self->calendarFormat, @"calendarFormat"); _addToPropList(_plist, self->columnName, @"columnName"); _addToPropList(_plist, self->externalType, @"externalType"); _addToPropList(_plist, self->valueClassName, @"valueClassName"); _addToPropList(_plist, self->valueType, @"valueType"); _addToPropList(_plist, self->userDictionary, @"userDictionary"); if (self->clientTimeZone) { #if !LIB_FOUNDATION_LIBRARY [_plist setObject:[self->clientTimeZone name] forKey:@"clientTimeZone"]; #else [_plist setObject:[self->clientTimeZone timeZoneName] forKey:@"clientTimeZone"]; #endif } if (self->serverTimeZone) { #if !LIB_FOUNDATION_LIBRARY [_plist setObject:[self->serverTimeZone name] forKey:@"serverTimeZone"]; #else [_plist setObject:[self->serverTimeZone timeZoneName] forKey:@"serverTimeZone"]; #endif } if (self->width != 0) { [_plist setObject:[NSNumber numberWithUnsignedInt:self->width] forKey:@"width"]; } if (self->flags.allowsNull) { [_plist setObject:[NSString stringWithCString:"Y"] forKey:@"allowsNull"]; } } @end /* EOAttribute(PropertyListCoding) */ @implementation EOAttribute(EOF2Additions) - (void)beautifyName { [self setName:[[self name] _beautifyAttributeName]]; } /* constraints */ - (void)setAllowsNull:(BOOL)_flag { self->flags.allowsNull = _flag ? 1 : 0; } - (BOOL)allowsNull { return self->flags.allowsNull ? YES : NO; } - (void)setWidth:(unsigned)_width { self->width = _width; } - (unsigned)width { return self->width; } - (NSException *)validateValue:(id *)_value { if (_value == NULL) return nil; /* check NULL constraint */ if (!self->flags.allowsNull) { if ((*_value == nil) || (*_value == null)) { NSException *e; NSDictionary *ui; ui = [NSDictionary dictionaryWithObjectsAndKeys: *_value ? *_value : (id)null, @"value", self, @"attribute", nil]; e = [NSException exceptionWithName:@"EOValidationException" reason:@"violated not-null constraint" userInfo:ui]; return e; } } /* check width constraint */ if (self->width != 0) { static Class NSDataClass = Nil; static Class NSStringClass = Nil; if (NSDataClass == nil) NSDataClass = [NSData class]; if (NSStringClass == nil) NSStringClass = [NSString class]; if ([(NSObject *)[*_value class] isKindOfClass:NSDataClass]) { unsigned len; len = [*_value length]; if (len > self->width) { NSException *e; NSDictionary *ui; ui = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithUnsignedInt:self->width], @"maxWidth", [NSNumber numberWithUnsignedInt:len], @"width", *_value ? *_value : (id)null, @"value", self, @"attribute", nil]; e = [NSException exceptionWithName:@"EOValidationException" reason:@"data value exceeds allowed attribute width" userInfo:ui]; return e; } } else if ([(NSObject *)[*_value class] isKindOfClass:NSStringClass]) { unsigned len; len = [*_value cStringLength]; if (len > self->width) { NSException *e; NSDictionary *ui; ui = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithUnsignedInt:self->width], @"maxWidth", [NSNumber numberWithUnsignedInt:len], @"width", *_value ? *_value : (id)null, @"value", self, @"attribute", nil]; e = [NSException exceptionWithName:@"EOValidationException" reason:@"string value exceeds allowed attribute width" userInfo:ui]; return e; } } } return nil; } @end /* EOAttribute(EOF2Additions) */ @implementation NSString(BeautifyAttributeName) - (NSString *)_beautifyAttributeName { // DML Unicode unsigned clen = 0; char *s = NULL; unsigned cnt, cnt2; if ([self length] == 0) return @""; clen = [self cStringLength]; s = malloc(clen + 4); [self getCString:s maxLength:clen]; for (cnt = cnt2 = 0; cnt < clen; cnt++, cnt2++) { if ((s[cnt] == '_') && (s[cnt + 1] != '\0')) { s[cnt2] = toupper(s[cnt + 1]); cnt++; } else if ((s[cnt] == '2') && (s[cnt + 1] != '\0')) { s[cnt2] = s[cnt]; cnt++; cnt2++; s[cnt2] = toupper(s[cnt]); } else s[cnt2] = tolower(s[cnt]); } s[cnt2] = '\0'; #if !LIB_FOUNDATION_LIBRARY { NSString *os; os = [NSString stringWithCString:s]; free(s); return os; } #else return [NSString stringWithCStringNoCopy:s freeWhenDone:YES]; #endif } @end /* NSString(BeautifyAttributeName) */ SOPE/sope-gdl1/GDLAccess/EOAdaptorChannel+Attributes.m0000644000000000000000000000473015004363604021261 0ustar rootroot/* EOAdaptorChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOAdaptorChannel+Attributes.m 1 2004-08-20 10:38:46Z znek $ #import "common.h" #import "EOAdaptorChannel+Attributes.h" #import "EOAdaptorContext.h" #import "EOEntity.h" #import "EOAdaptor.h" #import "EOModel.h" @implementation EOAdaptorChannel(Attributes) - (EOEntity *)_entityForTableName:(NSString *)_tableName { EOModel *model = nil; EOEntity *entity = nil; if (_tableName == nil || [_tableName length] == 0) return nil; model = [[self->adaptorContext adaptor] model]; if ((entity = [model entityNamed:_tableName]) == nil) { NSEnumerator *enumerator = nil; enumerator = [[model entities] objectEnumerator]; while ((entity = [enumerator nextObject])) { if ([[entity externalName] isEqualToString:_tableName]) break; } } if (entity == nil) { model = [self describeModelWithTableNames: [NSArray arrayWithObject:_tableName]]; if ((entity = [model entityNamed:_tableName]) == nil) { NSEnumerator *enumerator = nil; enumerator = [[model entities] objectEnumerator]; while ((entity = [enumerator nextObject])) { if ([[entity externalName] isEqualToString:_tableName]) break; } } } return entity; } - (NSArray *)attributesForTableName:(NSString *)_tableName { return [[self _entityForTableName:_tableName] attributes]; } - (NSArray *)primaryKeyAttributesForTableName:(NSString *)_tableName { return [[self _entityForTableName:_tableName] primaryKeyAttributes]; } @end /* EOAdaptorChannel(Attributes) */ SOPE/sope-gdl1/GDLAccess/EOCustomValues.m0000644000000000000000000001165515004363604016712 0ustar rootroot/* EOAttributeOrdering.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOCustomValues.m 1 2004-08-20 10:38:46Z znek $ #import "common.h" #import "EOCustomValues.h" #if LIB_FOUNDATION_LIBRARY @implementation NSTemporaryString(EOCustomValues) - initWithString:(NSString*)string type:(NSString*)type { return [self initWithString:string]; } @end #endif @implementation NSString(EOCustomValues) + stringWithString:(NSString*)string type:(NSString*)type { // If mutable return a copy if not return self if ([string isKindOfClass:[NSMutableString class]]) return [[NSString alloc] initWithString:string type:type]; else return RETAIN(self); } - initWithString:(NSString*)string type:(NSString*)type { return [self initWithString:string]; } - (NSString*)stringForType:(NSString*)type { // If mutable return a copy if not return self (handled in NSString) return [self copyWithZone:[self zone]]; } - (id)initWithData:(NSData*)data type:(NSString*)type { return [self initWithCString:[data bytes] length:[data length]]; } - (NSData *)dataForType:(NSString *)type { unsigned len = [self cStringLength]; char buf[len + 1]; [self getCString:buf]; return [NSData dataWithBytes:buf length:len]; } @end /* NSString(EOCustomValues) */ @implementation NSData(EOCustomValues) - (id)initWithString:(NSString*)string type:(NSString*)type { unsigned len = [string cStringLength]; char buf[len + 1]; [string getCString:buf]; return [self initWithBytes:buf length:len]; } - (NSString*)stringForType:(NSString*)type { return [NSString stringWithCString:[self bytes] length:[self length]]; } - initWithData:(NSData*)data type:(NSString*)type { return [self initWithBytes:[data bytes] length:[data length]]; } - (NSData*)dataForType:(NSString*)type { return [self copyWithZone:[self zone]]; } @end /* NSData(EOCustomValues) */ @implementation NSNumber(EOCustomValues) + (id)numberWithString:(NSString*)string type:(NSString*)type { char buf[[string cStringLength] + 1]; const char *cstring; [string getCString:buf]; cstring = buf; if ([type cStringLength] == 1) switch ((unsigned char)[type characterAtIndex:0]) { case 'c' : { char value = atoi(cstring); return [NSNumber numberWithChar:value]; } case 'C' : { unsigned char value = atoi(cstring); return [NSNumber numberWithUnsignedChar:value]; } case 's' : { short value = atoi(cstring); return [NSNumber numberWithShort:value]; } case 'S' : { unsigned short value = atoi(cstring); return [NSNumber numberWithUnsignedShort:value]; } case 'i' : { int value = atoi(cstring); return [NSNumber numberWithInt:value]; } case 'I' : { unsigned int value = atoi(cstring); return [NSNumber numberWithUnsignedInt:value]; } case 'l' : { long value = atol(cstring); return [NSNumber numberWithLong:value]; } case 'L' : { unsigned long value = atol(cstring); return [NSNumber numberWithUnsignedLong:value]; } case 'q' : { long long value = atol(cstring); return [NSNumber numberWithLongLong:value]; } case 'Q' : { unsigned long long value = atol(cstring); return [NSNumber numberWithUnsignedLongLong:value]; } case 'f' : { float value = atof(cstring); return [NSNumber numberWithFloat:value]; } case 'd' : { double value = atof(cstring); return [NSNumber numberWithDouble:value]; } } [NSException raise:NSInvalidArgumentException format:@"invalid type `%@' for NSNumber in " @"numberWithString:type:", type]; return nil; } - initWithString:(NSString*)string type:(NSString*)type { (void)AUTORELEASE(self); return RETAIN([NSNumber numberWithString:string type:type]); } - (NSString*)stringForType:(NSString*)type { return [self stringValue]; } @end /* NSNumber(EOCustomValues) */ void EOAccess_EOCustomValues_link(void) { EOAccess_EOCustomValues_link(); } SOPE/sope-gdl1/GDLAccess/EODatabaseContext.h0000644000000000000000000001223415004363604017316 0ustar rootroot/* EODatabaseContext.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EODatabaseContext_h__ #define __EODatabaseContext_h__ #import #import @class NSArray, NSMutableArray, NSDictionary, NSMutableDictionary; @class NSString, NSMutableString; @class EOAdaptorContext; @class EOEntity; @class EOObjectUniquer, EODatabase, EODatabaseContext, EODatabaseChannel; typedef enum { EOUpdateWithOptimisticLocking, EOUpdateWithPessimisticLocking, EOUpdateWithNoLocking, EONoUpdate, } EOUpdateStrategy; struct _EOTransactionScope; extern NSString *EODatabaseContextWillBeginTransactionName; extern NSString *EODatabaseContextDidBeginTransactionName; extern NSString *EODatabaseContextWillRollbackTransactionName; extern NSString *EODatabaseContextDidRollbackTransactionName; extern NSString *EODatabaseContextWillCommitTransactionName; extern NSString *EODatabaseContextDidCommitTransactionName; struct EODatabaseContextModificationQueue; @interface EODatabaseContext : NSObject < EOObjectRegistry > //EOCooperatingObjectStore < EOObjectRegistry > { EOAdaptorContext *adaptorContext; EODatabase *database; NSMutableArray *channels; EOUpdateStrategy updateStrategy; id coordinator; id delegate; /* non-retained */ struct _EOTransactionScope *transactionStackTop; int transactionNestingLevel; // These fields should be in a bitfield but are ivars for debug purposes BOOL isKeepingSnapshots; BOOL isUniquingObjects; /* modified objects */ struct EODatabaseContextModificationQueue *ops; /* statistics */ unsigned int txBeginCount; unsigned int txCommitCount; unsigned int txRollbackCount; } // Initializing instances - (id)initWithDatabase:(EODatabase *)aDatabase; /* accessors */ - (void)setDelegate:(id)_delegate; - (id)delegate; - (EODatabase *)database; // Getting the adaptor context - (EOAdaptorContext*)adaptorContext; // Finding channels - (BOOL)hasBusyChannels; - (BOOL)hasOpenChannels; - (NSArray *)channels; - (id)createChannel; // Controlling transactions - (BOOL)beginTransaction; - (BOOL)commitTransaction; - (BOOL)rollbackTransaction; // Notifying of other transactions - (void)transactionDidBegin; - (void)transactionDidCommit; - (void)transactionDidRollback; // Nesting transactions - (BOOL)canNestTransactions; - (unsigned)transactionNestingLevel; // Setting the update strategy - (void)setUpdateStrategy:(EOUpdateStrategy)aStrategy; - (EOUpdateStrategy)updateStrategy; - (BOOL)keepsSnapshots; // Handle Objects - (void)recordLockedObject:(id)anObj; - (BOOL)isObjectLocked:(id)anObj; - (void)recordUpdatedObject:(id)anObj; - (BOOL)isObjectUpdated:(id)anObj; @end /* EODatabaseContext */ @interface EODatabaseContext(Statistics) - (unsigned int)transactionBeginCount; - (unsigned int)transactionCommitCount; - (unsigned int)transactionRollbackCount; @end /* * Methods used by database classess internally */ @interface EODatabaseContext(Private) - (void)channelDidInit:(id)aChannel; - (void)channelWillDealloc:(id)aChannel; - (void)privateBeginTransaction; - (void)privateCommitTransaction; - (void)privateRollbackTransaction; @end @class EOModel; @interface EODatabaseContext(NewInEOF2) + (void)setContextClassToRegister:(Class)_cclass; + (Class)contextClassToRegister; #if 0 + (EODatabaseContext *)registeredDatabaseContextForModel:(EOModel *)_model editingContext:(id)_ec; - (id)coordinator; #endif /* managing channels */ - (EODatabaseChannel *)availableChannel; - (NSArray *)registeredChannels; - (void)registerChannel:(EODatabaseChannel *)_channel; - (void)unregisterChannel:(EODatabaseChannel *)_channel; @end @class EOFetchSpecification; @interface NSObject(EOF2DelegateMethods) - (BOOL)databaseContext:(EODatabaseContext *)_ctx shouldSelectObjectsWithFetchSpecification:(EOFetchSpecification *)_fspec databaseChannel:(EODatabaseChannel *)_channel; - (void)databaseContext:(EODatabaseContext *)_ctx didSelectObjectsWithFetchSpecification:(EOFetchSpecification *)_fspec databaseChannel:(EODatabaseChannel *)_channel; - (BOOL)databaseContext:(EODatabaseContext *)_ctx shouldUsePessimisticLockWithFetchSpecification:(EOFetchSpecification *)_fspec databaseChannel:(EODatabaseChannel *)_channel; @end #endif /* __EODatabaseContext_h__ */ SOPE/sope-gdl1/GDLAccess/fhs.make0000644000000000000000000000226215004363604015267 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) FHS_INCLUDE_DIR=$(FHS_INSTALL_ROOT)/include/ FHS_BIN_DIR=$(FHS_INSTALL_ROOT)/bin/ FHS_LIB_DIR=$(CONFIGURE_FHS_INSTALL_LIBDIR) NONFHS_LIBDIR="$(GNUSTEP_LIBRARIES)/$(GNUSTEP_TARGET_LDIR)/" NONFHS_LIBNAME="$(LIBRARY_NAME)$(LIBRARY_NAME_SUFFIX)$(SHARED_LIBEXT)" NONFHS_BINDIR="$(GNUSTEP_TOOLS)/$(GNUSTEP_TARGET_LDIR)" fhs-header-dirs :: $(MKDIRS) $(FHS_INCLUDE_DIR)$(libGDLAccess_HEADER_FILES_INSTALL_DIR) fhs-bin-dirs :: $(MKDIRS) $(FHS_BIN_DIR) move-headers-to-fhs :: fhs-header-dirs @echo "moving headers to $(FHS_INCLUDE_DIR) .." mv $(GNUSTEP_HEADERS)$(libGDLAccess_HEADER_FILES_INSTALL_DIR)/*.h \ $(FHS_INCLUDE_DIR)$(libGDLAccess_HEADER_FILES_INSTALL_DIR)/ move-libs-to-fhs :: @echo "moving libs to $(FHS_LIB_DIR) .." mv $(NONFHS_LIBDIR)/$(NONFHS_LIBNAME)* $(FHS_LIB_DIR)/ move-tools-to-fhs :: fhs-bin-dirs @echo "moving tools from $(NONFHS_BINDIR) to $(FHS_BIN_DIR) .." for i in $(TOOL_NAME); do \ mv "$(NONFHS_BINDIR)/$${i}" $(FHS_BIN_DIR); \ done move-to-fhs :: move-headers-to-fhs move-libs-to-fhs move-tools-to-fhs after-install :: move-to-fhs endif SOPE/sope-gdl1/GDLAccess/COPYING.LIB0000644000000000000000000006126115004363604015314 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 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. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-gdl1/GDLAccess/README0000644000000000000000000001357415004363604014540 0ustar rootrootNOTE: this file is outdated! GNU Database Library Access Layer - MDlink patch Version Contained code is derived from GDL - GNU Database Library and is therefore LGPL license. Copyright for GDL has the Free Software Foundation. Changes There are no EOJoin's anymore (only for compability). EORelationships cannot be compound and store source and destination themselves. No compound primary keys are allowed. Uniquing is always enabled. Added "abcX" methods which do not raise exceptions but return them. Static Linking uncomment '#imports' in EOModel.m Intro The GNUstep Database Library is a hierarchy of Objective-C classes that provide a three-tiered architecture for developing database applications. The three-tier architecture is a flexible paradigm for building robust and scalable client/server applications; the three tiers refer to the database, the Application Objects, and the user interface. The separation of the database from the user interface through intermediary Application Objects allows the data to be distributed appropriately across database servers and still have the user interface display data cohesively for the end-user. Business logic, as implemented in the Application Objects, provides the mechanism for consistency and reusability across all your business applications. Entity-relationship modelling is used for describing the Application Objects and how they are mapped to database fields. The GNUstep Database Library represents these models as plain ASCII text files; this allows external programs to be used for constructing and maintaining the models separate from the applications which use them. Differences to GNUstep gdl Datasource objects are missing. ToDo EOQualifier: `isValidQualifierType' from EOAdaptor is not used now. This method is supposed to verify, when a qualifier is constructed, if an attribute can appear inside an expression. Make the relationshipPaths of type GCMutableSet. EOSQLExpresion There is no support now for specifying properties for the tables that appear in the FROM clause; I am thinking specifically at the OUTER specifier required by some servers when you use outer joins. Optimize the generated WHERE clause when the same relationship appears more than one time in the entity. The external query from EOEntity is not used when a fetch operation is unrestricted, i.e. it fetches all the records from the table Class Hierachy NSObject DefaultScannerHandler EOInsertUpdateScannerHandler EOQualifierScannerHandler EOSelectScannerHandler EOAdaptor EOAdaptorChannel EOAdaptorContext EOAttributeOrdering EODatabase EODatabaseChannel EODatabaseContext EOFaultResolver EOArrayFault EOObjectFault EOGenericRecord EOKeySortOrdering EONull < NSCopying > EOObjectUniquer EOQualifierJoinHolder EOQuotedExpression < NSCopying > EOSQLExpression < EOExpressionContext > EODeleteSQLExpression EOInsertSQLExpression EOSelectSQLExpression EOUpdateSQLExpression NSDictionary EOPrimaryKeyDictionary EOSinglePrimaryKeyDictionary EOMultiplePrimaryKeyDictionary NSEnumerator EOSinglePrimaryKeyDictionaryEnumerator EOAttribute EOEntity EOModel EOQualifier EOSQLQualifier < NSCopying > EORelationship EOExpressionArray GCObject GCMutableArray EOFault NSException EOFException DestinationEntityDoesntMatchDefinitionException EOAdaptorException InvalidAttributeException InvalidQualifierException ObjectNotAvailableException PropertyDefinitionException PropertyDefinitionException InvalidNameException InvalidPropertyException InvalidValueTypeException RelationshipMustBeToOneException EOAdaptorException CannotFindAdaptorBundleException DataTypeMappingNotSupportedException InvalidAdaptorBundleException InvalidAdaptorStateException InvalidAdaptorStateException AdaptorIsFetchingException AdaptorIsNotFetchingException ChannelIsNotOpenedException NoTransactionInProgressException TooManyOpenedChannelsException Categories EOAdaptor+Private EOAdaptorContext+Private EOAttribute+EOAttributePrivate EOAttribute+ValuesConversion EODatabase+Private EODatabaseChannel+Private EODatabaseContext+Private EOEntity+EOEntityPrivate EOEntity+ValuesConversion EOJoin+EOJoinPrivate EOModel+EOModelPrivate EORelationship+EORelationshipPrivate NSArray+EOKeyBasedSorting NSData+EOCustomValues NSDictionary+EOKeyValueCoding NSMutableArray+EOKeyBasedSorting NSMutableDictionary+EOKeyValueCoding NSNumber+EOCustomValues NSObject+EOExpression NSObject+EOAdaptorChannelDelegation NSObject+EOAdaptorContextDelegate NSObject+EOAdaptorDelegate NSObject+EOCustomValues NSObject+EODatabaseChannelDelegateProtocol NSObject+EODatabaseChannelNotification NSObject+EODatabaseCustomValues NSObject+EOGenericRecord NSObject+EOKeyValueCoding NSObject+EOKeyValueCodingEONull NSObject+EOUnableToFaultToOne NSString+EOAttributeTypeCheck NSString+EOCustomValues Protocols EOExpressionContext Informal Protocols EOClassMapping EOCustomValues EODatabaseChannelNotification EODatabaseCustomValues EOExpression EOKeyValueCoding EOKeyValueCodingEONull EOUnableToFaultToOne -- Helge Hess (helge@mdlink.de) MDlink online service center, 1998-11-01 SOPE/sope-gdl1/GDLAccess/EOArrayProxy.h0000644000000000000000000000335115004363604016365 0ustar rootroot/* EOArrayProxy.h Copyright (C) 1999 MDlink online service center GmbH, Helge Hess Author: Helge Hess (hh@mdlink.de) Date: 1999 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOArrayProxy.h 1 2004-08-20 10:38:46Z znek $ #ifndef __eoaccess_EOArrayProxy_H__ #define __eoaccess_EOArrayProxy_H__ #import /* * EOArrayProxy class */ @class NSArray, NSString; @class EODatabaseChannel, EOSQLQualifier, EOEntity; @interface EOArrayProxy : NSArray { @private EODatabaseChannel *channel; EOSQLQualifier *qualifier; NSArray *fetchOrder; NSArray *content; } + (id)arrayProxyWithQualifier:(EOSQLQualifier *)_qualifier fetchOrder:(NSArray *)_fetchOrder channel:(EODatabaseChannel *)_channel; // accessors - (BOOL)isFetched; - (EODatabaseChannel *)databaseChannel; - (EOEntity *)entity; - (NSArray *)fetchOrder; - (EOSQLQualifier *)qualifier; // operations - (BOOL)fetch; @end #endif /* __eoaccess_EOArrayProxy_H__ */ SOPE/sope-gdl1/GDLAccess/EOObjectUniquer.h0000644000000000000000000000412215004363604017021 0ustar rootroot/* EOObjectUniquer.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOObjectUniquer_h__ #define __EOObjectUniquer_h__ #import #import @class EOEntity; @class NSDictionary; @class NSArray; typedef struct _EOUniquerRecord { int refCount; id pkey; id entity; id object; id snapshot; } EOUniquerRecord; @interface EOObjectUniquer : NSObject { @protected NSMapTable *primaryKeyToRec; NSMapTable *objectsToRec; struct _EOUniquerRecord *keyRecord; } // Initializing a uniquing dictionary - init; // Transfer self to parent - (void)transferTo:(EOObjectUniquer*)dest objects:(BOOL)isObj andSnapshots:(BOOL)isSnap; // Handling objects - (void)forgetObject:(id)anObj; - (void)forgetAllObjects; - (void)forgetAllSnapshots; - (id)objectForPrimaryKey:(NSDictionary *)aKey entity:(EOEntity *)anEntity; - (EOUniquerRecord *)recordForObject:(id)anObj; - (void)recordObject:(id)anObj primaryKey:(NSDictionary *)aKey entity:(EOEntity *)anEntity snapshot:(NSDictionary *)aSnapshot; @end /* EOObjectUniquer */ #endif /* __EOObjectUniquer_h__ */ /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/EOFExceptions.m0000644000000000000000000001171215004363604016501 0ustar rootroot/* EOFExceptions.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: August 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "EOFExceptions.h" #import "EOEntity.h" #import "EORelationship.h" @implementation EOFException @end /* EOFException */ @implementation ObjectNotAvailableException - initWithEntity:entity andPrimaryKey:key { id _reason = [NSString stringWithFormat:@"A to-one relation could not be " @"resolved for entity %@ and primary key %@", [(EOEntity*)entity name], [key description]]; [self initWithName:@"NSObjectNotAvailableException" reason:_reason userInfo:nil]; return self; } @end /* ObjectNotAvailableException */ @implementation PropertyDefinitionException @end /* PropertyDefinitionException */ @implementation DestinationEntityDoesntMatchDefinitionException - initForDestination:(EOEntity*)destinationEntity andDefinition:(NSString*)definition relationship:(EORelationship*)relationship { id _reason = [NSString stringWithFormat:@"destination entity '%@' does not" @" match definition '%@' in relationship '%@'", [destinationEntity name], definition, [relationship name]]; [self initWithName:NSStringFromClass(object_getClass(self)) reason:_reason userInfo:nil]; return self; } @end /* DestinationEntityDoesntMatchDefinitionException */ @implementation InvalidNameException - initWithName:(NSString*)_name { id _reason = [NSString stringWithFormat:@"invalid name: '%@'", _name]; [self initWithName:NSStringFromClass(object_getClass(self)) reason:_reason userInfo:nil]; return self; } @end /* InvalidNameException */ @implementation InvalidPropertyException - initWithName:propertyName entity:currentEntity { id _reason = [NSString stringWithFormat:@"property '%@' does not exist in " @"entity '%@'", propertyName, [(EOEntity*)currentEntity name]]; [self initWithName:NSStringFromClass(object_getClass(self)) reason:_reason userInfo:nil]; return self; } @end /* InvalidPropertyException */ @implementation RelationshipMustBeToOneException - initWithName:propertyName entity:currentEntity { id _reason = [NSString stringWithFormat:@"property '%@' must be to one in " @"entity '%@' to allow flattened attribute", propertyName, [(EOEntity*)currentEntity name]]; [self initWithName:NSStringFromClass(object_getClass(self)) reason:_reason userInfo:nil]; return self; } @end /* RelationshipMustBeToOneException */ @implementation InvalidValueTypeException - initWithType:type { id _reason = [NSString stringWithFormat:@"unknow value type '%@'", type]; [self initWithName:@"InvalidValueTypeException" reason:_reason userInfo:nil]; return self; } @end @implementation InvalidAttributeException @end /* InvalidAttributeException */ @implementation InvalidQualifierException @end /* InvalidQualifierException */ @implementation EOAdaptorException @end /* EOAdaptorException */ @implementation CannotFindAdaptorBundleException @end /* CannotFindAdaptorBundleException */ @implementation InvalidAdaptorBundleException @end /* InvalidAdaptorBundleException */ @implementation InvalidAdaptorStateException + exceptionWithAdaptor:(id)_adaptor { InvalidAdaptorStateException* exception = [self alloc]; exception->adaptor = _adaptor; return exception; } @end /* InvalidAdaptorStateException */ @implementation DataTypeMappingNotSupportedException @end /* DataTypeMappingNotSupportedException */ @implementation ChannelIsNotOpenedException @end /* ChannelIsNotOpenedException */ @implementation AdaptorIsFetchingException @end /* AdaptorIsFetchingException */ @implementation AdaptorIsNotFetchingException @end /* AdaptorIsNotFetchingException */ @implementation NoTransactionInProgressException @end /* NoTransactionInProgressException */ @implementation TooManyOpenedChannelsException @end /* TooManyOpenedChannelsException */ SOPE/sope-gdl1/GDLAccess/EOAttributeOrdering.m0000644000000000000000000000314515004363604017710 0ustar rootroot/* EOAttributeOrdering.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #import #import "common.h" @implementation EOAttributeOrdering + (id)attributeOrderingWithAttribute:(EOAttribute*)_attribute ordering:(EOOrdering)_ordering { return AUTORELEASE([[EOAttributeOrdering alloc] initWithAttribute:_attribute ordering:_ordering]); } - (id)initWithAttribute:(EOAttribute*)_attribute ordering:(EOOrdering)_ordering { ASSIGN(self->attribute, _attribute); self->ordering = _ordering; return self; } - (EOAttribute *)attribute { return self->attribute; } - (EOOrdering)ordering { return self->ordering; } @end /* EOAttributeOrdering */ SOPE/sope-gdl1/GDLAccess/EOModel.m0000644000000000000000000003170415004363604015315 0ustar rootroot/* EOModel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: August 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "EOModel.h" #import "EOEntity.h" /* Include the code from EOKeyValueCoding.m and EOCustomValues.m here because they contain categories to various classes from Foundation that don't get linked into the client application since no one refers them. The NeXT linker knows how to deal with this but all the other linkers don't... */ #if 0 # import "EOCustomValues.m" #endif void EOModel_linkCategories(void) { void EOAccess_EOCustomValues_link(void); EOAccess_EOCustomValues_link(); } @implementation EOModel - (id)copyWithZone:(NSZone *)_zone { return RETAIN(self); } + (NSString*)findPathForModelNamed:(NSString*)modelName { int i; NSBundle* bundle = [NSBundle mainBundle]; NSString* modelPath = [bundle pathForResource:modelName ofType:@"eomodel"]; NSString* paths[] = { @"~/Library/Models", @"/LocalLibrary/Models", @"/NextLibrary/Models", nil }; if(modelPath) return modelPath; for(i = 0; paths[i]; i++) { bundle = [NSBundle bundleWithPath:paths[i]]; modelPath = [bundle pathForResource:modelName ofType:@"eomodel"]; if(modelPath) return modelPath; } return nil; } - (id)init { if ((self = [super init])) { NSNotificationCenter *nc; nc = [NSNotificationCenter defaultCenter]; [nc addObserver:self selector:@selector(_requireClassDescriptionForClass:) name:@"EOClassDescriptionNeededForClass" object:nil]; [nc addObserver:self selector:@selector(_requireClassDescriptionForEntityName:) name:@"EOClassDescriptionNeededForEntityName" object:nil]; self->entities = [[NSArray alloc] init]; self->entitiesByName = [[NSMutableDictionary alloc] initWithCapacity:4]; self->entitiesByClassName = [[NSMutableDictionary alloc] initWithCapacity:4]; } return self; } - (void)resetEntities { [self->entities makeObjectsPerformSelector:@selector(resetModel)]; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [self resetEntities]; RELEASE(self->entities); RELEASE(self->entitiesByName); RELEASE(self->entitiesByClassName); RELEASE(self->name); RELEASE(self->path); RELEASE(self->adaptorName); RELEASE(self->adaptorClassName); RELEASE(self->connectionDictionary); RELEASE(self->pkeyGeneratorDictionary); RELEASE(self->userDictionary); [super dealloc]; } - (id)initWithContentsOfFile:(NSString*)filename { NSDictionary *propList; propList = [[[NSDictionary alloc] initWithContentsOfFile:filename] autorelease]; if (propList == nil) { [NSException raise:NSInvalidArgumentException format:@"EOModel: Couldn't load model file: %@", filename]; } if ((self = [self initWithPropertyList:propList])) { self->path = [filename copy]; self->name = [[[filename lastPathComponent] stringByDeletingPathExtension] copy]; } return self; } - (id)initWithPropertyList:(id)propertyList { if ((self = [self init]) != nil) { NSDictionary *dict; int i, count; NSArray *propListEntities; if (propertyList == nil) { [NSException raise:NSInvalidArgumentException format: @"EOModel: Argument of initWithPropertyList: must " @"not be the nil object"]; } if (![(dict = propertyList) isKindOfClass:[NSDictionary class]]) { [NSException raise:NSInvalidArgumentException format:@"EOModel: Argument of initWithPropertyList: must " @"be kind of NSDictionary class"]; } self->adaptorName = [[dict objectForKey:@"adaptorName"] copy]; self->adaptorClassName = [[dict objectForKey:@"adaptorClassName"] copy]; self->connectionDictionary = [[dict objectForKey:@"connectionDictionary"] copy]; self->pkeyGeneratorDictionary = [[dict objectForKey:@"pkeyGeneratorDictionary"] copy]; self->userDictionary = [[dict objectForKey:@"userDictionary"] copy]; propListEntities = [dict objectForKey:@"entities"]; flags.errors = NO; [self setCreateMutableObjects:YES]; count = [propListEntities count]; for (i = 0; i < count; i++) { EOEntity *entity; entity = [EOEntity entityFromPropertyList: [propListEntities objectAtIndex:i] model:self]; [self addEntity:entity]; } count = [self->entities count]; for (i = 0; i < count; i++) [[self->entities objectAtIndex:i] replaceStringsWithObjects]; /* Init relationships */ for (i = 0; i < count; i++) { EOEntity *entity; NSArray *rels; entity = [self->entities objectAtIndex:i]; rels = [entity relationships]; /* Replace all the strings in relationships. */ [rels makeObjectsPerformSelector:@selector(replaceStringsWithObjects)]; } /* Another pass to allow properly initialization of flattened relationships. */ for (i = 0; i < count; i++) { EOEntity* entity = [self->entities objectAtIndex:i]; NSArray* rels = [entity relationships]; [rels makeObjectsPerformSelector:@selector(initFlattenedRelationship)]; } /* Init attributes */ for (i = 0; i < count; i++) { EOEntity *entity = [self->entities objectAtIndex:i]; NSArray *attrs = [entity attributes]; [attrs makeObjectsPerformSelector:@selector(replaceStringsWithObjects)]; } [self setCreateMutableObjects:NO]; } return flags.errors ? (void)AUTORELEASE(self), (id)nil : (id)self; } - (id)initWithName:(NSString*)_name { if ((self = [self init])) { ASSIGN(self->name, _name); } return self; } /* class-description notifications */ - (void)_requireClassDescriptionForEntityName:(NSNotification *)_notification { NSString *entityName; if ((entityName = [_notification object])) { EOEntity *entity; if ((entity = [self->entitiesByName objectForKey:entityName])) { EOClassDescription *d; d = [[EOEntityClassDescription alloc] initWithEntity:entity]; [EOClassDescription registerClassDescription:d forClass:NSClassFromString([entity className])]; RELEASE(d); d = nil; } } } - (void)_requireClassDescriptionForClass:(NSNotification *)_notification { Class clazz; NSString *className; EOEntity *entity; EOClassDescription *d; if ((clazz = [_notification object]) == nil) return; if ((className = NSStringFromClass(clazz)) == nil) return; if ((entity = [self->entitiesByClassName objectForKey:className]) == nil) return; d = [[EOEntityClassDescription alloc] initWithEntity:entity]; [EOClassDescription registerClassDescription:d forClass:clazz]; [d release]; d = nil; } /* property list */ - (id)modelAsPropertyList { NSMutableDictionary *model = [NSMutableDictionary dictionaryWithCapacity:64]; int i, count; [model setObject:[[NSNumber numberWithInt:[object_getClass(self) version]] stringValue] forKey:@"EOModelVersion"]; if (name) [model setObject:name forKey:@"name"]; if (adaptorName) [model setObject:adaptorName forKey:@"adaptorName"]; if (adaptorClassName) [model setObject:adaptorClassName forKey:@"adaptorClassName"]; if (connectionDictionary) [model setObject:connectionDictionary forKey:@"connectionDictionary"]; if (pkeyGeneratorDictionary) { [model setObject:pkeyGeneratorDictionary forKey:@"pkeyGeneratorDictionary"]; } if (userDictionary) [model setObject:userDictionary forKey:@"userDictionary"]; if (self->entities && (count = [self->entities count])) { id entitiesArray = [NSMutableArray arrayWithCapacity:count]; [model setObject:entitiesArray forKey:@"entities"]; for (i = 0; i < count; i++) { [entitiesArray addObject: [[entities objectAtIndex:i] propertyList]]; } } return model; } - (BOOL)addEntity:(EOEntity *)entity { NSString * entityName = [entity name]; if ([self->entitiesByName objectForKey:entityName]) return NO; if ([self createsMutableObjects]) [(NSMutableArray*)self->entities addObject:entity]; else { self->entities = [[[self->entities autorelease] mutableCopy] autorelease]; [(NSMutableArray *)self->entities addObject:entity]; self->entities = [self->entities copy]; } [self->entitiesByName setObject:entity forKey:entityName]; [self->entitiesByClassName setObject:entity forKey:[entity className]]; [entity setModel:self]; return YES; } - (void)removeEntityNamed:(NSString*)entityName { id entity; if (entityName == nil) return; entity = [self->entitiesByName objectForKey:entityName]; if ([self createsMutableObjects]) [(NSMutableArray*)self->entities removeObject:entity]; else { self->entities = [AUTORELEASE(self->entities) mutableCopy]; [(NSMutableArray*)self->entities removeObject:entity]; self->entities = [AUTORELEASE(self->entities) copy]; } [self->entitiesByName removeObjectForKey:entityName]; [entity resetModel]; } - (EOEntity *)entityNamed:(NSString *)entityName { return [self->entitiesByName objectForKey:entityName]; } - (NSArray *)referencesToProperty:property { [self notImplemented:_cmd]; return 0; } - (EOEntity *)entityForObject:object { NSString *className; className = NSStringFromClass([object class]); return [self->entitiesByClassName objectForKey:className]; } - (BOOL)incorporateModel:(EOModel*)model { [self notImplemented:_cmd]; return 0; } - (void)setAdaptorName:(NSString*)_adaptorName { id tmp = self->adaptorName; self->adaptorName = [_adaptorName copyWithZone:[self zone]]; RELEASE(tmp); tmp = nil; } - (NSString *)adaptorName { return self->adaptorName; } - (void)setAdaptorClassName:(NSString*)_adaptorClassName { id tmp = self->adaptorClassName; self->adaptorClassName = [_adaptorClassName copyWithZone:[self zone]]; RELEASE(tmp); tmp = nil; } - (NSString *)adaptorClassName { return self->adaptorClassName; } - (void)setConnectionDictionary:(NSDictionary*)_connectionDictionary { ASSIGN(self->connectionDictionary, _connectionDictionary); } - (NSDictionary *)connectionDictionary { return self->connectionDictionary; } - (void)setPkeyGeneratorDictionary:(NSDictionary *)_dict { ASSIGN(self->pkeyGeneratorDictionary, _dict); } - (NSDictionary *)pkeyGeneratorDictionary { return self->pkeyGeneratorDictionary; } - (void)setUserDictionary:(NSDictionary *)_userDictionary { ASSIGN(self->userDictionary, _userDictionary); } - (NSDictionary *)userDictionary { return self->userDictionary; } - (NSString *)path { return self->path; } - (NSString *)name { return self->name; } - (NSArray *)entities { NSMutableArray *ents; int cnt, i; cnt = [self->entities count]; ents = [NSMutableArray arrayWithCapacity:cnt]; for (i = 0; i < cnt; i++) [ents addObject:[self->entities objectAtIndex:i]]; return ents; } /* description */ - (NSString *)description { NSMutableString *ms; NSString *s; ms = [NSMutableString stringWithCapacity:256]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if ((s = [self name])) [ms appendFormat:@" name=%@", s]; if ((s = [self path])) [ms appendFormat:@" path=%@", s]; if ((s = [self adaptorName])) [ms appendFormat:@" adaptor=%@", s]; if ((s = [self adaptorClassName])) [ms appendFormat:@" adaptor-class=%@", s]; [ms appendFormat:@" #entities=%d", (int)[self->entities count]]; [ms appendString:@">"]; return ms; } @end /* EOModel */ @implementation EOModel (EOModelPrivate) - (void)setCreateMutableObjects:(BOOL)flag { if(flags.createsMutableObjects == flag) return; flags.createsMutableObjects = flag; if(flags.createsMutableObjects) self->entities = [AUTORELEASE(self->entities) mutableCopy]; else self->entities = [AUTORELEASE(self->entities) copy]; } - (BOOL)createsMutableObjects { return flags.createsMutableObjects; } - (void)errorInReading { flags.errors = YES; } @end /* EOModel (EOModelPrivate) */ @implementation EOModel(NewInEOF2) - (void)loadAllModelObjects { } @end SOPE/sope-gdl1/GDLAccess/EOKeyComparisonQualifier+SQL.m0000644000000000000000000000445015004363604021333 0ustar rootroot/* EOAdaptorChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOKeyComparisonQualifier+SQL.m 1 2004-08-20 10:38:46Z znek $ #import "EOSQLQualifier.h" #include "common.h" @implementation EOKeyComparisonQualifier(SQLQualifier) /* SQL qualifier generation */ - (EOSQLQualifier *)sqlQualifierForEntity:(EOEntity *)_entity { EOSQLQualifier *q; NSString *format; if (sel_isEqual(self->operator, EOQualifierOperatorEqual)) format = @"%A = %A"; else if (sel_isEqual(self->operator, EOQualifierOperatorNotEqual)) format = @"%A <> %A"; else if (sel_isEqual(self->operator, EOQualifierOperatorLessThan)) format = @"%A < %A"; else if (sel_isEqual(self->operator, EOQualifierOperatorGreaterThan)) format = @"%A > %A"; else if (sel_isEqual(self->operator, EOQualifierOperatorLessThanOrEqualTo)) format = @"%A <= %A"; else if (sel_isEqual(self->operator, EOQualifierOperatorGreaterThanOrEqualTo)) format = @"%A >= %A"; else if (sel_isEqual(self->operator, EOQualifierOperatorLike)) format = @"%A LIKE %A"; else { format = [NSString stringWithFormat:@"%%A %@ %%A", NSStringFromSelector(self->operator)]; } q = [[EOSQLQualifier alloc] initWithEntity:_entity qualifierFormat:format, self->leftKey, self->rightKey]; return AUTORELEASE(q); } @end /* EOKeyComparisonQualifier(SQLQualifier) */ SOPE/sope-gdl1/GDLAccess/EONotQualifier+SQL.m0000644000000000000000000000251015004363604017303 0ustar rootroot/* EOAdaptorChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EONotQualifier+SQL.m 1 2004-08-20 10:38:46Z znek $ #import "EOSQLQualifier.h" #include "common.h" @implementation EONotQualifier(SQLQualifier) /* SQL qualifier generation */ - (EOSQLQualifier *)sqlQualifierForEntity:(EOEntity *)_entity { EOSQLQualifier *q; q = [self->qualifier sqlQualifierForEntity:_entity]; [q negate]; return q; } @end /* EONotQualifier */ SOPE/sope-gdl1/GDLAccess/EOGenericRecord.m0000644000000000000000000000461415004363604016770 0ustar rootroot/* EOGenericRecord.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #import #import #import #import "common.h" #import "EOEntity.h" #import "EOGenericRecord.h" #import "EODatabase.h" #import #import @interface EOClassDescription(ClassDesc) /* TODO: check, whether this can be removed */ + (NSClassDescription *)classDescriptionForEntityName:(NSString *)_entityName; @end @implementation EOGenericRecord(EOAccess) - (id)initWithPrimaryKey:(NSDictionary *)_key entity:(EOEntity *)_entity { /* TODO: is this method ever used? Maybe remove */ EOClassDescription *cd; NSEnumerator *e; NSString *key; if (_entity == nil) { AUTORELEASE(self); NSLog(@"WARNING: tried to create generic record with entity !"); return nil; } cd = (id)[EOClassDescription classDescriptionForEntityName:[_entity name]]; #if DEBUG NSAssert1(cd, @"did not find class description for entity %@", _entity); #endif self = [self initWithEditingContext:nil classDescription:cd globalID:nil]; e = [_key keyEnumerator]; while ((key = [e nextObject])) [self setObject:[_key objectForKey:key] forKey:key]; return self; } - (void)_letDatabasesForget { [EODatabase forgetObject:self]; } /* model */ - (EOEntity *)entity { return [(EOEntityClassDescription *)[self classDescription] entity]; } @end /* EOGenericRecord(EOAccess) */ SOPE/sope-gdl1/GDLAccess/EODelegateResponse.h0000644000000000000000000000025315004363604017474 0ustar rootroot// $Id: EODelegateResponse.h 1 2004-08-20 10:38:46Z znek $ typedef enum { EODelegateRejects, EODelegateApproves, EODelegateOverrides } EODelegateResponse; SOPE/sope-gdl1/GDLAccess/EOGenericRecord.h0000644000000000000000000000234515004363604016762 0ustar rootroot// $Id: EOGenericRecord.h 1 2004-08-20 10:38:46Z znek $ #ifndef __eoaccess_EOGenericRecord_H__ #define __eoaccess_EOGenericRecord_H__ #import @class NSDictionary; @class EOEntity; @interface EOGenericRecord(EOAccess) // Initializing new instances - (id)initWithPrimaryKey:(NSDictionary *)aKey entity:(EOEntity *)anEntity; // Getting the associated entity - (EOEntity *)entity; @end /* * Informal protocol. NOT implemented by NSObject. * Before sending one of this messages the caller must * check if the object responds to them. */ @interface NSObject(EOGenericRecord) /* * Initialize an new instance of an object. * If an enterprise object does not respond * to this method it will receive -init. */ - (id)initWithPrimaryKey:(NSDictionary *)key entity:(EOEntity *)entity; /* * Determines the entity of user defined objects, * when more than one entity uses the same class for its objects. */ - (EOEntity *)entity; /* * Determine the class for object based on its fetched row. * The returned class *must* be a subclass of the class that * receives this method. */ + (Class)classForEntity:(EOEntity *)entity values:(NSDictionary *)values; @end #endif /* __eoaccess_EOGenericRecord_H__ */ SOPE/sope-gdl1/GDLAccess/EOObjectUniquer.m0000644000000000000000000002516715004363604017042 0ustar rootroot/* EOObjectUniquer.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "EOEntity.h" #import "EOObjectUniquer.h" #import "EOPrimaryKeyDictionary.h" #import "EODatabaseFault.h" #import "EOGenericRecord.h" static unsigned uniquerHash(NSMapTable* table, EOUniquerRecord* rec) { // efficient hash for dictionaries is done in the concrete // dictionaries implementation; dictionaries are allocated // from EOPrimaryKeyDictionary concrete subclasses return ((unsigned long)(rec->entity) >> 4L) + ((EOPrimaryKeyDictionary*)(rec->pkey))->fastHash; } static BOOL uniquerCompare(NSMapTable *table, EOUniquerRecord *rec1, EOUniquerRecord *rec2) { // efficient compare between dictionaries is done in the concrete // dictionaries implementation; dictionaries are allocated // from EOPrimaryKeyDictionary concrete subclasses return (rec1->entity == rec2->entity) && [rec1->pkey fastIsEqual:rec2->pkey]; } static NSString* uniqDescription(NSMapTable *t, EOUniquerRecord* rec) { return [NSString stringWithFormat: @"<>", rec->pkey, rec->entity, rec->object, rec->snapshot]; } static void uniquerRetain(NSMapTable *table, EOUniquerRecord* rec) { rec->refCount++; } static void uniquerRelease(NSMapTable *table, EOUniquerRecord *rec) { rec->refCount--; if (rec->refCount <= 0) { RELEASE(rec->pkey); rec->pkey = NULL; RELEASE(rec->entity); rec->entity = NULL; RELEASE(rec->snapshot); rec->snapshot = NULL; Free(rec); rec = NULL; } } static inline EOUniquerRecord *uniquerCreate(id pkey, id entity, id object, id snapshot) { EOUniquerRecord *rec = NULL; rec = (EOUniquerRecord *)Malloc(sizeof(EOUniquerRecord)); rec->refCount = 0; rec->pkey = RETAIN(pkey); rec->entity = RETAIN(entity); rec->object = object; rec->snapshot = RETAIN(snapshot); return rec; } static void uniquerNoAction(NSMapTable * t, const void *_object) { } static NSMapTableKeyCallBacks uniquerKeyMapCallbacks = { (NSUInteger(*)(NSMapTable *, const void *))uniquerHash, (BOOL(*)(NSMapTable *, const void *, const void *))uniquerCompare, (void (*)(NSMapTable *, const void *))uniquerNoAction, (void (*)(NSMapTable *, void *))uniquerNoAction, (NSString *(*)(NSMapTable *, const void *))uniqDescription, (const void *)NULL }; static NSMapTableValueCallBacks uniquerValueMapCallbacks = { (void (*)(NSMapTable *, const void *))uniquerRetain, (void (*)(NSMapTable *, void *))uniquerRelease, (NSString *(*)(NSMapTable *, const void *))uniqDescription }; static int initialHashSize = 1021; @implementation EOObjectUniquer static NSMutableArray *uniquerExtent = nil; static NSRecursiveLock *lock = nil; + (void)initialize { static BOOL isInitialized = NO; if (!isInitialized) { isInitialized = YES; uniquerExtent = [[NSMutableArray alloc] initWithCapacity:16]; // THREAD: lock = [[NSRecursiveLock alloc] init]; } } static inline void _addUniquerInstance(EOObjectUniquer *_uniquer) { [lock lock]; [uniquerExtent addObject:[NSValue valueWithNonretainedObject:_uniquer]]; [lock unlock]; } static inline void _removeUniquerInstance(EOObjectUniquer *_uniquer) { [lock lock]; { int i; for (i = [uniquerExtent count] - 1; i >= 0; i--) { EOObjectUniquer *uniquer; uniquer = [[uniquerExtent objectAtIndex:i] nonretainedObjectValue]; if (uniquer == _uniquer) { [uniquerExtent removeObjectAtIndex:i]; break; } } } [lock unlock]; } // Initializing a uniquing dictionary - (id)init { self->primaryKeyToRec = NSCreateMapTable(uniquerKeyMapCallbacks, uniquerValueMapCallbacks, initialHashSize); #if LIB_FOUNDATION_LIBRARY self->objectsToRec = NSCreateMapTableInvisibleKeysOrValues (NSNonOwnedPointerMapKeyCallBacks, uniquerValueMapCallbacks, initialHashSize, YES, NO); #else self->objectsToRec = NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks, uniquerValueMapCallbacks, initialHashSize); #endif self->keyRecord = uniquerCreate(nil, nil, nil, nil); _addUniquerInstance(self); return self; } - (void)dealloc { [self forgetAllObjects]; _removeUniquerInstance(self); NSFreeMapTable(self->objectsToRec); NSFreeMapTable(self->primaryKeyToRec); if (self->keyRecord) { Free(self->keyRecord); self->keyRecord = NULL; } [super dealloc]; } // Transfer self to parent - (void)transferTo:(EOObjectUniquer *)_dest objects:(BOOL)isKey andSnapshots:(BOOL)isSnap { EOUniquerRecord *key = NULL; EOUniquerRecord *rec = NULL; NSMapEnumerator enumerator = NSEnumerateMapTable(primaryKeyToRec); while(NSNextMapEnumeratorPair(&enumerator, (void**)(&key), (void**)(&rec))) { [_dest recordObject:rec->object primaryKey: isKey ? rec->pkey : nil entity: isKey ? rec->entity : nil snapshot: isSnap ? rec->snapshot : nil]; } [self forgetAllObjects]; } // Handling objects - (void)forgetObject:(id)_object { EOUniquerRecord *rec = NULL; if (_object == nil) return; rec = (EOUniquerRecord *)NSMapGet(self->objectsToRec, _object); if (rec == NULL) return; /* NSLog(@"Uniquer[0x%p]: forget object 0x%p<%s> entity=%@", self, _object, class_get_class_name(*(Class *)_object), [[_object entity] name]); */ if (rec->pkey) NSMapRemove(self->primaryKeyToRec, rec); NSMapRemove(self->objectsToRec, _object); } - (void)forgetAllObjects { NSResetMapTable(self->primaryKeyToRec); NSResetMapTable(self->objectsToRec); } - (void)forgetAllSnapshots { NSMapEnumerator enumerator; EOUniquerRecord *rec = NULL; id key = nil; NSLog(@"uniquer 0x%p forgetAllSnapshots ..", self); enumerator = NSEnumerateMapTable(self->objectsToRec); while (NSNextMapEnumeratorPair(&enumerator, (void**)(&key), (void**)(&rec))) { RELEASE(rec->snapshot); rec->snapshot = nil; } } - (id)objectForPrimaryKey:(NSDictionary *)_key entity:(EOEntity *)_entity { EOUniquerRecord *rec; if (_key == nil || _entity == nil) return nil; if (![_key isKindOfClass:[EOPrimaryKeyDictionary class]]) { [NSException raise:NSInvalidArgumentException format: @"attempt to record object with non " @" EOPrimaryKeyDictionary class in EOObjectUniquer." @"This is a bug in EODatabase/Context/Channel."]; } keyRecord->pkey = _key; keyRecord->entity = _entity; rec = (EOUniquerRecord*)NSMapGet(primaryKeyToRec, keyRecord); return rec ? rec->object : nil; } - (EOUniquerRecord *)recordForObject:(id)_object { return (_object == nil) ? (EOUniquerRecord *)NULL : (EOUniquerRecord *)NSMapGet(self->objectsToRec, _object); } - (void)recordObject:(id)_object primaryKey:(NSDictionary *)_key entity:(EOEntity *)_entity snapshot:(NSDictionary *)_snapshot { EOUniquerRecord *rec = NULL; EOUniquerRecord *orc = NULL; if (_object == nil) return; if ((_key == nil) || (_entity == nil)) { _key = nil; _entity = nil; } if ((_key == nil) && (_snapshot == nil)) return; if (_key && ![_key isKindOfClass:[EOPrimaryKeyDictionary class]]) { [NSException raise:NSInvalidArgumentException format: @"attempt to record object with non " @" EOPrimaryKeyDictionary class in EOObjectUniquer." @"This is a bug in EODatabase/Context/Channel."]; } keyRecord->pkey = _key; keyRecord->entity = _entity; rec = (EOUniquerRecord*)NSMapGet(objectsToRec, _object); if (rec) { if (_key && uniquerCompare(NULL, rec, keyRecord)) { ASSIGN(rec->snapshot, _snapshot); return; } if (_key) { orc = (EOUniquerRecord*)NSMapGet(primaryKeyToRec, keyRecord); if (orc && orc != rec) { if (orc->pkey) NSMapRemove(primaryKeyToRec, orc); NSMapRemove(objectsToRec, orc->object); } NSMapRemove(primaryKeyToRec, rec); } ASSIGN(rec->pkey, _key); ASSIGN(rec->entity, _entity); ASSIGN(rec->snapshot, _snapshot); if (_key) NSMapInsertKnownAbsent(primaryKeyToRec, rec, rec); return; } if (_key) rec = (EOUniquerRecord*)NSMapGet(primaryKeyToRec, keyRecord); if (rec) { if (rec->object == _object) { ASSIGN(rec->snapshot, _snapshot); return; } NSMapRemove(objectsToRec, rec->object); ASSIGN(rec->snapshot, _snapshot); rec->object = _object; NSMapInsertKnownAbsent(objectsToRec, _object, rec); return; } rec = uniquerCreate(_key, _entity, _object, _snapshot); if (_key) NSMapInsertKnownAbsent(primaryKeyToRec, rec, rec); NSMapInsertKnownAbsent(objectsToRec, _object, rec); } /* This method is called by the Boehm's garbage collector when an object is finalized */ - (void)_objectWillFinalize:(id)_object { // printf ("_objectWillFinalize: %p (%s)\n", // _object, class_get_class_name ([_object class])); [self forgetObject:_object]; } + (void)forgetObject:(id)_object { [lock lock]; { int i; for (i = [uniquerExtent count] - 1; i >= 0; i--) { EOObjectUniquer *uniquer; uniquer = [[uniquerExtent objectAtIndex:i] nonretainedObjectValue]; [uniquer forgetObject:_object]; } } [lock unlock]; } @end /* EOObjectUniquer */ SOPE/sope-gdl1/GDLAccess/EOEntity+Factory.m0000644000000000000000000000662715004363604017142 0ustar rootroot/* EOAttributeOrdering.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOEntity+Factory.m 1 2004-08-20 10:38:46Z znek $ #include #include #include #include #include "common.h" @interface NSObject(PKeyInitializer) - (id)initWithPrimaryKey:(NSDictionary *)_pkey entity:(EOEntity *)_entity; @end @implementation EOEntity(AttributeNames) - (NSArray *)attributeNames { NSMutableArray *attrNames = [[[NSMutableArray alloc] init] autorelease]; NSEnumerator *attrs = [self->attributes objectEnumerator]; EOAttribute *attr = nil; while ((attr = [attrs nextObject])) [attrNames addObject:[attr name]]; return attrNames; } @end /* EOEntity(AttributeNames) */ @implementation EOEntity(PrimaryKeys) - (BOOL)isPrimaryKeyAttribute:(EOAttribute *)_attribute { NSEnumerator *pkeys = [self->primaryKeyAttributeNames objectEnumerator]; NSString *aname = [_attribute name]; NSString *n = nil; while ((n = [pkeys nextObject])) { if ([aname isEqualToString:n]) return YES; } return NO; } - (unsigned)primaryKeyCount { return [self->primaryKeyAttributeNames count]; } @end /* EOEntity(PrimaryKeys) */ @implementation EOEntity(ObjectFactory) - (id)produceNewObjectWithPrimaryKey:(NSDictionary *)_key { /* Note: used by LSDBObjectNewCommand */ Class objectClass = Nil; id obj; objectClass = NSClassFromString([self className]); NSAssert(objectClass != nil, @"no enterprise object class set in entity"); obj = [objectClass alloc]; NSAssert(objectClass != nil, @"could not allocate enterprise object"); if ([obj respondsToSelector:@selector(initWithPrimaryKey:entity:)]) [obj initWithPrimaryKey:_key entity:self]; else [obj init]; return AUTORELEASE(obj); } - (void)setAttributesOfObjectToEONull:(id)_object { static EONull *null = nil; NSEnumerator *attrs; EOAttribute *attr; int pkeyCount; if (null == nil) null = [[NSNull null] retain]; attrs = [self->attributes objectEnumerator]; attr = nil; pkeyCount = [self->primaryKeyAttributeNames count]; NSAssert(NSClassFromString([self className]) == [_object class], @"object does not belong to entity"); while ((attr = [attrs nextObject])) { if (pkeyCount > 0) { if ([self isPrimaryKeyAttribute:attr]) { pkeyCount--; continue; } } [_object takeValue:null forKey:[attr name]]; } } @end /* EOEntity(ObjectFactory) */ SOPE/sope-gdl1/GDLAccess/EOArrayProxy.m0000644000000000000000000001230615004363604016372 0ustar rootroot/* EOArrayProxy.m Copyright (C) 1999 MDlink online service center GmbH, Helge Hess Author: Helge Hess (hh@mdlink.de) Date: 1999 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOArrayProxy.m 1 2004-08-20 10:38:46Z znek $ #import "common.h" #import "EOArrayProxy.h" #import "EODatabaseChannel.h" #import "EODatabaseContext.h" #import "EOEntity.h" #import "EOSQLQualifier.h" #import "EOGenericRecord.h" @implementation EOArrayProxy - (id)initWithQualifier:(EOSQLQualifier *)_qualifier fetchOrder:(NSArray *)_fetchOrder channel:(EODatabaseChannel *)_channel { self->qualifier = RETAIN(_qualifier); self->fetchOrder = RETAIN(_fetchOrder); self->channel = RETAIN(_channel); return self; } + (id)arrayProxyWithQualifier:(EOSQLQualifier *)_qualifier fetchOrder:(NSArray *)_fetchOrder channel:(EODatabaseChannel *)_channel { return AUTORELEASE([[self alloc] initWithQualifier:_qualifier fetchOrder:_fetchOrder channel:_channel]); } - (void)dealloc { AUTORELEASE(self->content); RELEASE(self->qualifier); RELEASE(self->fetchOrder); RELEASE(self->channel); [super dealloc]; } // accessors - (BOOL)isFetched { return self->content ? YES : NO; } - (EODatabaseChannel *)databaseChannel { return self->channel; } - (EOEntity *)entity { return [self->qualifier entity]; } - (NSArray *)fetchOrder { return self->fetchOrder; } - (EOSQLQualifier *)qualifier { return self->qualifier; } // operations - (void)clear { RELEASE(self->content); self->content = nil; } - (BOOL)fetch { BOOL inTransaction; BOOL didOpenChannel; NSMutableArray *result; [self clear]; result = [NSMutableArray arrayWithCapacity:16]; didOpenChannel = (![self->channel isOpen]) ? [self->channel openChannel] : NO; if ([self->channel isFetchInProgress]) { [NSException raise:NSInvalidArgumentException format:@"attempt to fetch with busy channel: %@", self]; } inTransaction = [[self->channel databaseContext] transactionNestingLevel] > 0; if (!inTransaction) { if (![[self->channel databaseContext] beginTransaction]) { NSLog(@"WARNING: could not begin transaction to fetch array proxy !"); if (didOpenChannel) [self->channel closeChannel]; return NO; } } if (![self->channel selectObjectsDescribedByQualifier:self->qualifier fetchOrder:self->fetchOrder]) { if (!inTransaction) [[self->channel databaseContext] rollbackTransaction]; if (didOpenChannel) [self->channel closeChannel]; NSLog(@"ERROR: select on array proxy failed .."); return NO; } { // fetch objects NSZone *z = [self zone]; id object; while ((object = [self->channel fetchWithZone:z])) [result addObject:object]; object = nil; } [self->channel cancelFetch]; if (!inTransaction) { if (![[self->channel databaseContext] commitTransaction]) { NSLog(@"WARNING: could not commit array proxy's transaction !"); if (didOpenChannel) [self->channel closeChannel]; return NO; } } if (didOpenChannel) [self->channel closeChannel]; self->content = [result copyWithZone:[self zone]]; return YES; } // turn fault to real array .. void _checkFetch(EOArrayProxy *self) { if (self->content) return; [self fetch]; } // NSArray operations - (id)objectAtIndex:(NSUInteger)_index { _checkFetch(self); return [self->content objectAtIndex:_index]; } - (NSUInteger) count { _checkFetch(self); return [self->content count]; } - (BOOL)isNotEmpty { _checkFetch(self); return [self->content count] > 0 ? YES : NO; } - (NSUInteger)indexOfObjectIdenticalTo:(id)_object { _checkFetch(self); return [self->content indexOfObjectIdenticalTo:_object]; } // NSCopying - (id)copyWithZone:(NSZone*)zone { if (NSShouldRetainWithZone(self, zone)) return RETAIN(self); else { _checkFetch(self); return [[NSArray allocWithZone:zone] initWithArray:self->content copyItems:NO]; } } - (id)mutableCopyWithZone:(NSZone*)zone { _checkFetch(self); return [[NSMutableArray alloc] initWithArray:self->content]; } #if 0 // forwarding - (void)forwardInvocation:(NSInvocation *)_invocation { _checkFetch(self); [_invocation invokeWithTarget:self->content]; } - (retval_t)forward:(SEL)_selector:(arglist_t)_frame { _checkFetch(self); return objc_msg_sendv(self->content, _selector, _frame); } #endif @end SOPE/sope-gdl1/GDLAccess/EOCustomValues.h0000644000000000000000000000476615004363604016712 0ustar rootroot/* EOCustomValues.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOCustomValues_h__ #define __EOCustomValues_h__ #import #import #import /* * Informal protocols to initialize value-instances (used as objects * in the dictionaries for the enterprise objects) and to convert * those values to string or data. * NOT implemented in NSObject */ @interface NSObject(EOCustomValues) - (id)initWithString:(NSString*)string type:(NSString*)type; - (NSString*)stringForType:(NSString*)type; @end @interface NSObject(EODatabaseCustomValues) - (id)initWithData:(NSData*)data type:(NSString*)type; - (NSData*)dataForType:(NSString*)type; @end /* * These categories are added to NSString, NSData and NSNumber classes. */ @interface NSString(EOCustomValues) + stringWithString:(NSString*)string type:(NSString*)type; - (id)initWithString:(NSString*)string type:(NSString*)type; - (NSString*)stringForType:(NSString*)type; - (id)initWithData:(NSData*)data type:(NSString*)type; - (NSData*)dataForType:(NSString*)type; @end @interface NSData(EOCustomValues) - initWithString:(NSString*)string type:(NSString*)type; - (NSString*)stringForType:(NSString*)type; - (id)initWithData:(NSData*)data type:(NSString*)type; - (NSData*)dataForType:(NSString*)type; @end @interface NSNumber(EOCustomValues) + (id)numberWithString:(NSString*)string type:(NSString*)type; - (id)initWithString:(NSString*)string type:(NSString*)type; - (NSString*)stringForType:(NSString*)type; @end #endif /* __EOCustomValues_h__ */ /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/EOFault.h0000644000000000000000000000245215004363604015321 0ustar rootroot// $Id: EOFault.h 1 2004-08-20 10:38:46Z znek $ #ifndef __EOFault_h__ #define __EOFault_h__ #import @class NSArray, NSDictionary, NSString, NSMethodSignature; @class EOFaultHandler; #ifndef __has_attribute #define __has_attribute(x) 0 #endif #if __has_attribute(objc_root_class) __attribute__((objc_root_class)) #endif @interface EOFault { Class isa; EOFaultHandler *faultResolver; } + (void)makeObjectIntoFault:(id)_object withHandler:(EOFaultHandler *)_handler; + (EOFaultHandler *)handlerForFault:(id)_fault; /* Inquire about a fault */ + (BOOL)isFault:(id)object; + (BOOL)isFault; - (BOOL)isFault; + (void)clearFault:(id)fault; + (Class)targetClassForFault:fault; /* Non-Faulting Instance methods */ - (Class)superclass; - (Class)class; + (Class)class; - (BOOL)isKindOfClass:(Class)aClass; - (BOOL)isMemberOfClass:(Class)aClass; - (BOOL)conformsToProtocol:(Protocol *)aProtocol; - (BOOL)respondsToSelector:(SEL)aSelector; + (id)self; - (void)dealloc; - retain; - (void)release; - autorelease; - (NSUInteger)retainCount; - (NSZone*)zone; - (BOOL)isProxy; - (BOOL)isGarbageCollectable; - (NSString *)description; - (NSMethodSignature *)methodSignatureForSelector:(SEL)_selector; @end /* EOFault */ #include #endif /* __EOFault_h__ */ SOPE/sope-gdl1/GDLAccess/EOFaultHandler.m0000644000000000000000000001432415004363604016625 0ustar rootroot/* EOAdaptorChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOFaultHandler.m 1 2004-08-20 10:38:46Z znek $ #include "EOFaultHandler.h" #include "EOFault.h" #include "common.h" #if (defined(__GNU_LIBOBJC__) && (__GNU_LIBOBJC__ >= 20100911)) || defined(APPLE_RUNTIME) || defined(__GNUSTEP_RUNTIME__) # define METHOD_NULL NULL # define class_get_super_class class_getSuperclass # define object_is_instance(object) (object!=nil?YES:NO) # define class_get_instance_method class_getInstanceMethod typedef struct objc_method *Method_t; #endif #if NeXT_RUNTIME # if !defined(METHOD_NULL) # define METHOD_NULL NULL # endif #endif #if defined (__GNUSTEP_RUNTIME__) # define class_get_instance_method class_getInstanceMethod #endif #if !(__GNU_LIBOBJC__ >= 20100911) # define sel_getTypeEncoding(selector) ((selector)->sel_types) #endif @implementation EOFaultHandler - (void)setTargetClass:(Class)_class extraData:(void *)_extraData { self->targetClass = _class; self->extraData = _extraData; } - (Class)targetClass; { return self->targetClass; } - (void *)extraData { return self->extraData; } /* firing */ - (BOOL)shouldPerformInvocation:(NSInvocation *)_invocation { return YES; } - (void)faultWillFire:(EOFault *)_fault { } - (void)completeInitializationOfObject:(id)_object { [self doesNotRecognizeSelector:_cmd]; } /* fault reflection */ - (Class)classForFault:(EOFault *)_fault { #if GNU_RUNTIME && !defined(__GNUSTEP_RUNTIME__) return (object_is_instance(_fault)) ? [self targetClass] : (*(Class *)_fault); #else # warning TODO: add complete implementation for Apple/NeXT runtime! return [self targetClass]; #endif } - (BOOL)respondsToSelector:(SEL)_selector forFault:(EOFault *)_fault { Class class; /* first check whether fault itself responds to selector */ #if GNU_RUNTIME && !defined(__GNUSTEP_RUNTIME__) if (class_get_instance_method(*(Class *)_fault, _selector) != METHOD_NULL) return YES; #else # warning TODO: add implementation for NeXT/Apple runtime! #endif /* then check whether the target class does */ class = [self targetClass]; #if GNU_RUNTIME && !defined(__GNUSTEP_RUNTIME__) return (class_get_instance_method(class, _selector) != NULL) ? YES : NO; #else # warning TODO: use NeXT/Apple runtime function return [(NSObject *)class methodForSelector:_selector] ? YES : NO; #endif } - (BOOL)conformsToProtocol:(Protocol *)_protocol forFault:(EOFault *)_fault { Class class, sClass; #if GNU_RUNTIME && !defined(__GNUSTEP_RUNTIME__) && !(__GNU_LIBOBJC__ >= 20100911) struct objc_protocol_list* protos; int i; class = object_is_instance(_fault) ? [self targetClass] : (Class)_fault; for (protos = class->protocols; protos; protos = protos->next) { for (i = 0; i < protos->count; i++) { if ([protos->list[i] conformsToProtocol:_protocol]) return YES; } } #else # warning TODO: implement on NeXT/Apple runtime! class = [self targetClass]; #endif return ((sClass = [class superclass])) ? [sClass conformsToProtocol:_protocol] : NO; } - (BOOL)isKindOfClass:(Class)_class forFault:(EOFault *)_fault { Class class; #if GNU_RUNTIME && !defined(__GNUSTEP_RUNTIME__) class = object_is_instance(_fault) ? [self targetClass] : (Class)_fault; for (; class != Nil; class = class_get_super_class(class)) { if (class == _class) return YES; } #else # warning TODO: add implementation for NeXT/Apple runtime! class = [self targetClass]; #endif return NO; } - (BOOL)isMemberOfClass:(Class)_class forFault:(EOFault *)_fault { Class class; #if GNU_RUNTIME && !defined(__GNUSTEP_RUNTIME__) class = object_is_instance(_fault) ? [self targetClass] : (Class)_fault; #else # warning TODO: add implementation for NeXT/Apple runtime! class = [self targetClass]; #endif return class == _class ? YES : NO; } - (NSMethodSignature *)methodSignatureForSelector:(SEL)_selector forFault:(EOFault *)_fault { #if NeXT_Foundation_LIBRARY || defined(__GNUSTEP_RUNTIME__) // probably incorrect return [_fault methodSignatureForSelector:_selector]; #else register const char *types = NULL; if (_selector == NULL) // invalid selector return nil; #if GNU_RUNTIME && 0 // GNU runtime selectors may be typed, a lookup may not be necessary types = aSelector->sel_types; #endif /* first check for EOFault's own methods */ #if !(__GNU_LIBOBJC__ >= 20100911) if (types == NULL) { // lookup method for selector struct objc_method *mth; mth = class_get_instance_method(*(Class *)_fault, _selector); if (mth) types = mth->method_types; } /* then check in target class methods */ if (types == NULL) { // lookup method for selector struct objc_method *mth; mth = class_get_instance_method([self targetClass], _selector); if (mth) types = mth->method_types; } #endif #if GNU_RUNTIME // GNU runtime selectors may be typed, a lookup may not be necessary if (types == NULL) types = sel_getTypeEncoding(_selector); #endif if (types == NULL) return nil; return [NSMethodSignature signatureWithObjCTypes:types]; #endif } /* description */ - (NSString *)descriptionForObject:(id)_fault { return [NSString stringWithFormat:@"<%@[0x%p]: on=%@>", NSStringFromClass(*(Class *)_fault), _fault, NSStringFromClass([self targetClass])]; } @end /* EOFaultHandler */ SOPE/sope-gdl1/GDLAccess/EORecordDictionary.m0000644000000000000000000001372515004363604017524 0ustar rootroot/* EOAdaptorChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #import #import #import #import #import #if LIB_FOUNDATION_LIBRARY # include #else # include #endif #if (defined(__GNU_LIBOBJC__) && (__GNU_LIBOBJC__ >= 20100911)) || defined(APPLE_RUNTIME) || defined(__GNUSTEP_RUNTIME__) # include # define method_get_imp method_getImplementation # define class_get_instance_method class_getInstanceMethod #endif #include "EORecordDictionary.h" @implementation EORecordDictionary static NSDictionary *emptyDict = nil; - (id)init { RELEASE(self); if (emptyDict == nil) emptyDict = [[NSDictionary alloc] init]; return (id)[emptyDict retain]; } - (id)initWithObjects:(id *)_objects forKeys:(id *)_keys count:(NSUInteger)_count { if (_count == 0) { RELEASE(self); if (emptyDict == nil) emptyDict = [[NSDictionary alloc] init]; return (id)[emptyDict retain]; } if (_count == 1) { RELEASE(self); return (id)[[NSDictionary alloc] initWithObjects:_objects forKeys:_keys count:_count]; } self->count = _count; while(_count--) { if ((_keys[_count] == nil) || (_objects[_count] == nil)) { [NSException raise:NSInvalidArgumentException format:@"Nil object to be added in dictionary"]; } self->entries[_count].key = RETAIN(_keys[_count]); self->entries[_count].hash = [_keys[_count] hash]; self->entries[_count].value = RETAIN(_objects[_count]); } return self; } - (id)initWithDictionary:(NSDictionary *)dictionary { // TODO: who calls this method? NSEnumerator *keys; unsigned char i; keys = [dictionary keyEnumerator]; self->count = [dictionary count]; for (i = 0; i < self->count; i++) { id key = [keys nextObject]; self->entries[i].key = RETAIN(key); self->entries[i].hash = [key hash]; self->entries[i].value = RETAIN([dictionary objectForKey:key]); } return self; } - (void)dealloc { /* keys are always NSString keys?! */ #if GNU_RUNTIME static Class LastKeyClass = Nil; static IMP keyRelease = 0; static unsigned misses = 0, hits = 0; #endif register unsigned char i; for (i = 0; i < self->count; i++) { register NSString *key = self->entries[i].key; #if GNU_RUNTIME if (*(id *)key != LastKeyClass) { LastKeyClass = *(id *)key; keyRelease = method_get_imp(class_get_instance_method(LastKeyClass, @selector(release))); misses++; } else hits++; keyRelease(key, NULL /* dangerous? */); #if PROF_METHOD_CACHE if (hits % 1000 == 0 && hits != 0) NSLog(@"%s: DB HITS: %d MISSES: %d", __PRETTY_FUNCTION__,hits, misses); #endif #else [key release]; #endif RELEASE(self->entries[i].value); } [super dealloc]; } /* operations */ - (id)objectForKey:(id)aKey { register EORecordDictionaryEntry *e = self->entries; register signed char i; register unsigned hash; #if GNU_RUNTIME static Class LastKeyClass = Nil; static unsigned (*keyHash)(id,SEL) = 0; static BOOL (*keyEq)(id,SEL,id) = 0; #if PROF_METHOD_CACHE static unsigned misses = 0, hits = 0; #endif #endif #if GNU_RUNTIME if (aKey == nil) return nil; if (*(id *)aKey != LastKeyClass) { LastKeyClass = *(id *)aKey; keyHash = (void *) method_get_imp(class_get_instance_method(LastKeyClass, @selector(hash))); keyEq = (void *) method_get_imp(class_get_instance_method(LastKeyClass, @selector(isEqual:))); } hash = keyHash(aKey, NULL /* dangerous? */); #else hash = [aKey hash]; #endif for (i = (self->count - 1); i >= 0; i--, e++) { if (e->hash != hash) continue; if (e->key == aKey) return e->value; #if GNU_RUNTIME if (keyEq(e->key, NULL /* dangerous? */, aKey)) return e->value; #else if ([e->key isEqual:aKey]) return e->value; #endif } return nil; } - (NSUInteger)count { return self->count; } - (BOOL)isNotEmpty { return self->count > 0 ? YES : NO; } - (NSEnumerator *)keyEnumerator { return [[[_EORecordDictionaryKeyEnumerator alloc] initWithDictionary:self firstEntry:self->entries count:self->count] autorelease]; } @end /* NSConcreteSmallDictionary */ @implementation _EORecordDictionaryKeyEnumerator - (id)initWithDictionary:(EORecordDictionary *)_dict firstEntry:(EORecordDictionaryEntry *)_firstEntry count:(unsigned char)_count { self->dict = RETAIN(_dict); self->currentEntry = _firstEntry; self->count = _count; return self; } - (void)dealloc { RELEASE(self->dict); [super dealloc]; } - (id)nextObject { if (self->count > 0) { id obj; obj = self->currentEntry->key; self->currentEntry++; self->count--; return obj; } return nil; } @end /* _NSConcreteSmallDictionaryKeyEnumerator */ SOPE/sope-gdl1/GDLAccess/GDLAccess-Info.plist0000644000000000000000000000133215004363604017343 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable GDLAccess CFBundleGetInfoString CFBundleIdentifier org.opengroupware.SOPE.gdl1 CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType FMWK CFBundleShortVersionString CFBundleSignature ???? CFBundleVersion 4.5 SOPE/sope-gdl1/GDLAccess/EOAdaptorGlobalID.h0000644000000000000000000000113515004363604017173 0ustar rootroot// $Id: EOAdaptorGlobalID.h 1 2004-08-20 10:38:46Z znek $ #ifndef __EOAdaptorGlobalID_H__ #define __EOAdaptorGlobalID_H__ #include @class EOKeyGlobalID, NSDictionary; @interface EOAdaptorGlobalID : EOGlobalID < NSCopying > { @protected EOGlobalID *gid; NSDictionary *conDict; } - (id)initWithGlobalID:(EOGlobalID *)_gid connectionDictionary:(NSDictionary *)_conDict; - (EOGlobalID *)globalID; - (NSDictionary *)connectionDictionary; - (BOOL)isEqual:(id)_obj; - (BOOL)isEqualToEOAdaptorGlobalID:(EOAdaptorGlobalID *)_gid; @end #endif /* __EOAdaptorGlobalID_H__ */ SOPE/sope-gdl1/GDLAccess/EOAdaptorGlobalID.m0000644000000000000000000000423515004363604017204 0ustar rootroot/* EOArrayProxy.h Copyright (C) 1999 MDlink online service center GmbH, Helge Hess Author: Helge Hess (hh@mdlink.de) Date: 1999 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOAdaptorGlobalID.m 1 2004-08-20 10:38:46Z znek $ #include #include "common.h" @implementation EOAdaptorGlobalID - (id)initWithGlobalID:(EOGlobalID *)_gid connectionDictionary:(NSDictionary *)_conDict { if ((self = [super init])) { ASSIGN(self->gid, _gid); ASSIGN(self->conDict, _conDict); } return self; } - (void)dealloc { RELEASE(self->gid); RELEASE(self->conDict); [super dealloc]; } - (EOGlobalID *)globalID { return self->gid; } - (NSDictionary *)connectionDictionary { return self->conDict; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { return RETAIN(self); } /* equality */ - (BOOL)isEqual:(id)_obj { if ([_obj isKindOfClass:[EOAdaptorGlobalID class]]) return [self isEqualToEOAdaptorGlobalID:_obj]; return NO; } - (BOOL)isEqualToEOAdaptorGlobalID:(EOAdaptorGlobalID *)_gid { if ([[_gid globalID] isEqual:self->gid] && [[_gid connectionDictionary] isEqual:self->conDict]) return YES; return NO; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"%@: globalID: %@ connectionDictionary: %@", [super description], self->gid, self->conDict]; } @end /* SkyDBGlobalKey */ SOPE/sope-gdl1/GDLAccess/EOQualifierScanner.h0000644000000000000000000000316415004363604017502 0ustar rootroot/* EOQualifierScanner.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Helge Hess Date: September 1996 November 1999 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOQualifierScanner.h 1 2004-08-20 10:38:46Z znek $ #ifndef __EOAccess_EOQualifierScanner_H__ #define __EOAccess_EOQualifierScanner_H__ #if !LIB_FOUNDATION_LIBRARY # import "DefaultScannerHandler.h" #else # import #endif @class EOEntity; @interface EOQualifierScannerHandler : DefaultScannerHandler { EOEntity *entity; } - (void)setEntity:(EOEntity *)entity; @end @interface EOQualifierEnumScannerHandler : DefaultEnumScannerHandler { EOEntity *entity; } - (void)setEntity:(EOEntity *)entity; @end #endif /* __EOAccess_EOQualifierScanner_H__ */ SOPE/sope-gdl1/GDLAccess/EOModelGroup.h0000644000000000000000000000417415004363604016326 0ustar rootroot// $Id: EOModelGroup.h 1 2004-08-20 10:38:46Z znek $ #ifndef __EOAccess_EOModelGroup_H__ #define __EOAccess_EOModelGroup_H__ #import @class NSDictionary; @class EOGlobalID, EOFetchSpecification; @class EOModelGroup, EOModel, EOEntity, EORelationship; @protocol EOModelGroupClassDelegation < NSObject > - (EOModelGroup *)defaultModelGroup; @end @protocol EOModelGroupDelegation < NSObject > - (Class)entity:(EOEntity *)_entity classForObjectWithGlobalID:(EOGlobalID *)_oid; - (Class)entity:(EOEntity *)_entity failedToLookupClassNamed:(NSString *)_className; - (EOEntity *)relationship:(EORelationship *)_relship failedToLookupDestinationNamed:(NSString *)_entityName; - (EOEntity *)subEntityForEntity:(EOEntity *)_entity primaryKey:(NSDictionary *)_pkey isFinal:(BOOL *)_flag; - (EOModel *)modelGroup:(EOModelGroup *)_group entityNamed:(NSString *)_name; - (EORelationship *)entity:(EOEntity *)_entity relationshipForRow:(NSDictionary *)_row relationship:(EORelationship *)_relship; @end @class NSArray, NSMutableDictionary; @interface EOModelGroup : NSObject { NSMutableDictionary *nameToModel; id delegate; /* non-retained */ } + (void)setDefaultGroup:(EOModelGroup *)_group; + (EOModelGroup *)defaultGroup; + (EOModelGroup *)globalModelGroup; /* class delegate */ + (void)setClassDelegate:(id)_delegate; + (id)classDelegate; /* instance delegate */ - (void)setDelegate:(id)_delegate; - (id)delegate; /* models */ - (void)addModel:(EOModel *)_model; - (void)removeModel:(EOModel *)_model; - (EOModel *)modelNamed:(NSString *)_name; - (NSArray *)modelNames; - (NSArray *)models; - (EOModel *)modelWithPath:(NSString *)_path; - (EOModel *)addModelWithFile:(NSString *)_path; - (void)loadAllModelObjects; /* entities */ - (EOEntity *)entityForObject:(id)_object; - (EOEntity *)entityNamed:(NSString *)_name; - (EOFetchSpecification *)fetchSpecificationNamed:(NSString *)_name entityNamed:(NSString *)_entityName; @end #endif /* __EOAccess_EOModelGroup_H__ */ SOPE/sope-gdl1/GDLAccess/eoaccess.m0000644000000000000000000000575515004363604015625 0ustar rootroot/* EOAdaptorChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: eoaccess.m 1 2004-08-20 10:38:46Z znek $ #include "GDLAccess.h" #include "EOArrayProxy.h" @implementation GDLAccess - (void)_staticLinkClasses { [EOAdaptor class]; [EOAdaptorChannel class]; [EOAdaptorContext class]; [EOArrayProxy class]; [EOAttribute class]; [EOAttributeOrdering class]; [EODatabase class]; [EODatabaseChannel class]; [EODatabaseContext class]; [EOEntity class]; [EOFException class]; [ObjectNotAvailableException class]; [PropertyDefinitionException class]; [DestinationEntityDoesntMatchDefinitionException class]; [InvalidNameException class]; [InvalidPropertyException class]; [RelationshipMustBeToOneException class]; [InvalidValueTypeException class]; [InvalidAttributeException class]; [InvalidQualifierException class]; [EOAdaptorException class]; [CannotFindAdaptorBundleException class]; [InvalidAdaptorBundleException class]; [InvalidAdaptorStateException class]; [DataTypeMappingNotSupportedException class]; [ChannelIsNotOpenedException class]; [AdaptorIsFetchingException class]; [AdaptorIsNotFetchingException class]; [NoTransactionInProgressException class]; [TooManyOpenedChannelsException class]; [EOModel class]; [EOObjectUniquer class]; [EOPrimaryKeyDictionary class]; [EOSQLQualifier class]; [EOQuotedExpression class]; [EORelationship class]; [EOSQLExpression class]; #if 0 [EOSelectSQLExpression class]; [EOInsertSQLExpression class]; [EOUpdateSQLExpression class]; [EODeleteSQLExpression class]; #endif } - (void)_staticLinkCategories { } - (void)_staticLinkModules { } @end /* GDLAccess */ SOPE/sope-gdl1/GDLAccess/Version0000644000000000000000000000004515004363604015215 0ustar rootroot# version file SUBMINOR_VERSION:=63 SOPE/sope-gdl1/GDLAccess/EODatabaseFaultResolver.m0000644000000000000000000002077515004363604020505 0ustar rootroot/* EODatabaseFaultResolver.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 Author: Helge Hess Date: 1999 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "EODatabaseFaultResolver.h" #import "EODatabaseChannel.h" #import "EODatabaseContext.h" #import "EOEntity.h" #import "EODatabaseFault.h" #import "EOSQLQualifier.h" #import "EOGenericRecord.h" @implementation EODatabaseFaultResolver - (id)initWithDatabaseChannel:(EODatabaseChannel *)aChannel zone:(NSZone *)aZone targetClass:(Class)_targetClass { if ((self = [super init])) { self->channel = aChannel; self->targetClass = _targetClass; self->zone = aZone; self->faultReferences = 0; } return self; } - (BOOL)fault { return NO; } - (EODatabaseChannel *)databaseChannel { return self->channel; } - (Class)targetClass; { return self->targetClass; } - (NSDictionary *)primaryKey { return nil; } - (EOEntity *)entity { return nil; } - (EOSQLQualifier *)qualifier { return nil; } - (NSArray *)fetchOrder { return nil; } @end /* EODatabaseFaultResolver */ @implementation EOArrayFault - (id)initWithQualifier:(EOSQLQualifier *)aQualifier fetchOrder:(NSArray *)aFetchOrder databaseChannel:(EODatabaseChannel *)aChannel zone:(NSZone *)aZone targetClass:(Class)_targetClass { if ((self = [super initWithDatabaseChannel:aChannel zone:aZone targetClass:_targetClass])) { self->qualifier = RETAIN(aQualifier); self->fetchOrder = RETAIN(aFetchOrder); NSAssert([(NSObject *)self->targetClass isKindOfClass:[NSArray class]], @"target class of an array fault is not an array class"); } return self; } - (void)dealloc { RELEASE(self->qualifier); RELEASE(self->fetchOrder); [super dealloc]; } - (EOEntity *)entity { return [self->qualifier entity]; } - (EOSQLQualifier *)qualifier { return self->qualifier; } - (NSArray *)fetchOrder { return self->fetchOrder; } - (void)completeInitializationOfObject:(id)_fault { unsigned int oldRetainCount; BOOL inTransaction; NSAssert([(NSObject *)self->targetClass isKindOfClass:[NSArray class]], @"target class of an array fault is not an array class"); oldRetainCount = [_fault retainCount]; [EOFault clearFault:_fault]; NSAssert([(id)_fault init] == _fault, @"init modified fault reference .."); NSAssert([_fault isKindOfClass:[NSArray class]], @"resolved-object of an array fault is not of an array class"); if ([self->channel isFetchInProgress]) { [NSException raise:NSInvalidArgumentException format:@"attempt to fault with busy channel: %@", self]; } inTransaction = [[self->channel databaseContext] transactionNestingLevel] > 0; if (!inTransaction) { if (![[self->channel databaseContext] beginTransaction]) { [NSException raise:@"DBFaultResolutionException" format:@"could not begin transaction to resolve fault !"]; } } if (![self->channel selectObjectsDescribedByQualifier:self->qualifier fetchOrder:self->fetchOrder]) { if (!inTransaction) [[self->channel databaseContext] rollbackTransaction]; [NSException raise:@"DBFaultResolutionException" format:@"select for fault failed !"]; } { // fetch objects id object; while ((object = [self->channel fetchWithZone:zone])) { if (![object isKindOfClass:[EOGenericRecord class]]) { NSLog(@"Object is of class %@", NSStringFromClass([object class])); abort(); } NSAssert([object isKindOfClass:[EOGenericRecord class]], @"fetched object is not a EOGenericRecord .."); [(id)_fault addObject:object]; } object = nil; } [self->channel cancelFetch]; if (!inTransaction) { if (![[self->channel databaseContext] commitTransaction]) { NSLog(@"WARNING: could not commit fault's transaction !"); [NSException raise:@"DBFaultResolutionException" format:@"could not commit fault's transaction !"]; } } #if MOF2_DEBUG if ([fault retainCount] != oldRetainCount) { NSLog(@"fault retain count does not match replacement (old=%d, new=%d)", oldRetainCount, [fault retainCount]); } #endif NSAssert([_fault retainCount] == oldRetainCount, @"fault retain count does not match replacement's retain count"); } - (NSString *)descriptionForObject:(id)_fault { return [NSString stringWithFormat: @"", _fault, qualifier, fetchOrder, channel]; } @end /* EOArrayFault */ @implementation EOObjectFault - (id)initWithPrimaryKey:(NSDictionary *)_key entity:(EOEntity *)anEntity databaseChannel:(EODatabaseChannel *)aChannel zone:(NSZone *)aZone targetClass:(Class)_targetClass { [super initWithDatabaseChannel:aChannel zone:aZone targetClass:_targetClass]; self->entity = RETAIN(anEntity); self->primaryKey = RETAIN(_key); return self; } - (void)dealloc { RELEASE(self->entity); RELEASE(self->primaryKey); [super dealloc]; } - (NSDictionary*)primaryKey { return self->primaryKey; } - (EOEntity *)entity { return self->entity; } - (void)completeInitializationOfObject:(id)_fault { EOSQLQualifier *qualifier = nil; BOOL channelIsOpen = YES; BOOL inTransaction = YES; id object = nil; if ([self->channel isFetchInProgress]) { [NSException raise:NSInvalidArgumentException format:@"attempt to fault with busy channel: %@", self]; } qualifier = [EOSQLQualifier qualifierForPrimaryKey:primaryKey entity:self->entity]; if (qualifier == nil) { [NSException raise:NSInvalidArgumentException format:@"could not build qualifier for fault: %@", self]; } channelIsOpen = [self->channel isOpen]; if (!channelIsOpen) { if (![self->channel openChannel]) goto done; } inTransaction = [[self->channel databaseContext] transactionNestingLevel] != 0; if (!inTransaction) { if (![[self->channel databaseContext] beginTransaction]) { if (!channelIsOpen) [self->channel closeChannel]; goto done; } } if (![self->channel selectObjectsDescribedByQualifier:qualifier fetchOrder:nil]) { if (!inTransaction) { [[self->channel databaseContext] rollbackTransaction]; if (!channelIsOpen) [self->channel closeChannel]; } goto done; } // Fetch the object object = [self->channel fetchWithZone:zone]; // The fetch failed! if (object == nil) { [self->channel cancelFetch]; if (!inTransaction) [[self->channel databaseContext] rollbackTransaction]; if (!channelIsOpen) [self->channel closeChannel]; goto done; } // Make sure we only fetched one object if ([self->channel fetchWithZone:zone]) object = nil; [self->channel cancelFetch]; if (!inTransaction) { if (![[self->channel databaseContext] commitTransaction]) object = nil; if (!channelIsOpen) [self->channel closeChannel]; } done: if (object != _fault) { if ([EOFault isFault:_fault]) [EOFault clearFault:_fault]; [(id)_fault unableToFaultWithPrimaryKey:primaryKey entity:self->entity databaseChannel:self->channel]; } } - (NSString *)descriptionForObject:(id)_fault { return [NSString stringWithFormat: @"", _fault, NSStringFromClass(targetClass), [entity name], [primaryKey description], [channel description]]; } @end /* EOObjectFault */ SOPE/sope-gdl1/GDLAccess/EONull.h0000644000000000000000000000025615004363604015160 0ustar rootroot// $Id: EONull.h 1 2004-08-20 10:38:46Z znek $ #ifndef __eoaccess_EONull_H__ #define __eoaccess_EONull_H__ #import #endif /* __eoaccess_EONull_H__ */ SOPE/sope-gdl1/GDLAccess/EOAttribute.h0000644000000000000000000000757615004363604016225 0ustar rootroot/* EOAttribute.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: August 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOAttribute_h__ #define __EOAttribute_h__ #import #import #import @class NSString, NSTimeZone, NSDate, NSException; @class NSMutableArray; @class EOEntity; @interface EOAttribute : NSObject { NSString *name; NSString *calendarFormat; NSTimeZone *clientTimeZone; NSTimeZone *serverTimeZone; NSString *columnName; NSString *externalType; NSString *valueClassName; NSString *valueType; NSDictionary *userDictionary; EOEntity *entity; /* non-retained */ unsigned width; struct { int allowsNull:1; int reserved:31; } flags; } /* Initializing new instances */ - (id)initWithName:(NSString *)name; /* Accessing the entity */ - (void)setEntity:(EOEntity*)entity; - (EOEntity*)entity; - (void)resetEntity; - (BOOL)hasEntity; /* Accessing the name */ - (BOOL)setName:(NSString *)name; - (NSString *)name; + (BOOL)isValidName:(NSString *)name; /* Accessing date information */ + (NSString *)defaultCalendarFormat; - (void)setCalendarFormat:(NSString *)format; - (NSString *)calendarFormat; - (void)setClientTimeZone:(NSTimeZone*)tz; - (NSTimeZone*)clientTimeZone; - (void)setServerTimeZone:(NSTimeZone*)tz; - (NSTimeZone*)serverTimeZone; /* Accessing external definitions */ - (void)setColumnName:(NSString *)columnName; - (NSString *)columnName; - (void)setExternalType:(NSString *)type; - (NSString *)externalType; /* Accessing value type information */ - (void)setValueClassName:(NSString *)name; - (NSString *)valueClassName; - (void)setValueType:(NSString *)type; - (NSString *)valueType; /* Checking type information */ - (BOOL)referencesProperty:property; /* Accessing the user dictionary */ - (void)setUserDictionary:(NSDictionary*)dictionary; - (NSDictionary*)userDictionary; /* Obsolete. This method always return NO, because you should always release a property. */ - (BOOL)referencesProperty:property; @end @interface EOAttribute (EOAttributePrivate) + (EOAttribute*)attributeFromPropertyList:(id)propertyList; - (void)replaceStringsWithObjects; - (id)propertyList; @end /* EOAttribute (EOAttributePrivate) */ @interface EOAttribute(ValuesConversion) - (id)convertValue:(id)aValue toClass:(Class)aClass forType:(NSString *)aValueType; - (id)convertValueToModel:(id)aValue; @end /* EOAttribute (ValuesConversion) */ @interface NSString (EOAttributeTypeCheck) - (BOOL)isNameOfARelationshipPath; @end @class NSMutableDictionary; @interface EOAttribute(PropertyListCoding) - (void)encodeIntoPropertyList:(NSMutableDictionary *)_plist; @end @interface EOAttribute(EOF2Additions) - (void)beautifyName; /* constraints */ - (void)setAllowsNull:(BOOL)_flag; - (BOOL)allowsNull; - (void)setWidth:(unsigned)_width; - (unsigned)width; - (NSException *)validateValue:(id *)_value; @end #endif /* __EOAttribute_h__ */ /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/EOQualifier+SQL.m0000644000000000000000000001023415004363604016624 0ustar rootroot/* EOAdaptorChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOQualifier+SQL.m 1 2004-08-20 10:38:46Z znek $ #include "EOSQLExpression.h" #include "EOSQLQualifier.h" #include #include "common.h" @implementation EOAndQualifier(SQLGeneration) - (NSString *)sqlStringForSQLExpression:(EOSQLExpression *)_sqlExpr { return [_sqlExpr sqlStringForConjoinedQualifiers:[self qualifiers]]; } - (EOQualifier *)schemaBasedQualifierWithRootEntity:(EOEntity *)_entity { NSArray *array; id objects[self->count + 1]; unsigned i; IMP objAtIdx; objAtIdx = [self->qualifiers methodForSelector:@selector(objectAtIndex:)]; for (i = 0; i < self->count; i++) { id q, newq; q = objAtIdx(self->qualifiers, @selector(objectAtIndex:), i); newq = [q schemaBasedQualifierWithRootEntity:_entity]; if (newq == nil) newq = q; objects[i] = newq; } array = [NSArray arrayWithObjects:objects count:self->count]; return [[[[self class] alloc] initWithQualifierArray:array] autorelease]; } @end /* EOAndQualifier(SQLGeneration) */ @implementation EOOrQualifier(SQLGeneration) - (NSString *)sqlStringForSQLExpression:(EOSQLExpression *)_sqlExpr { return [_sqlExpr sqlStringForDisjoinedQualifiers:[self qualifiers]]; } - (EOQualifier *)schemaBasedQualifierWithRootEntity:(EOEntity *)_entity { NSArray *array; id objects[self->count + 1]; unsigned i; IMP objAtIdx; objAtIdx = [self->qualifiers methodForSelector:@selector(objectAtIndex:)]; for (i = 0; i < self->count; i++) { id q, newq; q = objAtIdx(self->qualifiers, @selector(objectAtIndex:), i); newq = [q schemaBasedQualifierWithRootEntity:_entity]; if (newq == nil) newq = q; objects[i] = newq; } array = [NSArray arrayWithObjects:objects count:self->count]; return [[[[self class] alloc] initWithQualifierArray:array] autorelease]; } @end /* EOOrQualifier(SQLGeneration) */ @implementation EONotQualifier(SQLGeneration) - (NSString *)sqlStringForSQLExpression:(EOSQLExpression *)_sqlExpr { return [_sqlExpr sqlStringForNegatedQualifier:[self qualifier]]; } - (EOQualifier *)schemaBasedQualifierWithRootEntity:(EOEntity *)_entity { EOQualifier *sq; sq = [(id)self->qualifier schemaBasedQualifierWithRootEntity:_entity]; if (sq == self->qualifier) return self; sq = [[EONotQualifier alloc] initWithQualifier:sq]; return [sq autorelease]; } @end /* EONotQualifier(SQLGeneration) */ @implementation EOKeyValueQualifier(SQLGeneration) - (NSString *)sqlStringForSQLExpression:(EOSQLExpression *)_sqlExpr { return [_sqlExpr sqlStringForKeyValueQualifier:self]; } - (EOQualifier *)schemaBasedQualifierWithRootEntity:(EOEntity *)_entity { NSLog(@"ERROR(%s): subclasses need to override this method!", __PRETTY_FUNCTION__); return nil; } @end /* EOKeyValueQualifier(SQLGeneration) */ @implementation EOKeyComparisonQualifier(SQLGeneration) - (NSString *)sqlStringForSQLExpression:(EOSQLExpression *)_sqlExpr { return [_sqlExpr sqlStringForKeyComparisonQualifier:self]; } - (EOQualifier *)schemaBasedQualifierWithRootEntity:(EOEntity *)_entity { NSLog(@"ERROR(%s): subclasses need to override this method!", __PRETTY_FUNCTION__); return nil; } @end /* EOKeyComparisonQualifier(SQLGeneration) */ SOPE/sope-gdl1/GDLAccess/EOExpressionArray.m0000644000000000000000000002121715004363604017411 0ustar rootroot/* EOExpressionArray.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: September 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "EOExpressionArray.h" #import "EOAttribute.h" #import "EOEntity.h" #import "EORelationship.h" @implementation EOExpressionArray - (id)init { [super init]; self->array = [[NSMutableArray allocWithZone:[self zone]] init]; return self; } - (id)initWithPrefix:(NSString *)_prefix infix:(NSString *)_infix suffix:(NSString *)_suffix { [super init]; ASSIGN(self->prefix, _prefix); ASSIGN(self->infix, _infix); ASSIGN(self->suffix, _suffix); RELEASE(self->array); self->array = [[NSMutableArray allocWithZone:[self zone]] init]; return self; } - (void)dealloc { RELEASE(self->array); RELEASE(self->prefix); RELEASE(self->infix); RELEASE(self->suffix); [super dealloc]; } - (BOOL)referencesObject:(id)anObject { return [self indexOfObject:anObject] != NSNotFound; } - (NSString *)expressionValueForContext:(id)ctx { if(ctx && [self count] && [[self objectAtIndex:0] isKindOfClass:[EORelationship class]]) return [ctx expressionValueForAttributePath:self->array]; else { NSUInteger i, count; id result; SEL sel; IMP imp; count = [self count]; result = [NSMutableString stringWithCapacity:256]; sel = @selector(appendString:); imp = [result methodForSelector:sel]; if (self->prefix) [result appendString:self->prefix]; if (count) { id o; o = [self objectAtIndex:0]; (*imp)(result, sel, [o expressionValueForContext:ctx]); for (i = 1 ; i < count; i++) { if (self->infix) (*imp)(result, sel, self->infix); o = [self objectAtIndex:i]; (*imp)(result, sel, [o expressionValueForContext:ctx]); } } if (self->suffix) [result appendString:self->suffix]; return result; } } - (void)setPrefix:(NSString *)_prefix { ASSIGNCOPY(self->prefix, _prefix); } - (void)setInfix:(NSString *)_infix { ASSIGNCOPY(self->infix, _infix); } - (void)setSuffix:(NSString *)_suffix { ASSIGNCOPY(self->suffix, _suffix); } - (NSString *)prefix { return self->prefix; } - (NSString *)infix { return self->infix; } - (NSString *)suffix { return self->suffix; } + (EOExpressionArray *)parseExpression:(NSString *)expression entity:(EOEntity *)entity replacePropertyReferences:(BOOL)replacePropertyReferences { return [EOExpressionArray parseExpression:expression entity:entity replacePropertyReferences: replacePropertyReferences relationshipPaths:nil]; } + (EOExpressionArray *)parseExpression:(NSString *)expression entity:(EOEntity *)entity replacePropertyReferences:(BOOL)replacePropertyReferences relationshipPaths:(NSMutableArray *)relationshipPaths { EOExpressionArray *exprArray; unsigned char buf[[expression lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 4]; // TODO: not too good const unsigned char *s, *start; id objectToken; NSAutoreleasePool *pool; exprArray = [[EOExpressionArray new] autorelease]; pool = [[NSAutoreleasePool alloc] init]; [expression getCString:(char *)buf maxLength:[expression lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 4 encoding:NSUTF8StringEncoding]; s = buf; /* Divide the expression string in alternating substrings that obey the following simple grammar: I = [a-zA-Z0-9@_#]([a-zA-Z0-9@_.#$])+ O = \'.*\' | \".*\" | [^a-zA-Z0-9@_#]+ S -> I S | O S | nothing */ while(*s) { /* Determines an I token. */ if(isalnum((int)*s) || *s == '@' || *s == '_' || *s == '#') { start = s; for(++s; *s; s++) if(!isalnum((int)*s) && *s != '@' && *s != '_' && *s != '.' && *s != '#' && *s != '$') break; objectToken = [NSString stringWithCString:(char *)start length:(unsigned)(s - start)]; if (replacePropertyReferences) { id property = [entity propertyNamed:objectToken]; if(property) { if ([objectToken isNameOfARelationshipPath] && relationshipPaths) { [relationshipPaths addObject: [entity relationshipsNamed: objectToken]]; } objectToken = property; } } [exprArray addObject:objectToken]; } /* Determines an O token. */ start = s; for(; *s && !isalnum((int)*s) && *s != '@' && *s != '_' && *s != '#'; s++) { if(*s == '\'' || *s == '"') { unsigned char quote = *s; for(++s; *s; s++) if(*s == quote) break; else if(*s == '\\') s++; /* Skip the escaped characters */ if(!*s) { [NSException raise:@"SyntaxErrorException" format:@"unterminated character string"]; } } } if (s != start) { objectToken = [NSString stringWithCString:(char *)start length:(unsigned)(s - start)]; [exprArray addObject:objectToken]; } } [pool release]; return exprArray; } /* NSMutableCopying */ - (id)copyWithZone:(NSZone *)_zone { return [self mutableCopyWithZone:_zone]; } - (id)mutableCopyWithZone:(NSZone *)_zone { EOExpressionArray *new; new = [[EOExpressionArray allocWithZone:_zone] initWithPrefix:self->prefix infix:self->infix suffix:self->suffix]; RELEASE(new->array); new->array = nil; new->array = [self->array mutableCopyWithZone:_zone]; return new; } /* NSArray compatibility */ - (void)addObjectsFromExpressionArray:(EOExpressionArray *)_array { [self->array addObjectsFromArray:_array->array]; } - (void)insertObject:(id)_obj atIndex:(NSUInteger)_idx { [self->array insertObject:_obj atIndex:_idx]; } - (void)addObjectsFromArray:(NSArray *)_array { [self->array addObjectsFromArray:_array]; } - (void)addObject:(id)_object { [self->array addObject:_object]; } - (NSUInteger)indexOfObject:(id)_object { return [self->array indexOfObject:_object]; } - (id)objectAtIndex:(NSUInteger)_idx { return [self->array objectAtIndex:_idx]; } - (id)lastObject { return [self->array lastObject]; } - (NSUInteger)count { return [self->array count]; } - (BOOL)isNotEmpty { return [self->array count] > 0 ? YES : NO; } - (NSEnumerator *)objectEnumerator { return [self->array objectEnumerator]; } - (NSEnumerator *)reverseObjectEnumerator { return [self->array reverseObjectEnumerator]; } - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if (self->array) [ms appendFormat:@" array=%@", self->array]; if (self->prefix) [ms appendFormat:@" prefix='%@'", self->prefix]; if (self->infix) [ms appendFormat:@" infix='%@'", self->infix]; if (self->suffix) [ms appendFormat:@" suffix='%@'", self->suffix]; [ms appendString:@">"]; return ms; } @end /* EOExpressionArray */ @implementation NSObject(EOExpression) - (NSString *)expressionValueForContext:(id)ctx { if([self respondsToSelector:@selector(stringValue)]) return [(id)self stringValue]; return [self description]; } @end /* NSObject(EOExpression) */ @implementation NSString(EOExpression) /* Avoid returning the description in case of NSString because if the string contains whitespaces it will be quoted. Particular adaptors have to override -formatValue:forAttribute: and they have to quote with the specific database character the returned string. */ - (NSString *)expressionValueForContext:(id)ctx { return self; } @end /* NSString(EOExpression) */ /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/EOAdaptorContext.m0000644000000000000000000001447015004363604017215 0ustar rootroot/* EOAdaptorContext.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #import #import "common.h" #import "EOAdaptor.h" #import "EOAdaptorContext.h" #import "EOAdaptorChannel.h" @implementation EOAdaptorContext - (id)initWithAdaptor:(EOAdaptor *)_adaptor { ASSIGN(self->adaptor, _adaptor); self->channels = [[NSMutableArray alloc] initWithCapacity:2]; [self->adaptor contextDidInit:self]; return self; } - (void)dealloc { [self->adaptor contextWillDealloc:self]; [self->adaptor release]; [self->channels release]; [super dealloc]; } /* channels */ - (EOAdaptorChannel *)createAdaptorChannel { return [[[[adaptor adaptorChannelClass] alloc] initWithAdaptorContext:self] autorelease]; } - (NSArray *)channels { NSMutableArray *ma; unsigned i, count; if ((count = [self->channels count]) == 0) return nil; ma = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) [ma addObject:[[self->channels objectAtIndex:i] nonretainedObjectValue]]; return ma; } - (void)channelDidInit:aChannel { [self->channels addObject:[NSValue valueWithNonretainedObject:aChannel]]; } - (void)channelWillDealloc:(id)aChannel { int i; for (i = [self->channels count] - 1; i >= 0; i--) if ([[channels objectAtIndex:i] nonretainedObjectValue] == aChannel) { [channels removeObjectAtIndex:i]; break; } } - (BOOL)hasOpenChannels { int i, count = [channels count]; for (i = 0; i < count; i++) if ([[[channels objectAtIndex:i] nonretainedObjectValue] isOpen]) return YES; return NO; } - (BOOL)hasBusyChannels { int i, count = [channels count]; for (i = 0; i < count; i++) if ([[[channels objectAtIndex:i] nonretainedObjectValue] isFetchInProgress]) return YES; return NO; } /* transactions */ - (BOOL)beginTransaction { if (transactionNestingLevel && ![self canNestTransactions]) return NO; if ([self->channels count] == 0) return NO; if (delegateRespondsTo.willBegin) { EODelegateResponse response = [delegate adaptorContextWillBegin:self]; if (response == EODelegateRejects) return NO; else if (response == EODelegateOverrides) return YES; } if ([self primaryBeginTransaction] == NO) return NO; [self transactionDidBegin]; if (delegateRespondsTo.didBegin) [delegate adaptorContextDidBegin:self]; return YES; } - (BOOL)commitTransaction { if (!transactionNestingLevel || [self hasBusyChannels]) return NO; if (![channels count]) return NO; if (delegateRespondsTo.willCommit) { EODelegateResponse response = [delegate adaptorContextWillCommit:self]; if (response == EODelegateRejects) return NO; else if (response == EODelegateOverrides) return YES; } if ([self primaryCommitTransaction] == NO) return NO; [self transactionDidCommit]; if (delegateRespondsTo.didCommit) [delegate adaptorContextDidCommit:self]; return YES; } - (BOOL)rollbackTransaction { if (!transactionNestingLevel || [self hasBusyChannels]) return NO; if (![channels count]) return NO; if (delegateRespondsTo.willRollback) { EODelegateResponse response = [delegate adaptorContextWillRollback:self]; if (response == EODelegateRejects) return NO; else if (response == EODelegateOverrides) return YES; } if ([self primaryRollbackTransaction] == NO) return NO; [self transactionDidRollback]; if (delegateRespondsTo.didRollback) [delegate adaptorContextDidRollback:self]; return YES; } - (void)transactionDidBegin { /* Increment the transaction scope */ transactionNestingLevel++; } - (void)transactionDidCommit { /* Decrement the transaction scope */ transactionNestingLevel--; } - (void)transactionDidRollback { /* Decrement the transaction scope */ transactionNestingLevel--; } /* delegate */ - (void)setDelegate:(id)_delegate { self->delegate = _delegate; delegateRespondsTo.willBegin = [delegate respondsToSelector:@selector(adaptorContextWillBegin:)]; delegateRespondsTo.didBegin = [delegate respondsToSelector:@selector(adaptorContextDidBegin:)]; delegateRespondsTo.willCommit = [delegate respondsToSelector:@selector(adaptorContextWillCommit:)]; delegateRespondsTo.didCommit = [delegate respondsToSelector:@selector(adaptorContextDidCommit:)]; delegateRespondsTo.willRollback = [delegate respondsToSelector:@selector(adaptorContextWillRollback:)]; delegateRespondsTo.didRollback = [delegate respondsToSelector:@selector(adaptorContextDidRollback:)]; } - (id)delegate { return self->delegate; } /* adaptor */ - (EOAdaptor *)adaptor { return self->adaptor; } /* transactions */ - (BOOL)canNestTransactions { /* deprecated in WO 4.5 */ return NO; } - (unsigned)transactionNestingLevel { /* deprecated in WO 4.5 */ return self->transactionNestingLevel; } - (BOOL)hasOpenTransaction { /* new in WO 4.5 */ return self->transactionNestingLevel > 0 ? YES : NO; } - (BOOL)primaryBeginTransaction { return NO; } - (BOOL)primaryCommitTransaction { return NO; } - (BOOL)primaryRollbackTransaction { return NO; } @end /* EOAdaptorContext */ SOPE/sope-gdl1/GDLAccess/EOAdaptorChannel+Attributes.h0000644000000000000000000000067515004363604021260 0ustar rootroot//$Id: EOAdaptorChannel+Attributes.h 1 2004-08-20 10:38:46Z znek $ #ifndef __EOAdaptorChannel_Attributes_h__ #define __EOAdaptorChannel_Attributes_h__ @class NSString, NSArray; #import @interface EOAdaptorChannel(Attributes) - (NSArray *)attributesForTableName:(NSString *)_tableName; - (NSArray *)primaryKeyAttributesForTableName:(NSString *)_tableName; @end #endif /* __EOAdaptorChannel_Attributes_h__ */ SOPE/sope-gdl1/GDLAccess/EOQualifierScanner.m0000644000000000000000000001306415004363604017507 0ustar rootroot/* EOQualifierScanner.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Helge Hess Date: September 1996 November 1999 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOQualifierScanner.m 1 2004-08-20 10:38:46Z znek $ #import "common.h" #include "EOQualifierScanner.h" #include "EOFExceptions.h" #include "EOEntity.h" #include "EOSQLQualifier.h" #include #if LIB_FOUNDATION_LIBRARY # import # import #else # import "DefaultScannerHandler.h" # import "PrintfFormatScanner.h" #endif @implementation EOQualifierScannerHandler - (id)init { [super init]; specHandler['d'] = [self methodForSelector:@selector(convertInt:scanner:)]; specHandler['f'] = [self methodForSelector:@selector(convertFloat:scanner:)]; specHandler['s'] = [self methodForSelector:@selector(convertCString:scanner:)]; specHandler['A'] = [self methodForSelector:@selector(convertProperty:scanner:)]; specHandler['@'] = [self methodForSelector:@selector(convertObject:scanner:)]; return self; } - (void)setEntity:(EOEntity *)_entity { ASSIGN(self->entity, _entity); } - (void)dealloc { RELEASE(self->entity); [super dealloc]; } /* conversions */ - (NSString *)convertInt:(va_list *)pInt scanner:(FormatScanner*)scanner { char buffer[256]; sprintf(buffer, [scanner currentSpecifier], va_arg(*pInt, int)); return [NSString stringWithCString:buffer]; } - (NSString*)convertFloat:(va_list *)pFloat scanner:(FormatScanner*)scanner { char buffer[256]; sprintf(buffer, [scanner currentSpecifier], va_arg(*pFloat, double)); return [NSString stringWithCString:buffer]; } - (NSString*)convertCString:(va_list *)pString scanner:(FormatScanner*)scanner { char *string; string = va_arg(*pString, char*); return string ? [NSString stringWithCString:string] : (id)@""; } - (NSString*)convertProperty:(va_list*)pString scanner:(FormatScanner*)scanner { NSString *propertyName; id property; propertyName = va_arg(*pString, id); property = [entity propertyNamed:propertyName]; if(property == nil) { [[[InvalidPropertyException alloc] initWithName:propertyName entity:entity] raise]; } return propertyName; } - (NSString *)convertObject:(va_list *)pId scanner:scanner { id object = va_arg(*pId, id); if (object == nil) object = [NSNull null]; return [object expressionValueForContext:nil]; } @end /* EOQualifierScannerHandler */ @implementation EOQualifierEnumScannerHandler - (id)init { [super init]; specHandler['d'] = [self methodForSelector:@selector(convertInt:scanner:)]; specHandler['f'] = [self methodForSelector:@selector(convertFloat:scanner:)]; specHandler['s'] = [self methodForSelector:@selector(convertCString:scanner:)]; specHandler['A'] = [self methodForSelector:@selector(convertProperty:scanner:)]; specHandler['@'] = [self methodForSelector:@selector(convertObject:scanner:)]; return self; } - (void)setEntity:(EOEntity *)_entity { ASSIGN(self->entity, _entity); } - (void)dealloc { RELEASE(self->entity); [super dealloc]; } - (NSString *)convertInt:(NSEnumerator **)pInt scanner:(FormatScanner*)scanner { char buffer[256]; sprintf(buffer, [scanner currentSpecifier], [[*pInt nextObject] intValue]); return [NSString stringWithCString:buffer]; } - (NSString *)convertFloat:(NSEnumerator **)pFloat scanner:(FormatScanner *)scanner { char buffer[256]; sprintf(buffer, [scanner currentSpecifier], [[*pFloat nextObject] doubleValue]); return [NSString stringWithCString:buffer]; } - (NSString *)convertCString:(NSEnumerator **)pString scanner:(FormatScanner *)scanner { id str; if ((str = [*pString nextObject]) == nil) str = @""; else if ([str isKindOfClass:[NSString class]]) ; else if ([str respondsToSelector:@selector(stringValue)]) str = [str stringValue]; else str = [str description]; return (str == nil) ? (id)@"" : str; } - (NSString *)convertProperty:(NSEnumerator **)pString scanner:(FormatScanner *)scanner { NSString *propertyName; id property; propertyName = [*pString nextObject]; property = [entity propertyNamed:propertyName]; if(property == nil) { [[[InvalidPropertyException alloc] initWithName:propertyName entity:entity] raise]; } return propertyName; } - (NSString *)convertObject:(NSEnumerator **)pId scanner:(id)scanner { id object; object = [*pId nextObject]; return [object expressionValueForContext:nil]; } @end /* EOQualifierEnumScannerHandler */ SOPE/sope-gdl1/GDLAccess/EORelationship.m0000644000000000000000000003702215004363604016715 0ustar rootroot/* EORelationship.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: August 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "EOModel.h" #import "EOAttribute.h" #import "EOEntity.h" #import "EORelationship.h" #import "EOExpressionArray.h" #import "EOFExceptions.h" #import static EONull *null = nil; @interface EOJoin : EORelationship // for adaptor compability @end @implementation EORelationship + (void)initialize { if (null == nil) null = [[EONull null] retain]; } - (id)init { if ((self = [super init])) { self->flags.createsMutableObjects = YES; self->entity = nil; self->destinationEntity = nil; } return self; } - (id)initWithName:(NSString*)_name { if ((self = [self init])) { self->name = _name; } return self; } - (void)dealloc { RELEASE(self->name); RELEASE(self->definition); RELEASE(self->userDictionary); self->entity = nil; if ([self->destinationEntity isKindOfClass:[NSString class]]) RELEASE(self->destinationEntity); // else: non-retained EOEntity self->destinationEntity = nil; RELEASE(self->componentRelationships); RELEASE(self->sourceAttribute); RELEASE(self->destinationAttribute); [super dealloc]; } // These methods should be here to let the library work with NeXT foundation - (id)copy { return RETAIN(self); } - (id)copyWithZone:(NSZone *)_zone { return RETAIN(self); } // Is equal only if same name; used to make aliasing ordering stable - (NSUInteger)hash { return [self->name hash]; } + (BOOL)isValidName:(NSString*)_name { return [EOEntity isValidName:_name]; } - (void)setDefinition:(NSString *)def { // TODO: do we need this? if (def == nil) { [NSException raise:NSInvalidArgumentException format:@"invalid (nil) definition argument ..."]; } if ([def isNameOfARelationshipPath]) { NSArray *defArray = nil; int count; defArray = [def componentsSeparatedByString:@"."]; count = [defArray count]; RELEASE(self->componentRelationships); self->componentRelationships = [[NSMutableArray alloc] initWithCapacity:count]; flags.isFlattened = YES; NS_DURING { EOEntity *currentEntity = self->entity; id relationship = nil; int i; for (i = 0; i < count; i++) { id relationshipName = [defArray objectAtIndex:i]; /* Take the address of `relationship' to force the compiler to not allocate it into a register. */ *(&relationship) = [currentEntity relationshipNamed: relationshipName]; if (!relationship) [[[InvalidPropertyException alloc] initWithName:relationshipName entity:currentEntity] raise]; [self->componentRelationships addObject:relationship]; flags.isToMany |= [relationship isToMany]; currentEntity = [relationship destinationEntity]; } if (self->destinationEntity && ![self->destinationEntity isEqual:currentEntity]) [[[DestinationEntityDoesntMatchDefinitionException alloc] initForDestination:self->destinationEntity andDefinition:def relationship:self] raise]; if ([self->destinationEntity isKindOfClass:[NSString class]]) RELEASE(self->destinationEntity); self->destinationEntity = currentEntity; /* non-retained */ if ([self->destinationEntity isKindOfClass:[NSString class]]) RETAIN(self->destinationEntity); } NS_HANDLER { RELEASE(self->componentRelationships); self->componentRelationships = nil; [localException raise]; } NS_ENDHANDLER; } else [[[InvalidNameException alloc] initWithName:def] raise]; ASSIGN(self->definition, def); } - (BOOL)setToMany:(BOOL)_flag { if ([self isFlattened]) return NO; self->flags.isToMany = _flag; return YES; } - (BOOL)isToMany { return self->flags.isToMany; } - (BOOL)setName:(NSString *)_name { if ([self->entity referencesProperty:_name]) return NO; ASSIGN(self->name, _name); return NO; } - (NSString *)name { return self->name; } - (BOOL)isCompound { return NO; } - (NSString *)expressionValueForContext:(id)_ctx { return self->name; } - (void)setEntity:(EOEntity *)_entity { self->entity = _entity; /* non-retained */ } - (EOEntity *)entity { return self->entity; } - (void)resetEntities { self->entity = nil; self->destinationEntity = nil; } - (BOOL)hasEntity { return (self->entity != nil) ? YES : NO; } - (BOOL)hasDestinationEntity { return (self->destinationEntity != nil) ? YES : NO; } - (void)setUserDictionary:(NSDictionary *)dict { ASSIGN(self->userDictionary, dict); } - (NSDictionary *)userDictionary { return self->userDictionary; } - (NSArray *)joins { return self->sourceAttribute ? [NSArray arrayWithObject:self] : nil; } - (NSString *)definition { return self->definition; } - (NSArray *)sourceAttributes { return [NSArray arrayWithObject:self->sourceAttribute]; } - (NSArray *)destinationAttributes { return [NSArray arrayWithObject:self->destinationAttribute]; } - (EOEntity *)destinationEntity { return self->destinationEntity; } - (BOOL)isFlattened { return self->flags.isFlattened; } - (NSArray *)componentRelationships { return self->componentRelationships; } - (BOOL)referencesProperty:(id)_property { if ([self->sourceAttribute isEqual:_property]) return YES; if ([self->destinationAttribute isEqual:_property]) return YES; if ([self->componentRelationships indexOfObject:_property] != NSNotFound) return YES; return NO; } - (NSDictionary *)foreignKeyForRow:(NSDictionary *)_row { int j, i, n = [_row count]; id keys[n], vals[n]; for (i = j = 0, n = 1; j < n; j++) { EOAttribute *keyAttribute = self->sourceAttribute; EOAttribute *fkeyAttribute = self->destinationAttribute; NSString *key = nil; NSString *fkey = nil; id value = nil; key = [keyAttribute name]; fkey = [fkeyAttribute name]; value = [_row objectForKey:key]; if (value) { vals[i] = value; keys[i] = fkey; i++; } else { NSLog(@"%s: could not get value of key %@ (foreignKey=%@)", __PRETTY_FUNCTION__, key, fkey); } } return AUTORELEASE([[NSDictionary alloc] initWithObjects:vals forKeys:keys count:i]); } - (NSString *)description { return [[self propertyList] description]; } @end /* EORelationship */ @implementation EORelationship (EORelationshipPrivate) + (EORelationship *)relationshipFromPropertyList:(id)_plist model:(EOModel *)model { NSDictionary *plist = _plist; EORelationship *relationship = nil; NSArray *array = nil; NSEnumerator *enumerator = nil; id joinPList = nil; relationship = [[[EORelationship alloc] init] autorelease]; [relationship setCreateMutableObjects:YES]; [relationship setName:[plist objectForKey:@"name"]]; [relationship setUserDictionary: [plist objectForKey:@"userDictionary"]]; if ((array = [plist objectForKey:@"joins"])) { enumerator = [array objectEnumerator]; joinPList = [enumerator nextObject]; [relationship loadJoinPropertyList:joinPList]; joinPList = [enumerator nextObject]; NSAssert(joinPList == nil, @"a relationship only supports one join !"); } else { [relationship loadJoinPropertyList:_plist]; } relationship->destinationEntity = RETAIN([plist objectForKey:@"destination"]); // retained string relationship->flags.isToMany = [[plist objectForKey:@"isToMany"] isEqual:@"Y"]; relationship->flags.isMandatory = [[plist objectForKey:@"isMandatory"] isEqual:@"Y"]; /* Do not send here the -setDefinition: message because the relationships are not yet created from the model file. */ relationship->definition = RETAIN([plist objectForKey:@"definition"]); return relationship; } - (void)replaceStringsWithObjects { EOModel *model = [self->entity model]; if (self->destinationEntity) { // now self->destinationEntity is NSString and retained !! id destinationEntityName = AUTORELEASE(self->destinationEntity); self->destinationEntity = [model entityNamed:destinationEntityName]; // now hold entity non-retained if (self->destinationEntity == nil) { NSLog(@"invalid entity name '%@' specified as destination entity " @"for relationship '%@' in entity '%@'", destinationEntityName, name, [self->entity name]); [model errorInReading]; } } if (!(self->destinationEntity || self->definition)) { NSLog(@"relationship '%@' in entity '%@' is incompletely specified: " @"no destination entity or definition.", name, [self->entity name]); [model errorInReading]; } if (self->definition && (self->sourceAttribute != nil)) { NSLog(@"relationship '%@' in entity '%@': flattened relationships " @"cannot have joins", name, [self->entity name]); [model errorInReading]; } if (self->sourceAttribute) { EOEntity *attributeEntity; EOAttribute *attribute = nil; #if 0 attributeEntity = self->flags.isToMany ? self->destinationEntity : self->entity; #endif attributeEntity = self->entity; attribute = [attributeEntity attributeNamed:(NSString*)self->sourceAttribute]; if (attribute) [self setSourceAttribute:attribute]; else { [model errorInReading]; NSLog(@"invalid attribute name '%@' specified as source attribute for " @"join in relationship '%@' in entity '%@' (dest='%@')", sourceAttribute, [self name], [self->entity name], [self->destinationEntity name]); } #if 0 attributeEntity = self->flags.isToMany ? self->entity : self->destinationEntity; #endif attributeEntity = self->destinationEntity; attribute = [attributeEntity attributeNamed:(NSString*)destinationAttribute]; if (attribute) [self setDestinationAttribute:attribute]; else { [model errorInReading]; NSLog(@"invalid attribute name '%@' specified as destination " @"attribute for join in relationship '%@' in entity '%@' (dest='%@')", destinationAttribute, [self name], [self->entity name], [self->destinationEntity name]); } } [self setCreateMutableObjects:NO]; } - (void)initFlattenedRelationship { if (self->definition) { NS_DURING [self setDefinition:self->definition]; NS_HANDLER { NSLog(@"%@", [localException reason]); [[self->entity model] errorInReading]; } NS_ENDHANDLER; } } - (id)propertyList { NSMutableDictionary *propertyList = nil; propertyList = [NSMutableDictionary dictionary]; [self encodeIntoPropertyList:propertyList]; return propertyList; } - (void)setCreateMutableObjects:(BOOL)flag { if (self->flags.createsMutableObjects == flag) return; self->flags.createsMutableObjects = flag; } - (BOOL)createsMutableObjects { return self->flags.createsMutableObjects; } - (int)compareByName:(EORelationship *)_other { return [[(EORelationship *)self name] compare:[_other name]]; } /* EOJoin */ - (void)loadJoinPropertyList:(id)propertyList { NSDictionary *plist = propertyList; NSString *joinOperatorPList; NSString *joinSemanticPList; id tmp; tmp = [plist objectForKey:@"sourceAttribute"]; [self setSourceAttribute:tmp]; tmp = [plist objectForKey:@"destinationAttribute"]; [self setDestinationAttribute:tmp]; if ((joinOperatorPList = [plist objectForKey:@"joinOperator"])) { NSAssert([joinOperatorPList isEqual:@"EOJoinEqualTo"], @"only EOJoinEqualTo is supported as the join operator !"); } if ((joinSemanticPList = [plist objectForKey:@"joinSemantic"])) { NSAssert([joinSemanticPList isEqual:@"EOInnerJoin"], @"only EOInnerJoin is supported as the join semantic !"); } } - (void)setDestinationAttribute:(EOAttribute*)attribute { ASSIGN(self->destinationAttribute, attribute); } - (EOAttribute*)destinationAttribute { return self->destinationAttribute; } - (void)setSourceAttribute:(EOAttribute *)attribute { ASSIGN(self->sourceAttribute, attribute); } - (EOAttribute*)sourceAttribute { return self->sourceAttribute; } - (EOJoinOperator)joinOperator { return EOJoinEqualTo; } - (EOJoinSemantic)joinSemantic { return EOInnerJoin; } - (EORelationship*)relationship { return self; } // misc - (void)addJoin:(EOJoin *)_join { [self setSourceAttribute:[_join sourceAttribute]]; [self setDestinationAttribute:[_join destinationAttribute]]; } /* PropertyListCoding */ static inline void _addToPropList(NSMutableDictionary *_plist, id _value, NSString *key) { if (_value) [_plist setObject:_value forKey:key]; } - (void)encodeIntoPropertyList:(NSMutableDictionary *)_plist { _addToPropList(_plist, self->name, @"name"); _addToPropList(_plist, self->definition, @"definition"); _addToPropList(_plist, self->userDictionary, @"userDictionary"); if (self->sourceAttribute) { // has join ? _addToPropList(_plist, [self->sourceAttribute name], @"sourceAttribute"); _addToPropList(_plist, [self->destinationAttribute name], @"destinationAttribute"); _addToPropList(_plist, [[self->sourceAttribute entity] name], @"destination"); } if (![self isFlattened] && self->destinationEntity) { _addToPropList(_plist, [self->destinationEntity name], @"destination"); } if (![self isFlattened]) _addToPropList(_plist, flags.isToMany ? @"Y" : @"N", @"isToMany"); if (![self isMandatory]) _addToPropList(_plist, flags.isMandatory ? @"Y" : @"N", @"isMandatory"); } /* EOF2Additions */ /* constraints */ - (void)setIsMandatory:(BOOL)_flag { self->flags.isMandatory = _flag ? 1 : 0; } - (BOOL)isMandatory { return self->flags.isMandatory ? YES : NO; } - (NSException *)validateValue:(id *)_value { if (_value == NULL) return nil; /* check 'mandatory' constraint */ if (self->flags.isMandatory) { if (self->flags.isToMany) { if ([*_value count] == 0) { NSLog(@"WARNING(%s): tried to use value %@" @"with mandatory toMany relationship %@", __PRETTY_FUNCTION__, *_value, self); } } else { if ((*_value == nil) || (*_value == null)) { NSLog(@"WARNING(%s): tried to use value %@" @"with mandatory toOne relationship %@", __PRETTY_FUNCTION__, *_value, self); } } } return nil; } @end /* EORelationship */ @implementation EOJoin @end /* EOJoin */ SOPE/sope-gdl1/GDLAccess/libGDLAccess.def0000644000000000000000000000467215004363604016556 0ustar rootrootEXPORTS __objc_class_name_EOAdaptor; __objc_class_name_EOAdaptorChannel; __objc_class_name_EOAdaptorContext; __objc_class_name_EOArrayProxy; __objc_class_name_EOAttribute; __objc_class_name_EOAttributeOrdering; __objc_class_name_EODatabase; __objc_class_name_EODatabaseChannel; __objc_class_name_EODatabaseContext; __objc_class_name_EODatabaseFault; __objc_class_name_EODatabaseFaultResolver; __objc_class_name_EOArrayFault; __objc_class_name_EOObjectFault; __objc_class_name_EOEntity; __objc_class_name_EOEntityClassDescription; __objc_class_name_EOExpressionArray; __objc_class_name_EOFException; __objc_class_name_ObjectNotAvailableException; __objc_class_name_PropertyDefinitionException; __objc_class_name_DestinationEntityDoesntMatchDefinitionException; __objc_class_name_InvalidNameException; __objc_class_name_InvalidPropertyException; __objc_class_name_RelationshipMustBeToOneException; __objc_class_name_InvalidValueTypeException; __objc_class_name_InvalidAttributeException; __objc_class_name_InvalidQualifierException; __objc_class_name_EOAdaptorException; __objc_class_name_CannotFindAdaptorBundleException; __objc_class_name_InvalidAdaptorBundleException; __objc_class_name_InvalidAdaptorStateException; __objc_class_name_DataTypeMappingNotSupportedException; __objc_class_name_ChannelIsNotOpenedException; __objc_class_name_AdaptorIsFetchingException; __objc_class_name_AdaptorIsNotFetchingException; __objc_class_name_NoTransactionInProgressException; __objc_class_name_TooManyOpenedChannelsException; __objc_class_name_EOKeySortOrdering; __objc_class_name_EOModel; __objc_class_name_EOModelGroup; __objc_class_name_EOObjectUniquer; __objc_class_name_EOSinglePrimaryKeyDictionary; __objc_class_name_EOSinglePrimaryKeyDictionaryEnumerator; __objc_class_name_EOMultiplePrimaryKeyDictionary; __objc_class_name_EOPrimaryKeyDictionary; __objc_class_name_EOQualifierScannerHandler; __objc_class_name_EOQualifierEnumScannerHandler; __objc_class_name_EOQuotedExpression; __objc_class_name_EORelationship; __objc_class_name_EOJoin; __objc_class_name_EOSelectScannerHandler; __objc_class_name_EOInsertUpdateScannerHandler; __objc_class_name_EOSQLExpression; __objc_class_name_EOSelectSQLExpression; __objc_class_name_EOInsertSQLExpression; __objc_class_name_EOUpdateSQLExpression; __objc_class_name_EODeleteSQLExpression; __objc_class_name_EOQualifierJoinHolder; __objc_class_name_EOSQLQualifier; __objc_class_name_eoaccess; SOPE/sope-gdl1/GDLAccess/EOSQLQualifier.h0000644000000000000000000000761315004363604016553 0ustar rootroot/* EOSQLQualifier.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Helge Hess Date: September 1996 November 1999 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOSQLQualifier_h__ #define __EOSQLQualifier_h__ #import #import /* EOSQLQualifier TODO: document Note: the expression context is the EOSQLExpression. */ @class NSDictionary, NSString, NSMutableSet; @class EOEntity, EORelationship, EOExpressionArray, EOSQLQualifier; @class EOSQLExpression; @protocol EOQualifierSQLGeneration - (NSString *)sqlStringForSQLExpression:(EOSQLExpression *)_sqlExpr; - (EOQualifier *)schemaBasedQualifierWithRootEntity:(EOEntity *)_entity; @end @interface EOSQLQualifier : EOQualifier < NSCopying > { /* TODO: these should be GCMutableSet */ NSMutableSet *relationshipPaths; NSMutableSet *additionalEntities; /* Garbage collectable objects */ EOEntity *entity; EOExpressionArray *content; BOOL usesDistinct; } /* Combining qualifiers */ - (void)negate; - (void)conjoinWithQualifier:(EOSQLQualifier*)qualifier; - (void)disjoinWithQualifier:(EOSQLQualifier*)qualifier; /* Getting the entity */ - (EOEntity *)entity; /* Checking the definition */ - (BOOL)isEmpty; /* Accessing the distinct selection */ - (void)setUsesDistinct:(BOOL)flag; - (BOOL)usesDistinct; /* Accessing the relationships referred within qualifier */ - (NSMutableSet*)relationshipPaths; - (NSMutableSet*)additionalEntities; /* Getting the expression value */ - (NSString*)expressionValueForContext:(id)ctx; /* Private methods */ - (void)_computeRelationshipPaths:(NSArray *)_relationshipPaths; - (void)_computeRelationshipPaths; - (EOSQLQualifier *)sqlQualifierForEntity:(EOEntity *)_entity; @end @interface EOSQLQualifier(QualifierCreation) - (id)initWithEntity:(EOEntity *)_entity qualifierFormat:(NSString *)_qualifierFormat, ...; - (id)initWithEntity:(EOEntity *)_entity qualifierFormat:(NSString *)_qualifierFormat argumentsArray:(NSArray *)_args; /* Creating instances */ + (EOSQLQualifier *)qualifierForRow:(NSDictionary *)row entity:(EOEntity *)entity; + (EOSQLQualifier *)qualifierForPrimaryKey:(NSDictionary *)key entity:(EOEntity *)entity; + (EOSQLQualifier *)qualifierForRow:(NSDictionary *)row relationship:(EORelationship *)relationship; + (EOSQLQualifier *)qualifierForObject:(id)sourceObject relationship:(EORelationship *)relationship; @end @interface EOQualifier(SQLQualifier) - (EOSQLQualifier *)sqlQualifierForEntity:(EOEntity *)_entity; @end @interface EOAndQualifier(SQLGeneration) < EOQualifierSQLGeneration > @end @interface EOOrQualifier(SQLGeneration) < EOQualifierSQLGeneration > @end @interface EONotQualifier(SQLGeneration) < EOQualifierSQLGeneration > @end @interface EOKeyValueQualifier(SQLGeneration) < EOQualifierSQLGeneration > @end @interface EOKeyComparisonQualifier(SQLGeneration) < EOQualifierSQLGeneration > @end #endif /* __EOSQLQualifier_h__ */ /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/EODatabaseFault.h0000644000000000000000000000455615004363604016755 0ustar rootroot/* EODatabaseFault.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __eoaccess_EODatabaseFault_h__ #define __eoaccess_EODatabaseFault_h__ #import @class EOSQLQualifier, EOEntity, EODatabaseChannel; @class NSArray, NSDictionary, NSString; /* * EODatabaseFault class */ @interface EODatabaseFault : EOFault // Creating a fault + (id)objectFaultWithPrimaryKey:(NSDictionary*)key entity:(EOEntity*)entity databaseChannel:(EODatabaseChannel*)channel zone:(NSZone*)zone; + (NSArray *)arrayFaultWithQualifier:(EOSQLQualifier*)qualifier fetchOrder:(NSArray*)fetchOrder databaseChannel:(EODatabaseChannel*)channel zone:(NSZone*)zone; + (NSArray *)gcArrayFaultWithQualifier:(EOSQLQualifier*)qualifier fetchOrder:(NSArray*)fetchOrder databaseChannel:(EODatabaseChannel*)channel zone:(NSZone*)zone; + (NSDictionary*)primaryKeyForFault:fault; + (EOEntity*)entityForFault:fault; + (EOSQLQualifier*)qualifierForFault:fault; + (NSArray*)fetchOrderForFault:fault; + (EODatabaseChannel*)databaseChannelForFault:fault; @end /* EODatabaseFault */ /* * Informal protocol that informs an instance that a to-one * relationship could not be resoved to get data for self. * Its implementation in NSObject raises NSObjectNotAvailableException. */ @interface NSObject(EOUnableToFaultToOne) - (void)unableToFaultWithPrimaryKey:(NSDictionary*)key entity:(EOEntity*)entity databaseChannel:(EODatabaseChannel*)channel; @end #endif /* __eoaccess_EODatabaseFault_h__ */ SOPE/sope-gdl1/GDLAccess/EODatabaseFaultResolver.h0000644000000000000000000000457015004363604020473 0ustar rootroot/* EODatabaseFaultResolver.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 Author: Helge Hess Date: 1999 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EODatabaseFaultResolver_h__ #define __EODatabaseFaultResolver_h__ #import @class EODatabaseChannel; @class EOSQLQualifier; @class EOEntity; @interface EODatabaseFaultResolver : EOFaultHandler { @public EODatabaseChannel *channel; } - (id)initWithDatabaseChannel:(EODatabaseChannel*)aChannel zone:(NSZone*)zone targetClass:(Class)targetClass; - (Class)targetClass; - (NSDictionary *)primaryKey; - (EOEntity *)entity; - (EOSQLQualifier *)qualifier; - (NSArray *)fetchOrder; - (EODatabaseChannel *)databaseChannel; @end /* EODatabaseFaultResolver */ @interface EOArrayFault : EODatabaseFaultResolver { EOSQLQualifier *qualifier; NSArray *fetchOrder; } - (id)initWithQualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder databaseChannel:(EODatabaseChannel *)channel zone:(NSZone *)zone targetClass:(Class)targetClass; - (EOEntity *)entity; - (EOSQLQualifier *)qualifier; - (NSArray *)fetchOrder; @end @interface EOObjectFault : EODatabaseFaultResolver { EOEntity *entity; NSDictionary *primaryKey; } - (id)initWithPrimaryKey:(NSDictionary *)key entity:(EOEntity *)entity databaseChannel:(EODatabaseChannel *)channel zone:(NSZone *)zone targetClass:(Class)targetClass ; - (NSDictionary*)primaryKey; - (EOEntity*)entity; @end #endif /* __EODatabaseFaultResolver_h__ */ SOPE/sope-gdl1/GDLAccess/NSObject+EONullInit.m0000644000000000000000000000302115004363604017445 0ustar rootroot/* EOAdaptorChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: NSObject+EONullInit.m 1 2004-08-20 10:38:46Z znek $ #include #include #include "common.h" @interface NSObject(Entity) - (EOEntity *)entity; @end @implementation NSObject(EONullInit) - (void)setAllAttributesToEONull:(EOEntity *)_entity { NSAssert(_entity != nil, @"invalid entity parameter"); [_entity setAttributesOfObjectToEONull:self]; } - (void)setAllAttributesToEONull { // assume the object respondsTo: entity [self setAllAttributesToEONull:[self entity]]; } @end /* NSObject(EONullInit) */ SOPE/sope-gdl1/GDLAccess/EOKeySortOrdering.h0000644000000000000000000000312015004363604017331 0ustar rootroot/* EOKeySortOrdering.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #import @interface EOKeySortOrdering : NSObject { NSString* key; NSComparisonResult ordering; } + keyOrderingWithKey:(NSString*)aKey ordering:(NSComparisonResult)anOrdering; - initWithKey:(NSString*)aKey ordering:(NSComparisonResult)anOrdering; - (NSString*)key; - (NSComparisonResult)ordering; @end @interface NSArray(EOKeyBasedSorting) - (NSArray*)sortedArrayUsingKeyOrderArray:(NSArray*)orderArray; @end @interface NSMutableArray(EOKeyBasedSorting) - (void)sortUsingKeyOrderArray:(NSArray *)orderArray; @end /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/EOKeyValueQualifier+SQL.m0000644000000000000000000000440715004363604020277 0ustar rootroot/* EOAdaptorChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOKeyValueQualifier+SQL.m 1 2004-08-20 10:38:46Z znek $ #import "EOSQLQualifier.h" #include "common.h" @implementation EOKeyValueQualifier(SQLQualifier) /* SQL qualifier generation */ - (EOSQLQualifier *)sqlQualifierForEntity:(EOEntity *)_entity { EOSQLQualifier *q; NSString *format; if (sel_isEqual(self->operator, EOQualifierOperatorEqual)) format = @"%A = %@"; else if (sel_isEqual(self->operator, EOQualifierOperatorNotEqual)) format = @"%A <> %@"; else if (sel_isEqual(self->operator, EOQualifierOperatorLessThan)) format = @"%A < %@"; else if (sel_isEqual(self->operator, EOQualifierOperatorGreaterThan)) format = @"%A > %@"; else if (sel_isEqual(self->operator, EOQualifierOperatorLessThanOrEqualTo)) format = @"%A <= %@"; else if (sel_isEqual(self->operator, EOQualifierOperatorGreaterThanOrEqualTo)) format = @"%A >= %@"; else if (sel_isEqual(self->operator, EOQualifierOperatorLike)) format = @"%A LIKE %@"; else { format = [NSString stringWithFormat:@"%%A %@ %%@", NSStringFromSelector(self->operator)]; } q = [[EOSQLQualifier alloc] initWithEntity:_entity qualifierFormat:format, self->key, self->value]; return AUTORELEASE(q); } @end /* EOKeyValueQualifier */ SOPE/sope-gdl1/GDLAccess/GDLAccess.h0000644000000000000000000000241415004363604015550 0ustar rootroot// $Id: EOAccess.h 1 2004-08-20 10:38:46Z znek $ #ifndef __GDLAccess_H__ #define __GDLAccess_H__ #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import // Kit class @interface GDLAccess : NSObject @end #endif /* __GDLAccess_H__ */ SOPE/sope-gdl1/GDLAccess/EOQuotedExpression.h0000644000000000000000000000262015004363604017564 0ustar rootroot/* EOQuotedExpression.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOQuotedExpression_h__ #define __EOQuotedExpression_h__ #import @class NSString; @interface EOQuotedExpression : NSObject { id expression; NSString *quote; NSString *escape; } - (id)expressionValueForContext:(id)context; - (id)initWithExpression:(id)expression quote:(NSString *)quote escape:(NSString *)escape; @end #endif /* __EOQuotedExpression_h__ */ SOPE/sope-gdl1/GDLAccess/EOFault.m0000644000000000000000000002260215004363604015325 0ustar rootroot/* EOAttributeOrdering.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOFault.m 1 2004-08-20 10:38:46Z znek $ #include "EOFault.h" #include "EOFaultHandler.h" #include "common.h" #if NeXT_RUNTIME || APPLE_RUNTIME # include #endif typedef struct { Class isa; } *my_objc_object; #if (defined(__GNU_LIBOBJC__) && (__GNU_LIBOBJC__ >= 20100911)) || defined(APPLE_RUNTIME) || defined(__GNUSTEP_RUNTIME__) # warning TODO: implement for NeXT/Apple runtime! # define object_is_instance(object) (object!=nil?YES:NO) # define class_get_super_class class_getSuperclass # define class_get_class_method class_getClassMethod # define class_get_instance_method class_getInstanceMethod # define METHOD_NULL NULL typedef struct objc_method *Method_t; #else # define object_is_instance(object) \ ((object!=nil)&&CLS_ISCLASS(((my_objc_object)object)->isa)) #endif #if __GNU_LIBOBJC__ >= 20100911 # define METHOD_NULL NULL # define class_get_super_class class_getSuperclass # define object_is_instance(object) (object!=nil?YES:NO) typedef struct objc_method *Method_t; #endif /* * EOFault class */ @implementation EOFault + (void)makeObjectIntoFault:(id)_object withHandler:(EOFaultHandler *)_handler{ [_handler setTargetClass:[_object class] extraData:((id *)_object)[1]]; object_setClass(_object, self); ((EOFault *)_object)->faultResolver = [_handler retain]; } + (EOFaultHandler *)handlerForFault:(id)_fault { if (![self isFault:_fault]) return nil; return ((EOFault *)_fault)->faultResolver; } /* Fault class methods */ + (void)clearFault:(id)fault { EOFault *aFault = (EOFault*)fault; int refs; /* check if fault */ if (object_getClass(aFault) != self) return; /* get fault instance reference count + 1 set in creation methods */ refs = aFault->faultResolver->faultReferences; /* make clear instance */ object_setClass(aFault, [aFault->faultResolver targetClass]); aFault->faultResolver = [aFault->faultResolver autorelease]; aFault->faultResolver = [aFault->faultResolver extraData]; /* set references to real instance so that re-implemented retain/release mechanism take control */ while(refs-- > 0) [aFault retain]; } + (BOOL)isFault:(id)fault { static Class EOFaultClass = Nil; Class clazz; if (fault == nil) return NO; if (EOFaultClass == Nil) EOFaultClass = [EOFault class]; #if defined(APPLE_RUNTIME) || defined(__GNUSTEP_RUNTIME__) || (__GNU_LIBOBJC__ >= 20100911) for (clazz = object_getClass(fault); clazz; clazz = class_getSuperclass(clazz)) { #else for (clazz = ((EOFault *)fault)->isa; clazz; clazz = clazz->super_class) { #endif if (clazz == EOFaultClass) return YES; } return NO; } + (BOOL)isFault { return NO; // no class faults } - (BOOL)isFault { return YES; } + (Class)targetClassForFault:(id)_fault { EOFault *aFault = (EOFault*)_fault; // Check that argument is fault if (object_getClass(aFault) != self) return nil; return [aFault->faultResolver targetClass]; } // Fault Instance methods - (Class)superclass { #if GNU_RUNTIME return (object_is_instance(self)) ? [[self->faultResolver classForFault:self] superclass] : class_get_super_class((Class)self); #else # warning TODO: add complete implementation for NeXT/Apple runtime! return [[self->faultResolver classForFault:self] superclass]; #endif } + (Class)class { return self; } - (Class)class { return [self->faultResolver classForFault:self]; } - (BOOL)isKindOfClass:(Class)_class; { return [self->faultResolver isKindOfClass:_class forFault:self]; } - (BOOL)isMemberOfClass:(Class)_class { return [self->faultResolver isMemberOfClass:_class forFault:self]; } - (BOOL)conformsToProtocol:(Protocol *)_protocol { return [self->faultResolver conformsToProtocol:_protocol forFault:self]; } + (BOOL)respondsToSelector:(SEL)_selector { #if GNU_RUNTIME return class_get_instance_method(self, _selector) != NULL; #else # warning TODO: add complete implementation for Apple/NeXT runtime! return NO; #endif } - (BOOL)respondsToSelector:(SEL)_selector { #if GNU_RUNTIME return (object_is_instance(self)) ? [self->faultResolver respondsToSelector:_selector forFault:self] : class_get_class_method(object_getClass(self), _selector) != METHOD_NULL; #else # warning TODO: add complete implementation for Apple/NeXT runtime! return [self->faultResolver respondsToSelector:_selector forFault:self]; #endif } // ******************** retain counting ******************** + (id)retain { return self; } - (id)retain { self->faultResolver->faultReferences++; return self; } + (oneway void)release { } - (oneway void)release { if (faultResolver->faultReferences <= 0) [self dealloc]; else faultResolver->faultReferences--; } + (NSUInteger)retainCount { return 1; } - (NSUInteger)retainCount { // For instance return faultResolver->faultReferences+1; } + (id)autorelease { return self; } - (id)autorelease { [NSAutoreleasePool addObject:self]; return self; } - (NSZone *)zone { return NSZoneFromPointer(self); } - (BOOL)isProxy { return NO; } - (BOOL)isGarbageCollectable { return NO; } + (void)dealloc { NSLog(@"WARNING: tried to deallocate EOFault class .."); } - (void)dealloc { [object_getClass(self) clearFault:self]; [self dealloc]; } /* descriptions */ - (NSString *)description { return [self->faultResolver descriptionForObject:self]; } - (NSString *)descriptionWithIndent:(unsigned)level { return [self description]; } - (NSString *)stringRepresentation { return [self description]; } - (NSString *)eoShallowDescription { return [self description]; } - (NSString *)propertyListStringWithLocale:(NSDictionary *)_locale indent:(int)_i { return [self description]; } /* Forwarding stuff */ + (void)initialize { /* Must be here as initialize is called for each root class without asking if it responds to it ! */ } static inline void _resolveFault(EOFault *self) { EOFaultHandler *handler; /* If in class */ if (!object_is_instance(self)) { [NSException raise:@"NSInvalidArgumentException" format:@"used EOFault class in forward"]; } handler = self->faultResolver; [handler completeInitializationOfObject:self]; if (object_getClass(self) == [EOFault class]) { [NSException raise:@"NSInvalidArgumentException" format: @"fault error: %@ was not cleared during fault fetching", [handler descriptionForObject:self]]; } } + (id)self { _resolveFault((id)self); return self; } #if 0 - (void)setObject:(id)object forKey:(id)key { _resolveFault(self); [self setObject:object forKey:key]; } - (id)objectForKey:(id)key { _resolveFault(self); return [self objectForKey:key]; } - (void)removeObjectForKey:(id)key { _resolveFault(self); [self removeObjectForKey:key]; } - (void)takeValuesFromDictionary:(NSDictionary *)dictionary { _resolveFault(self); [self takeValuesFromDictionary:dictionary]; } - (NSDictionary *)valuesForKeys:(NSArray *)keys { _resolveFault(self); return [self valuesForKeys:keys]; } - (BOOL)takeValue:(id)object forKey:(id)key { _resolveFault(self); return [self takeValue:object forKey:key]; } - (id)valueForKey:(id)key { _resolveFault(self); return [self valueForKey:key]; } - (BOOL)kvcIsPreferredInKeyPath { _resolveFault(self); return YES; } #endif /* 0 */ - (NSMethodSignature *)methodSignatureForSelector:(SEL)_sel { return [self->faultResolver methodSignatureForSelector:_sel forFault:self]; } - (void)forwardInvocation:(NSInvocation *)_invocation { if ([self->faultResolver shouldPerformInvocation:_invocation]) { _resolveFault(self); [_invocation invoke]; } } @end /* EOFault */ #if 0 @implementation EOFault(RealForwarding) #if NeXT_Foundation_LIBRARY - (void)forwardInvocation:(NSInvocation *)_inv { _resolveFault(self); [_inv setTarget:self]; [_inv invoke]; } #else - (retval_t)forward:(SEL)sel:(arglist_t)args { #if 1 && !defined(__APPLE__) Method_t forward; forward = class_get_instance_method(objc_lookup_class("NSObject"), _cmd); return ((retval_t (*)(id, SEL, SEL, arglist_t))forward->method_imp) (self, _cmd, sel, args); #else struct objc_method *m; _resolveFault(self); if ((m = class_get_instance_method(self->isa, sel)) == NULL) { NSString *r; r = [NSString stringWithFormat: @"fault error: resolved fault does not responds to selector %s", sel_getName(sel)]; [NSException raise:@"NSInvalidArgumentException" reason:r userInfo:nil]; } return objc_msg_sendv(self, sel, args); #endif } #endif @end /* EOFault(RealForwarding) */ #endif // #if 0 SOPE/sope-gdl1/GDLAccess/test.py0000755000000000000000000001711515004363604015207 0ustar rootroot#!/usr/bin/env python # $Id: test.py 2 2004-08-20 10:48:47Z znek $ from sys import * from Foundation import * from eoaccess import * from EOControl import * from NGExtensions import * from GDLExtensions import * import resource; defaults = NSUserDefaults(); connDict = defaults["LSConnectionDictionary"]; if connDict is None: print "missing connection dictionary\n"; exit(1); primKeyGenDict = defaults["pkeyGeneratorDictionary"]; print primKeyGenDict; if primKeyGenDict is None: print "missing pkeyGeneratorDictionary\n"; exit(1); print "ConnectionDictionary: "; print connDict.description(); adaptorName = defaults["LSAdaptor"]; if adaptorName is None: adaptorName = "Sybase10"; adaptor = EOAdaptor(adaptorName); adaptor.setConnectionDictionary(connDict); adaptor.setPkeyGeneratorDictionary(primKeyGenDict); adContext = adaptor.createAdaptorContext(); adChannel = adContext.createAdaptorChannel(); def test_database_channel(): print "adChannel " + adChannel.description() + "\n"; print "channel "; print "attributesForTableName doc"; print adChannel.invoke1("attributesForTableName:", "doc"); print "primaryKeyAttributesForTableName document _______________________________________\n"; print adChannel.invoke1("primaryKeyAttributesForTableName:", "document"); print "primaryKeyAttributesForTableName:, doc _______________________________________\n"; print adChannel.invoke1("primaryKeyAttributesForTableName:", "doc"); print "primaryKeyAttributesForTableName company _______________________________________\n"; print adChannel.invoke1("primaryKeyAttributesForTableName:", "company"); print "primaryKeyAttributesForTableName person_______________________________________\n"; print adChannel.invoke1("primaryKeyAttributesForTableName:", "person"); print "_______________________________________\n"; def test_adaptor_data_source(): adaptor = adChannel.adaptorContext().adaptor(); dict = NSMutableDictionary(); dict["login"] = "jan_1"; dict["name"] = "JR"; dict["firstname"] = "jan"; dict["is_person"] = 1; dict["number"] = "12345_1"; dict["birthday"] = NSCalendarDate('1999-09-21 13:23', '%Y-%m-%d %H:%M'); dict["middlename"] = "Ein Unnuetzer middlename"; dataSource = EOAdaptorDataSource(adChannel); hints = NSMutableDictionary(); pks = NSMutableArray(); pks.addObject("company_id"); hints.setObjectForKey(pks, "EOPrimaryKeyAttributeNamesHint") fetchSpec = EOFetchSpecification(); fetchSpec.setEntityName("company"); fetchSpec.setHints(hints); dataSource.setFetchSpecification(fetchSpec); print "-------------------- {insert ---------------------\n"; dataSource.insertObject(dict); print "-------------------- insert} ---------------------\n"; print "-------------------- {select with hints ---------------------\n"; qualifier = EOQualifier("login = %@", ("jan_1", )) fetchSpec = EOFetchSpecification(); fetchSpec.setQualifier(qualifier); fetchSpec.setEntityName("company"); hints = NSMutableDictionary(); pks.addObject("company_id"); hints.setObjectForKey(NSTimeZone('MET'), "EOFetchResultTimeZoneHint") fetchSpec.setHints(hints); sortOrderings = NSMutableArray(); sortOrderings.addObject(EOSortOrdering("login", "compareCaseInsensitiveAscending:")); sortOrderings.addObject(EOSortOrdering("company_id", "compareCaseInsensitiveDescending:")); fetchSpec.setSortOrderings(sortOrderings); dataSource = EOAdaptorDataSource(adChannel); dataSource.setFetchSpecification(fetchSpec); objs = dataSource.fetchObjects(); print objs; print "-------------------- select} ---------------------\n"; obj = objs[0]; print "-------------------- {update ---------------------\n"; print obj; obj["login"] = "jan_1_1"; obj["middlename"] = EONull(); dataSource.updateObject(obj); print "-------------------- update} ---------------------\n"; qualifier = EOQualifier("login caseInsensitiveLike %@", ("jan_1_*", )) fetchSpec.setQualifier(qualifier); dataSource.setFetchSpecification(fetchSpec); print "-------------------- {select ---------------------\n"; objs = dataSource.fetchObjects(); print objs; print "-------------------- select} ---------------------\n"; print "-------------------- {delete ---------------------\n"; obj = objs[0]; dataSource.deleteObject(obj); print "-------------------- delete} ---------------------\n"; print "-------------------- {select ---------------------\n"; objs = dataSource.fetchObjects(); print objs; print "-------------------- select} ---------------------\n"; def test_cascaded_datasources(): adaptor = adChannel.adaptorContext().adaptor(); dict = NSMutableDictionary(); dict["login"] = "jan_1"; dict["name"] = "JR"; dict["firstname"] = "jan"; dict["is_person"] = 1; dict["number"] = "12345_1"; dataSource = EOAdaptorDataSource(adChannel); fetchSpec = EOFetchSpecification(); fetchSpec.setEntityName("company"); qualifier = EOQualifier("login like %@", ("j%", )) fetchSpec = EOFetchSpecification(); fetchSpec.setQualifier(qualifier); fetchSpec.setEntityName("company"); sortOrderings = NSMutableArray(); sortOrderings.addObject(EOSortOrdering("login", "compareCaseInsensitiveAscending:")); fetchSpec.setSortOrderings(sortOrderings); hints = NSMutableDictionary(); pks = NSMutableArray(); pks.addObject("company_id"); hints.setObjectForKey(pks, "EOPrimaryKeyAttributeNamesHint") fetchSpec.setHints(hints); dataSource.setFetchSpecification(fetchSpec); cacheDataSource = EOCacheDataSource(dataSource); objs = dataSource.fetchObjects(); print objs; print cacheDataSource.fetchObjects(); print "-----------------------------\n"; print cacheDataSource.fetchObjects(); dataSource.insertObject(dict); print "++++++++++++++++++++++++++++\n"; fetchSpec = EOFetchSpecification(); fetchSpec.setEntityName("company"); qualifier = EOQualifier("login = %@", ("jan_1", )) fetchSpec = EOFetchSpecification(); fetchSpec.setQualifier(qualifier); fetchSpec.setEntityName("company"); dataSource.setFetchSpecification(fetchSpec); cacheDataSource = EOCacheDataSource(dataSource); objs = dataSource.fetchObjects(); obj = objs[0]; print objs; print "-----------------------------\n"; print cacheDataSource.deleteObject(obj); print "++++++++++++++++++++++++++++\n"; print cacheDataSource.fetchObjects(); def echo_logins(objs): for o in objs: print o['login']; def test_sort_datasource(): dataSource = EOAdaptorDataSource(adChannel); fetchSpec = EOFetchSpecification(); fetchSpec.setEntityName("company"); qualifier = EOQualifier("login like %@", ("%a%", )) fetchSpec.setQualifier(qualifier); dataSource.setFetchSpecification(fetchSpec); echo_logins(dataSource.fetchObjects()); sortOrderings = NSMutableArray(); sO = EOSortOrdering("login", "compareDescending:"); sortOrderings.addObject(sO); fetchSpec.setSortOrderings(sortOrderings); dataSource.setFetchSpecification(fetchSpec); echo_logins(dataSource.fetchObjects()); print resource.getrlimit(resource.RLIMIT_CORE); if adChannel.openChannel(): print "open channel ok"; else: print "open channel failed"; exit(1); print "adChannel ", adChannel; #test_database_channel(); test_adaptor_data_source(); #test_cascaded_datasources(); #test_sort_datasource(); SOPE/sope-gdl1/GDLAccess/EOPrimaryKeyDictionary.m0000644000000000000000000002470215004363604020377 0ustar rootroot/* EOPrimaryKeyDictionary.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "EOPrimaryKeyDictionary.h" #import /* * Concrete Classes declaration */ @interface EOSinglePrimaryKeyDictionary : EOPrimaryKeyDictionary { id key; id value; } - (id)initWithObject:(id)anObject forKey:(id)aKey; - (id)key; @end @interface EOSinglePrimaryKeyDictionaryEnumerator : NSEnumerator { id key; } - (id)iniWithObject:(id)_key; @end @interface EOMultiplePrimaryKeyDictionary : EOPrimaryKeyDictionary { int count; NSArray *keys; id values[0]; } + (id)allocWithZone:(NSZone *)_zone capacity:(int)_capacity; - (id)initWithKeys:(NSArray *)_keys fromDictionary:(NSDictionary *)_dict; @end /* * Single key dictionary */ @implementation EOSinglePrimaryKeyDictionary - (id)initWithObject:(id)_object forKey:(id)_key { NSAssert(_key, @"provided invalid key (is nil)"); NSAssert1(_object, @"provided invalid value (is nil), key=%@", _key); if ([_object isKindOfClass:[EONull class]]) { NSLog(@"value of primary key %@ is null ..", _key); RELEASE(self); return nil; } NSAssert(![_object isKindOfClass:[EONull class]], @"value of primary key may not be null !"); self->key = RETAIN(_key); self->value = RETAIN(_object); self->fastHash = [_object hash]; return self; } - (void)dealloc { RELEASE(self->key); RELEASE(self->value); [super dealloc]; } /* operations */ - (NSEnumerator *)keyEnumerator { return AUTORELEASE([[EOSinglePrimaryKeyDictionaryEnumerator alloc] iniWithObject:self->key]); } - (id)objectForKey:(id)_key { return [key isEqual:_key] ? value : nil; } - (NSUInteger)count { return 1; } - (BOOL)isNotEmpty { return YES; } - (NSUInteger)hash { return 1; } - (id)key { return self->key; } - (NSArray *)allKeys { return [NSArray arrayWithObject:key]; } - (NSArray *)allValues { return [NSArray arrayWithObject:value]; } - (BOOL)isEqualToDictionary:(NSDictionary *)other { if (self == (EOSinglePrimaryKeyDictionary*)other) return YES; if (object_getClass(self) == object_getClass(other)) { if (fastHash == ((EOSinglePrimaryKeyDictionary*)other)->fastHash && [key isEqual:((EOSinglePrimaryKeyDictionary*)other)->key] && [value isEqual:((EOSinglePrimaryKeyDictionary*)other)->value]) return YES; else return NO; } if ([other count] != 1) return NO; return [value isEqual:[other objectForKey:key]]; } - (id)copyWithZone:(NSZone*)zone { if ([self zone] == (zone ? zone : NSDefaultMallocZone())) return RETAIN(self); else return [[[self class] allocWithZone:zone] initWithObject:value forKey:key]; } - (id)copy { return [self copyWithZone:NULL]; } - (BOOL)fastIsEqual:(id)other { if (self == other) return YES; if (object_getClass(self) == object_getClass(other)) { if (fastHash == ((EOSinglePrimaryKeyDictionary*)other)->fastHash && key == ((EOSinglePrimaryKeyDictionary*)other)->key && [value isEqual:((EOSinglePrimaryKeyDictionary*)other)->value]) return YES; else return NO; } [NSException raise:NSInvalidArgumentException format: @"fastIsEqual: compares only " @"EOPrimaryKeyDictionary instances !"]; return NO; } @end /* EOSinglePrimaryKeyDictionary */ @implementation EOSinglePrimaryKeyDictionaryEnumerator - (id)iniWithObject:(id)aKey { self->key = RETAIN(aKey); return self; } - (void)dealloc { RELEASE(self->key); [super dealloc]; } /* operations */ - (id)nextObject { id tmp = self->key; self->key = nil; return AUTORELEASE(tmp); } @end /* EOSinglePrimaryKeyDictionaryEnumerator */ /* * Multiple key dictionary is very time-memory efficient */ @implementation EOMultiplePrimaryKeyDictionary + (id)allocWithZone:(NSZone *)zone capacity:(int)capacity { return NSAllocateObject(self, sizeof(id)*capacity, zone); } - (id)initWithKeys:(NSArray*)theKeys fromDictionary:(NSDictionary*)dict; { int i; self->count = [theKeys count]; self->keys = RETAIN(theKeys); self->fastHash = 0; for (i = 0; i < count; i++) { self->values[i] = [dict objectForKey:[keys objectAtIndex:i]]; RETAIN(self->values[i]); NSAssert(![values[i] isKindOfClass:[EONull class]], @"primary key values may not be null !"); if (self->values[i] == nil) { AUTORELEASE(self); return nil; } self->fastHash += [self->values[i] hash]; } return self; } - (void)dealloc { int i; for (i = 0; i < count; i++) RELEASE(self->values[i]); RELEASE(self->keys); [super dealloc]; } /* operations */ - (NSEnumerator *)keyEnumerator { return [self->keys objectEnumerator]; } - (id)objectForKey:(id)aKey { int max, min, mid; // Binary search for key's index for (min = 0, max = count-1; min <= max; ) { NSComparisonResult ord; mid = (min+max) >> 1; ord = [(NSString*)aKey compare:(NSString*)[keys objectAtIndex:mid]]; if (ord == NSOrderedSame) return values[mid]; if (ord == NSOrderedDescending) min = mid+1; else max = mid-1; } return nil; } - (NSUInteger)count { return self->count; } - (BOOL)isNotEmpty { return self->count > 0 ? YES : NO; } - (NSUInteger)hash { return self->count; } - (NSArray *)allKeys { return self->keys; } - (NSArray *)allValues { return AUTORELEASE([[NSArray alloc] initWithObjects:values count:count]); } - (BOOL)isEqualToDictionary:(NSDictionary *)other { int i; if (self == (EOMultiplePrimaryKeyDictionary*)other) return YES; if ((unsigned)self->count != [other count]) return NO; for (i = 0; i < self->count; i++) { if (![values[i] isEqual:[other objectForKey:[keys objectAtIndex:i]]]) return NO; } return YES; } - (id)copyWithZone:(NSZone *)zone { if ([self zone] == (zone ? zone : NSDefaultMallocZone())) return RETAIN(self); else { return [[[self class] allocWithZone:zone capacity:count] initWithKeys:keys fromDictionary:self]; } } - (id)copy { return [self copyWithZone:NULL]; } - (unsigned)fastHash { return self->fastHash; } - (BOOL)fastIsEqual:(id)aDict { int i; if (object_getClass(self) == object_getClass(aDict)) { [NSException raise:NSInvalidArgumentException format:@"fastIsEqual: can compare only " @"EOPrimaryKeyDictionary instances"]; } if (self->count != ((EOMultiplePrimaryKeyDictionary*)aDict)->count || self->fastHash != ((EOMultiplePrimaryKeyDictionary*)aDict)->fastHash || self->keys != ((EOMultiplePrimaryKeyDictionary*)aDict)->keys) return NO; for (i = count - 1; i >= 0; i--) { if (![values[i] isEqual: ((EOMultiplePrimaryKeyDictionary*)aDict)->values[i]]) return NO; } return YES; } @end /* EOMultiplePrimaryKeyDictionary */ /* * Cluster Abstract class */ @implementation EOPrimaryKeyDictionary + (id)allocWithZone:(NSZone *)_zone { return NSAllocateObject(self, 0, _zone); } + (id)dictionaryWithKeys:(NSArray *)keys fromDictionary:(NSDictionary *)dict { if ([dict count] == 0) return nil; if ([keys count] == 1) { id key = [keys objectAtIndex:0]; id keyValue = [dict objectForKey:key]; NSAssert2(keyValue, @"dictionary %@ contained no value for key %@ ..", dict, key); // Check if already an EOSinglePrimaryKeyDictionary from same entity // return it since the new one will be identical to it; we have // no problem regarding its correctness since it was built by this // method ! if ([dict isKindOfClass:[EOSinglePrimaryKeyDictionary class]]) { if ([(EOSinglePrimaryKeyDictionary*)dict key]==key) return dict; } //HH: // Check if the keyValue is EONull. If this is the case, return nil. // Primary keys are always 'not null'. if ([keyValue isKindOfClass:[EONull class]]) return nil; // Alloc single key dictionary return AUTORELEASE([[EOSinglePrimaryKeyDictionary alloc] initWithObject:keyValue forKey:key]); } else { // Check if already an EOMultiplePrimaryKeyDictionary from same entity // return it since the new one will be identical to it; we have // no problem regarding its correctness since it was built by this // method ! if ([dict isKindOfClass:[EOMultiplePrimaryKeyDictionary class]] && [dict allKeys] == keys) return dict; // Alloc multi-key dictionary return AUTORELEASE([[EOMultiplePrimaryKeyDictionary allocWithZone:NULL capacity:[keys count]] initWithKeys:keys fromDictionary:dict]); } } + (id)dictionaryWithObject:(id)object forKey:(id)key { return AUTORELEASE([[EOSinglePrimaryKeyDictionary alloc] initWithObject:object forKey:key]); } - (unsigned)fastHash { return self->fastHash; } - (BOOL)fastIsEqual:aDict { // TODO - request concrete implementation return NO; } @end /* EOPrimaryKeyDictionary */ SOPE/sope-gdl1/GDLAccess/EOKeySortOrdering.m0000644000000000000000000000724215004363604017347 0ustar rootroot/* EOKeySortOrdering.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #import #import #import #import "common.h" #import "EOKeySortOrdering.h" #import @implementation EOKeySortOrdering + keyOrderingWithKey:(NSString*)aKey ordering:(NSComparisonResult)anOrdering { return AUTORELEASE([[EOKeySortOrdering alloc] initWithKey:aKey ordering:anOrdering]); } - initWithKey:(NSString*)aKey ordering:(NSComparisonResult)anOrdering { ASSIGN(key, aKey); ordering = anOrdering; return self; } - (NSString*)key {return key;} - (NSComparisonResult)ordering {return ordering;} @end // TODO : integrate this function in the two methods above and optimize // object creation and method calls for objects that provide quick // access to their values - do not use nested functions static NSComparisonResult _keySortCompare(id obj1, id obj2, NSArray* order) __attribute__((unused)); static NSComparisonResult _keySortCompare(id obj1, id obj2, NSArray* order) { int i, n; for (i = 0, n = [order count]; i < n; i++) { id val1, val2, key, kar; NSComparisonResult ord, vord; EOKeySortOrdering* kso = [order objectAtIndex:i]; key = [kso key]; ord = [kso ordering]; kar = [NSArray arrayWithObject:key]; val1 = [[obj1 valuesForKeys:kar] objectForKey:key]; val2 = [[obj2 valuesForKeys:kar] objectForKey:key]; if (!val1 && !val2) continue; if (!val1 && val2) return ord == NSOrderedAscending ? NSOrderedAscending : NSOrderedDescending; if (val1 && !val2) return ord == NSOrderedAscending ? NSOrderedDescending : NSOrderedAscending; vord = [(NSString *)val1 compare:val2]; if (vord == NSOrderedSame) continue; if (vord == NSOrderedAscending) return ord == NSOrderedAscending ? NSOrderedAscending : NSOrderedDescending; else return ord == NSOrderedAscending ? NSOrderedDescending : NSOrderedAscending; } return NSOrderedSame; } #if 0 @implementation NSArray(EOKeyBasedSorting) - (NSArray*)sortedArrayUsingKeyOrderArray:(NSArray*)orderArray { NSArray* arry; CREATE_AUTORELEASE_POOL(pool); arry = [self sortedArrayUsingFunction: (int(*)(id, id, void*))_keySortCompare context:orderArray]; RELEASE(pool); return arry; } @end @implementation NSMutableArray(EOKeyBasedSorting) - (void)sortUsingKeyOrderArray:(NSArray*)orderArray { CREATE_AUTORELEASE_POOL(pool); [self sortUsingFunction: (int(*)(id, id, void*))_keySortCompare context:orderArray]; RELEASE(pool); } @end #endif /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/EODatabase.m0000644000000000000000000003236515004363604015765 0ustar rootroot/* EODatabase.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "common.h" #import "EODatabase.h" #import "EOAdaptor.h" #import "EOModel.h" #import "EOEntity.h" #import "EOGenericRecord.h" #import "EODatabaseContext.h" #import "EOObjectUniquer.h" #import "EODatabaseFault.h" NSTimeInterval NSDistantPastTimeInterval = 0.0; @implementation EODatabase // Database Global Methods static NSMutableArray *databaseInstances = nil; static NSRecursiveLock *lock = nil; + (void)initialize { static BOOL isInitialized = NO; // THREAD if (!isInitialized) { isInitialized = YES; databaseInstances = [[NSMutableArray alloc] init]; lock = [[NSRecursiveLock alloc] init]; } } static inline void _addDatabaseInstance(EODatabase *_db) { [lock lock]; [databaseInstances addObject:[NSValue valueWithNonretainedObject:_db]]; [lock unlock]; } static inline void _removeDatabaseInstance(EODatabase *_db) { [lock lock]; { int i; for (i = [databaseInstances count] - 1; i >= 0; i--) { EODatabase *db; db = [[databaseInstances objectAtIndex:i] nonretainedObjectValue]; if (db == _db) { [databaseInstances removeObjectAtIndex:i]; break; } } } [lock unlock]; } /* * Initializing new instances */ - (id)initWithAdaptor:(EOAdaptor *)_adaptor { if (_adaptor == nil) { AUTORELEASE(self); return nil; } self->adaptor = RETAIN(_adaptor); self->objectsDictionary = [[EOObjectUniquer allocWithZone:[self zone]] init]; self->contexts = [[NSMutableArray allocWithZone:[self zone]] init]; self->flags.isUniquingObjects = YES; self->flags.isKeepingSnapshots = YES; self->flags.isLoggingWarnings = YES; _addDatabaseInstance(self); return self; } - (id)initWithModel:(EOModel *)_model { return [self initWithAdaptor:[EOAdaptor adaptorWithModel:_model]]; } - (id)init { return [self initWithAdaptor:nil]; } - (void)dealloc { _removeDatabaseInstance(self); RELEASE(self->adaptor); RELEASE(self->objectsDictionary); RELEASE(self->contexts); [super dealloc]; } // accessors - (EOAdaptor *)adaptor { return self->adaptor; } - (EOObjectUniquer *)objectUniquer { return self->objectsDictionary; } // Checking connection status - (BOOL)hasOpenChannels { int i; for (i = ([self->contexts count] - 1); i >= 0; i--) { if ([[[self->contexts objectAtIndex:i] nonretainedObjectValue] hasOpenChannels]) return YES; } return NO; } /* * Getting the database contexts */ - (id)createContext { return AUTORELEASE([[EODatabaseContext alloc] initWithDatabase:self]); } - (NSArray *)contexts { NSMutableArray *array = nil; int i, n; n = [self->contexts count]; array = [[NSMutableArray alloc] initWithCapacity:n]; for (i = 0; i < n; i++) { EODatabaseContext *ctx; ctx = [[self->contexts objectAtIndex:i] nonretainedObjectValue]; [array addObject:ctx]; } return AUTORELEASE(array); } - (void)contextDidInit:(id)_context { [self->contexts addObject:[NSValue valueWithNonretainedObject:_context]]; } - (void)contextWillDealloc:(id)aContext { int i; for (i = [self->contexts count]-1; i >= 0; i--) { if ([[self->contexts objectAtIndex:i] nonretainedObjectValue] == aContext) { [self->contexts removeObjectAtIndex:i]; break; } } } /* * Uniquing/snapshotting */ - (void)setUniquesObjects:(BOOL)yn { if ([self hasOpenChannels]) { [NSException raise:NSInvalidArgumentException format: @"EODatabase:%@: All channels must be closed when changing " @"uniquing mode in the EODatabase, " @"in [EODatabase setUniquesObjects:]", self]; } if ((!yn) && (self->flags.isUniquingObjects)) [self->objectsDictionary forgetAllObjects]; self->flags.isUniquingObjects = yn; } - (BOOL)uniquesObjects { return self->flags.isUniquingObjects; } - (void)setKeepsSnapshots:(BOOL)yn { if ([self hasOpenChannels]) { [NSException raise:NSInvalidArgumentException format: @"EODatabase:%@: All channels must be closed when changing " @"snapshoting mode in the EODatabase, " @"in [EODatabase setKeepsSnapshots:]", self]; } if ((yn == NO) && self->flags.isKeepingSnapshots) [self->objectsDictionary forgetAllSnapshots]; self->flags.isKeepingSnapshots = yn; } - (BOOL)keepsSnapshots { return self->flags.isKeepingSnapshots; } // ******************** Handle Objects ******************** - (void)forgetAllObjects { [self->objectsDictionary forgetAllObjects]; } + (void)forgetObject:(id)_object { static Class UniquerClass = Nil; if (UniquerClass == Nil) UniquerClass = [EOObjectUniquer class]; [(EOObjectUniquer *)UniquerClass forgetObject:_object]; [lock lock]; { int i; for (i = [databaseInstances count] - 1; i >= 0; i--) { EODatabase *db; db = [[databaseInstances objectAtIndex:i] nonretainedObjectValue]; [db forgetObject:_object]; } } [lock unlock]; } - (void)forgetObject:(id)_object { /* NSLog(@"DB[0x%p]: forget object 0x%p<%s> entity=%@", self, _object, class_get_class_name(*(Class *)_object), [[_object entity] name]); */ [self->objectsDictionary forgetObject:_object]; } - (void)forgetAllSnapshots { [self->objectsDictionary forgetAllSnapshots]; } - (id)objectForPrimaryKey:(NSDictionary *)_key entity:(EOEntity *)_entity { if (self->flags.isUniquingObjects && (_key != nil) && (_entity != nil)) { _key = [_entity primaryKeyForRow:_key]; if (_key == nil) return nil; else { id object = [self->objectsDictionary objectForPrimaryKey:_key entity:_entity]; #if 0 if (object) { if (![object isKindOfClass:[EOGenericRecord class]]) NSLog(@"object 0x%p pkey=%@ entity=%@", object, _key, _entity); } #endif return object; } } return nil; } - (NSDictionary *)snapshotForObject:_object { EOUniquerRecord* rec = [self->objectsDictionary recordForObject:_object]; return rec ? rec->snapshot : nil; } - (NSDictionary *)primaryKeyForObject:(id)_object { EOUniquerRecord* rec = [self->objectsDictionary recordForObject:_object]; return rec ? rec->pkey : nil; } - (void)primaryKey:(NSDictionary**)_key andSnapshot:(NSDictionary**)_snapshot forObject:(id)_object { EOUniquerRecord *rec = [self->objectsDictionary recordForObject:_object]; if (rec) { if (_key) *_key = rec->pkey; if (_snapshot) *_snapshot = rec->snapshot; } else { if (_key) *_key = nil; if (_snapshot) *_snapshot = nil; } } - (void)recordObject:(id)_object primaryKey:(NSDictionary *)_key snapshot:(NSDictionary *)_snapshot { EOEntity *entity; entity = [_object respondsToSelector:@selector(entity)] ? [_object entity] : [[self->adaptor model] entityForObject:_object]; [self recordObject:_object primaryKey:_key entity:entity snapshot:_snapshot]; } - (void)recordObject:(id)_object primaryKey:(NSDictionary *)_key entity:(EOEntity *)_entity snapshot:(NSDictionary *)_snapshot { if (_object == nil) { [NSException raise:NSInvalidArgumentException format: @"EODatabase:%@: Cannot record null object, " @"in [EODatabase recordObject:primaryKey:entity:snapshot:]", self]; } if ((_entity == nil) && self->flags.isUniquingObjects) { [NSException raise:NSInvalidArgumentException format: @"EODatabase:%@: Cannot record object with null entity " @"when the database is uniquing objects, " @"in [EODatabase recordObject:primaryKey:entity:snapshot:]", self]; } _key = [_entity primaryKeyForRow:_key]; if ((_key == nil) && self->flags.isUniquingObjects) { [NSException raise:NSInvalidArgumentException format: @"EODatabase:%@: Cannot record object with null key " @"when the database is uniquing objects, " @"in [EODatabase recordObject:primaryKey:entity:snapshot:]", self]; } if ((_snapshot == nil) && self->flags.isKeepingSnapshots) { [NSException raise:NSInvalidArgumentException format: @"EODatabase:%@: Cannot record object with null snapshot " @"when the database is keeping snapshots, " @"in [EODatabase recordObject:primaryKey:entity:snapshot:]", self]; } [objectsDictionary recordObject:_object primaryKey: self->flags.isUniquingObjects ? _key:(NSDictionary *)nil entity:self->flags.isUniquingObjects ?_entity : (EOEntity *)nil snapshot: self->flags.isKeepingSnapshots ? _snapshot : (NSDictionary *)nil]; } - (BOOL)isObject:(id)_object updatedOutsideContext:(EODatabaseContext *)_context { int i; for (i = [contexts count] - 1; i >= 0; i--) { EODatabaseContext *ctx; ctx = [[self->contexts objectAtIndex:i] nonretainedObjectValue]; if ((ctx != _context) && [ctx isObjectUpdated:_object]) return YES; } return NO; } // ******************** Error messages ******************** - (void)setLogsErrorMessages:(BOOL)yn { self->flags.isLoggingWarnings = yn; } - (BOOL)logsErrorMessages { return self->flags.isLoggingWarnings; } - (void)reportErrorFormat:(NSString*)format, ... { va_list va; va_start(va, format); [self reportErrorFormat:format arguments:va]; va_end(va); } - (void)reportErrorFormat:(NSString*)format arguments:(va_list)arguments { [self reportError:AUTORELEASE([[NSString alloc] initWithFormat:format arguments:arguments])]; } - (void)reportError:(NSString*)error { if (self->flags.isLoggingWarnings) NSLog(@"EODatabase:%@:%@", self, error); } @end /* EODatabase */ @implementation EODatabase(EOF2Additions) - (NSArray *)models { EOModel *model; model = [[self adaptor] model]; return model ? [NSArray arrayWithObject:model] : nil; } - (void)addModel:(EOModel *)_model { EOModel *model; model = [[self adaptor] model]; if (model == nil) [[self adaptor] setModel:_model]; else [self notImplemented:_cmd]; } - (BOOL)addModelIfCompatible:(EOModel *)_model { NSEnumerator *e; EOModel *m; if (![[self adaptor] canServiceModel:_model]) return NO; e = [[self models] objectEnumerator]; while ((m = [e nextObject])) { if (m == _model) return YES; if (![[m adaptorName] isEqualToString:[_model adaptorName]]) return NO; } [self addModel:_model]; return YES; } - (EOEntity *)entityForObject:(id)_object { return [[[self adaptor] model] entityForObject:_object]; } - (EOEntity *)entityNamed:(NSString *)_name { return [[[self adaptor] model] entityNamed:_name]; } /* snapshots */ - (void)forgetSnapshotsForGlobalIDs:(NSArray *)_gids { NSEnumerator *e; EOGlobalID *gid; e = [_gids objectEnumerator]; while ((gid = [e nextObject])) [self forgetSnapshotsForGlobalID:gid]; } - (void)forgetSnapshotsForGlobalID:(EOGlobalID *)_gid { [self notImplemented:_cmd]; } - (void)recordSnapshot:(NSDictionary *)_snapshot forGlobalID:(EOGlobalID *)_gid { [self notImplemented:_cmd]; } - (void)recordSnapshots:(NSDictionary *)_snapshots { NSEnumerator *gids; EOGlobalID *gid; gids = [_snapshots keyEnumerator]; while ((gid = [gids nextObject])) [self recordSnapshot:[_snapshots objectForKey:gid] forGlobalID:gid]; } - (void)recordSnapshot:(NSArray *)_gids forSourceGlobalID:(EOGlobalID *)_gid relationshipName:(NSString *)_name { /* to-many snapshot */ [self notImplemented:_cmd]; } - (void)recordToManySnapshots:(NSDictionary *)_snapshots { NSEnumerator *gids; EOGlobalID *gid; gids = [_snapshots keyEnumerator]; while ((gid = [gids nextObject])) { NSDictionary *d; NSEnumerator *relNames; NSString *relName; d = [_snapshots objectForKey:gid]; relNames = [d keyEnumerator]; while ((relName = [relNames nextObject])) { [self recordSnapshot:[d objectForKey:relName] forSourceGlobalID:gid relationshipName:relName]; } } } - (NSDictionary *)snapshotForGlobalID:(EOGlobalID *)_gid after:(NSTimeInterval)_duration { NSLog(@"ERROR(%s): subclasses must override this method!", __PRETTY_FUNCTION__); return nil; } - (NSDictionary *)snapshotForGlobalID:(EOGlobalID *)_gid { return [self snapshotForGlobalID:_gid after:NSDistantPastTimeInterval]; } @end /* EODatabase(EOF2Additions) */ SOPE/sope-gdl1/GDLAccess/EOAttributeOrdering.h0000644000000000000000000000320715004363604017702 0ustar rootroot/* EOAttributeOrdering.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOAttributeOrdering_h__ #define __EOAttributeOrdering_h__ #import @class EOAttribute; typedef enum { EOAnyOrder, EOAscendingOrder, EODescendingOrder } EOOrdering; @interface EOAttributeOrdering : NSObject { EOAttribute* attribute; EOOrdering ordering; } /* Creating an attribute ordering */ + attributeOrderingWithAttribute:(EOAttribute*)attribute ordering:(EOOrdering)ordering; - initWithAttribute:(EOAttribute*)attribute ordering:(EOOrdering)ordering; /* Getting values */ - (EOAttribute*)attribute; - (EOOrdering)ordering; @end #endif /* __EOAttributeOrdering_h__ */ /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/EOSQLExpression.h0000644000000000000000000002016015004363604016761 0ustar rootroot/* EOSQLExpression.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: September 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOSQLExpression_h__ #define __EOSQLExpression_h__ #import #import #include #include /* EOSQLExpression TODO: document Apparently the only object which implements EOExpressionContext? */ @class EOAdaptor, EOAdaptorChannel, EOEntity, EOSQLQualifier; extern NSString *EOBindVariableNameKey; extern NSString *EOBindVariablePlaceHolderKey; extern NSString *EOBindVariableAttributeKey; extern NSString *EOBindVariableValueKey; @interface EOSQLExpression : NSObject { EOEntity *entity; EOAdaptor *adaptor; NSMutableDictionary *entitiesAndPropertiesAliases; NSMutableArray *fromListEntities; NSMutableString *content; /* new in EOF2 */ NSString *whereClauseString; NSMutableString *listString; NSMutableArray *bindings; } /* Building SQL expressions */ + (id)deleteExpressionWithQualifier:(EOSQLQualifier *)qualifier channel:(EOAdaptorChannel *)channel; + (id)insertExpressionForRow:(NSDictionary *)row entity:(EOEntity *)entity channel:(EOAdaptorChannel *)channel; + (id)selectExpressionForAttributes:(NSArray *)attributes lock:(BOOL)flag qualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder channel:(EOAdaptorChannel *)channel; + (id)updateExpressionForRow:(NSDictionary *)row qualifier:(EOSQLQualifier *)qualifier channel:(EOAdaptorChannel *)channel; - (id)deleteExpressionWithQualifier:(EOSQLQualifier *)qualifier channel:(EOAdaptorChannel *)channel; - (id)insertExpressionForRow:(NSDictionary *)row entity:(EOEntity *)entity channel:(EOAdaptorChannel *)channel; - (id)selectExpressionForAttributes:(NSArray *)attributes lock:(BOOL)flag qualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder channel:(EOAdaptorChannel *)channel; - (id)updateExpressionForRow:(NSDictionary *)row qualifier:(EOSQLQualifier *)qualifier channel:(EOAdaptorChannel *)channel; /* factory classes */ + (Class)selectExpressionClass; + (Class)insertExpressionClass; + (Class)deleteExpressionClass; + (Class)updateExpressionClass; /* Getting the adaptor */ - (EOAdaptor *)adaptor; // Private methods. /* Creating components for the SELECT operation */ - (NSString *)selectListWithAttributes:(NSArray *)attributes qualifier:(EOSQLQualifier *)qualifier; - (NSString *)fromClause; - (NSString *)whereClauseForQualifier:(EOSQLQualifier *)qualifier; - (NSString *)joinExpressionForRelationshipPaths:(NSArray *)relationshipPaths; - (NSString *)lockClause; - (NSString *)orderByClauseForFetchOrder:(NSArray *)fetchOrder; /* Creating components for the UPDATE operation */ - (id)updateListForRow:(NSDictionary *)row; /* Creating components for the INSERT operation */ - (id)columnListForRow:(NSDictionary *)row; - (id)valueListForRow:(NSDictionary *)row; /* Final initialization */ - (id)finishBuildingExpression; /* Caching aliases */ - (NSArray *)relationshipPathsForAttributes:(NSArray *)attributes qualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder; /* Getting the entity */ - (EOEntity *)entity; /* Getting the expression value of an attribute in a given context. This method is used by the expressionValueForAttribute: method. */ - (NSString *)expressionValueForAttribute:(EOAttribute *)attribute context:context; @end @class NSArray; @class EOFetchSpecification, EOKeyComparisonQualifier, EOKeyValueQualifier; @class EOQualifier; @interface EOSQLExpression(NewInEOF2) + (EOSQLExpression *)selectStatementForAttributes:(NSArray *)_attributes lock:(BOOL)_flag fetchSpecification:(EOFetchSpecification *)_fspec entity:(EOEntity *)_entity; + (EOSQLExpression *)expressionForString:(NSString *)_sql; /* accessors */ - (void)setStatement:(NSString *)_stmt; - (NSString *)statement; - (NSString *)whereClauseString; /* tables */ - (NSString *)tableListWithRootEntity:(EOEntity *)_entity; /* assembly */ - (NSString *)assembleDeleteStatementWithQualifier:(EOQualifier *)_qualifier tableList:(NSString *)_tableList whereClause:(NSString *)_whereClause; - (NSString *)assembleInsertStatementWithRow:(NSDictionary *)_row tableList:(NSString *)_tables columnList:(NSString *)_columns valueList:(NSString *)_values; - (NSString *)assembleSelectStatementWithAttributes:(NSArray *)_attributes lock:(BOOL)_lock qualifier:(EOQualifier *)_qualifier fetchOrder:(NSArray *)_fetchOrder selectString:(NSString *)_selectString columnList:(NSString *)_columns tableList:(NSString *)_tables whereClause:(NSString *)_whereClause joinClause:(NSString *)_joinClause orderByClause:(NSString *)_orderByClause lockClause:(NSString *)_lockClause; - (NSString *)assembleUpdateStatementWithRow:(NSDictionary *)_row qualifier:(EOQualifier *)_qualifier tableList:(NSString *)_tables updateList:(NSString *)_updates whereClause:(NSString *)_whereClause; - (NSString *)assembleJoinClauseWithLeftName:(NSString *)_leftName rightName:(NSString *)_rightName joinSemantic:(EOJoinSemantic)_semantic; /* bind variables */ - (BOOL)mustUseBindVariableForAttribute:(EOAttribute *)_attr; - (BOOL)shouldUseBindVariableForAttribute:(EOAttribute *)_attr; + (BOOL)useBindVariables; - (NSMutableDictionary *)bindVariableDictionaryForAttribute:(EOAttribute *)_attr value:(id)_value; - (void)addBindVariableDictionary:(NSMutableDictionary *)_dictionary; - (NSArray *)bindVariableDictionaries; /* values */ + (NSString *)formatValue:(id)_value forAttribute:(EOAttribute *)_attribute; - (NSString *)sqlStringForValue:(id)_value attributeNamed:(NSString *)_attrName; + (NSString *)sqlPatternFromShellPattern:(NSString *)_pattern; /* attributes */ - (NSString *)sqlStringForAttribute:(EOAttribute *)_attribute; - (NSString *)sqlStringForAttributePath:(NSString *)_attrPath; - (NSString *)sqlStringForAttributeNamed:(NSString *)_attrName; /* SQL formats */ + (NSString *)formatSQLString:(NSString *)_sqlString format:(NSString *)_fmt; /* qualifier operators */ - (NSString *)sqlStringForSelector:(SEL)_selector value:(id)_value; /* qualifiers */ - (NSString *)sqlStringForKeyComparisonQualifier:(EOKeyComparisonQualifier *)_q; - (NSString *)sqlStringForKeyValueQualifier:(EOKeyValueQualifier *)_q; - (NSString *)sqlStringForNegatedQualifier:(EOQualifier *)_q; - (NSString *)sqlStringForConjoinedQualifiers:(NSArray *)_qs; - (NSString *)sqlStringForDisjoinedQualifiers:(NSArray *)_qs; /* list strings */ - (NSMutableString *)listString; - (void)appendItem:(NSString *)_itemString toListString:(NSMutableString *)_lstr; /* deletes */ - (void)prepareDeleteExpressionForQualifier:(EOQualifier *)_qualifier; /* updates */ - (void)addUpdateListAttribute:(EOAttribute *)_attr value:(NSString *)_value; - (void)prepareUpdateExpressionWithRow:(NSDictionary *)_row qualifier:(EOQualifier *)_qualifier; @end /* Private subclasses used by EOSQLExpression. */ @interface EOSelectSQLExpression : EOSQLExpression @end @interface EOUpdateSQLExpression : EOSQLExpression @end @interface EOInsertSQLExpression : EOSQLExpression @end @interface EODeleteSQLExpression : EOSQLExpression @end #endif /* __EOSQLExpression_h__ */ /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/EORecordDictionary.h0000644000000000000000000000203715004363604017511 0ustar rootroot/* */ #ifndef __EORecordDictionary_h__ #define __EORecordDictionary_h__ #import typedef struct _EORecordDictionaryEntry { unsigned hash; id key; id value; } EORecordDictionaryEntry; @interface EORecordDictionary : NSDictionary { unsigned char count; EORecordDictionaryEntry entries[1]; } /* Allocating and Initializing an Dictionary */ - (id)initWithObjects:(id*)objects forKeys:(id*)keys count:(NSUInteger)count; - (id)initWithDictionary:(NSDictionary*)dictionary; /* Accessing keys and values */ - (id)objectForKey:(id)aKey; - (NSUInteger)count; - (NSEnumerator *)keyEnumerator; @end /* EORecordDictionary */ #import @interface _EORecordDictionaryKeyEnumerator : NSEnumerator { NSDictionary *dict; EORecordDictionaryEntry *currentEntry; unsigned char count; } - (id)initWithDictionary:(EORecordDictionary *)_dict firstEntry:(EORecordDictionaryEntry *)_firstEntry count:(unsigned char)_count; - (id)nextObject; @end #endif SOPE/sope-gdl1/GDLAccess/EOAdaptorDataSource.h0000644000000000000000000000711115004363604017610 0ustar rootroot/* EOAdaptorDataSource.h Copyright (C) SKYRIX Software AG and Helge Hess Author: Helge Hess (helge.hess@opengroupware.org) Date: 1999-2004 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOAdaptorDataSource.h 1 2004-08-20 10:38:46Z znek $ #ifndef __EOAdaptorDataSource_h__ #define __EOAdaptorDataSource_h__ #import @class NSArray, NSDictionary; @class EOFetchSpecification, EOAdaptorChannel, EOQualifier; /* Fetch dictionaries from database tables. The tablename has to be set in [FetchSpecification entityName]. Qualifier, sortOrdering, distinct will be evaluated. It handles now tables with more than one primary key. Its possible to set the primary key in the fetchspecification hints (EOPrimaryKeyAttributeNamesHint -> array with strings as columnnames for the PKeys; EOPrimaryKeyAttributesHint -> array with EOAttributes for the PKeys). If no primary key is set, and now primary key could find in the table schema, all keys will be taken as primary keys. If only one primary key exsist, in insert object a new key will be generatet, else all keys has to be set. If fetch hint EOFetchResultTimeZone is set (NSTimeZone), this timezone will be set in date objectes. */ extern NSString *EOPrimaryKeyAttributeNamesHint; extern NSString *EOPrimaryKeyAttributesHint; extern NSString *EOFetchResultTimeZone; @interface EOAdaptorDataSource : EODataSource { @private EOFetchSpecification *fetchSpecification; @protected EOAdaptorChannel *adChannel; EOQualifier *__qualifier; NSArray *__attributes; BOOL commitTransaction; NSDictionary *connectionDictionary; } - (id)initWithAdaptorChannel:(EOAdaptorChannel *)_channel; - (id)initWithAdaptorChannel:(EOAdaptorChannel *)_channel connectionDictionary:(NSDictionary *)_connDict; - (id)initWithAdaptorName:(NSString *)_adName connectionDictionary:(NSDictionary *)_dict primaryKeyGenerationDictionary:(NSDictionary *)_pkGen; /* Returns an array with dictionaries, who contains key/values from the entity (use entityName/qualifier/sortOrdering). Also it contains an key named 'globalID'. If EOAdaptorDataSource is initialized with initWithAdaptorChannel the globaID is an EOKeyGlobalID else if it is initialized with initWithAdaptorName the globalID is and EOAdaptorGlobalID. */ - (NSArray *)fetchObjects; /* returns an mutable dictionary */ - (id)createObject; - (void)insertObject:(id)_obj; - (void)deleteObject:(id)_obj; - (void)updateObject:(id)_obj; - (void)setFetchSpecification:(EOFetchSpecification *)_fs; - (EOFetchSpecification *)fetchSpecification; /* for subclasses */ - (EOAdaptorChannel *)beginTransaction; - (void)commitTransaction; - (void)rollbackTransaction; - (void)openChannel; - (void)closeChannel; @end #endif /* __EOAdaptorDataSource_h__ */ SOPE/sope-gdl1/GDLAccess/English.lproj/0000755000000000000000000000000015004363604016364 5ustar rootrootSOPE/sope-gdl1/GDLAccess/English.lproj/InfoPlist.strings0000644000000000000000000000106015004363604021703 0ustar rootrootþÿ/* Localized versions of Info.plist keys */ CFBundleName = "GDLAccess"; CFBundleShortVersionString = "GDLAccess version 4.1"; CFBundleGetInfoString = "GDLAccess version 4.1, Copyright 2001, SKYRIX Software AG."; NSHumanReadableCopyright = "Copyright 2001, SKYRIX Software AG."; SOPE/sope-gdl1/GDLAccess/EOFaultHandler.h0000644000000000000000000000233615004363604016620 0ustar rootroot// $Id: EOFaultHandler.h 1 2004-08-20 10:38:46Z znek $ #ifndef __EOFaultHandler_h__ #define __EOFaultHandler_h__ #import @class NSInvocation, NSMethodSignature; @class EOFault; @interface EOFaultHandler : NSObject { @public int faultReferences; void *extraData; /* saved ivars overridden by 'faultHandler' ivar */ Class targetClass; NSZone *zone; } - (Class)targetClass; - (void *)extraData; - (void)setTargetClass:(Class)_class extraData:(void *)_extraData; /* firing */ - (BOOL)shouldPerformInvocation:(NSInvocation *)_invocation; - (void)faultWillFire:(EOFault *)_fault; - (void)completeInitializationOfObject:(id)_object; /* fault reflection */ - (Class)classForFault:(EOFault *)_fault; - (BOOL)respondsToSelector:(SEL)_selector forFault:(EOFault *)_fault; - (BOOL)conformsToProtocol:(Protocol *)_protocol forFault:(EOFault *)_fault; - (BOOL)isKindOfClass:(Class)_class forFault:(EOFault *)_fault; - (BOOL)isMemberOfClass:(Class)_class forFault:(EOFault *)_fault; - (NSMethodSignature *)methodSignatureForSelector:(SEL)_selector forFault:(EOFault *)_fault; /* description */ - (NSString *)descriptionForObject:(id)_fault; @end /* EOFaultHandler */ #endif /* __EOFaultHandler_h__ */ SOPE/sope-gdl1/GDLAccess/connect-EOAdaptor.m0000644000000000000000000000650415004363604017276 0ustar rootroot/* EOAdaptorChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: connect-EOAdaptor.m 1 2004-08-20 10:38:46Z znek $ #import #include #include #include #include int main(int argc, char **argv, char **env) { NSAutoreleasePool *pool; NSArray *args; NSString *adaptorName; NSString *condictstr; NSDictionary *condict; EOAdaptor *adaptor; EOAdaptorContext *adctx; EOAdaptorChannel *adch; BOOL ok; pool = [[NSAutoreleasePool alloc] init]; #if LIB_FOUNDATION_LIBRARY [NSProcessInfo initializeWithArguments:argv count:argc environment:env]; #endif args = [[NSProcessInfo processInfo] arguments]; if ([args count] < 3) { fprintf(stderr, "usage: %s adaptorname condict\n", argv[0]); exit(10); } adaptorName = [args objectAtIndex:1]; condictstr = [args objectAtIndex:2]; /* load adaptor */ NS_DURING { adaptor = [EOAdaptor adaptorWithName:adaptorName]; } NS_HANDLER { fprintf(stderr, "ERROR: %s: %s\n", [[localException name] cString], [[localException reason] cString]); adaptor = nil; } NS_ENDHANDLER; if (adaptor == nil) { fprintf(stderr, "ERROR: failed to load adaptor '%s'.\n", [adaptorName cString]); exit(1); } printf("did load adaptor: %s\n", [[adaptor name] cString]); /* setup connection dictionary */ if ((condict = [condictstr propertyList]) == nil) { fprintf(stderr, "ERROR: invalid connection dictionary '%s'.\n", [condictstr cString]); exit(2); } [adaptor setConnectionDictionary:condict]; /* setup connection */ if ((adctx = [adaptor createAdaptorContext]) == nil) { fprintf(stderr, "ERROR: could not create adaptor context."); exit(3); } if ((adch = [adctx createAdaptorChannel]) == nil) { fprintf(stderr, "ERROR: could not create adaptor channel."); exit(4); } /* connect */ ok = NO; NS_DURING { ok = [adch openChannel]; } NS_HANDLER { fprintf(stderr, "ERROR: could not connect to database %s: %s\n", [[localException name] cString], [[localException reason] cString]); exit(5); } NS_ENDHANDLER; if (!ok) { fprintf(stderr, "ERROR: could not connect to database.\n"); exit(6); } else printf("connection could be established.\n"); [adch closeChannel]; [pool release]; exit(0); return 0; } SOPE/sope-gdl1/GDLAccess/TODO0000644000000000000000000000051015004363604014332 0ustar rootroot# $Id: TODO 1 2004-08-20 10:38:46Z znek $ TODO ==== - remove all things not required for OGo MacOSX ====== - replace all InvalidArgumentExceptions with proper Foundation replacements - remove dependency on FoundationExt - currently the dependency is formed by the libFoundation scanner handlers and format processors SOPE/sope-gdl1/GDLAccess/EOFExceptions.h0000644000000000000000000000570315004363604016477 0ustar rootroot/* EOFExceptions.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: August 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOFExceptions_h__ #define __EOFExceptions_h__ #import @class NSString; @class EOEntity; @class EORelationship; @class EOAdaptorChannel; @interface EOFException : NSException @end @interface ObjectNotAvailableException : EOFException - initWithEntity:entity andPrimaryKey:key; @end @interface PropertyDefinitionException : EOFException @end @interface DestinationEntityDoesntMatchDefinitionException : PropertyDefinitionException - initForDestination:(EOEntity*)destinationEntity andDefinition:(NSString*)definition relationship:(EORelationship*)relationship; @end @interface InvalidNameException : PropertyDefinitionException - initWithName:(NSString*)name; @end @interface InvalidPropertyException : PropertyDefinitionException - initWithName:propertyNamed entity:currentEntity; @end @interface RelationshipMustBeToOneException : PropertyDefinitionException - initWithName:propertyNamed entity:currentEntity; @end @interface InvalidValueTypeException : PropertyDefinitionException - initWithType:type; @end @interface InvalidAttributeException : EOFException @end @interface InvalidQualifierException : EOFException @end @interface EOAdaptorException : EOFException @end @interface CannotFindAdaptorBundleException : EOAdaptorException @end @interface InvalidAdaptorBundleException : EOAdaptorException @end @interface InvalidAdaptorStateException : EOAdaptorException { id adaptor; } + exceptionWithAdaptor:(id)adaptor; @end @interface DataTypeMappingNotSupportedException : EOAdaptorException @end @interface ChannelIsNotOpenedException : InvalidAdaptorStateException @end @interface AdaptorIsFetchingException : InvalidAdaptorStateException @end @interface AdaptorIsNotFetchingException : InvalidAdaptorStateException @end @interface NoTransactionInProgressException : InvalidAdaptorStateException @end @interface TooManyOpenedChannelsException : EOAdaptorException @end #endif /* __EOFExceptions_h__ */ /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/EOPrimaryKeyDictionary.h0000644000000000000000000000274315004363604020373 0ustar rootroot/* EOPrimaryKeyDictionary.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Mircea Oancea Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOPrimaryKeyDictionary_h__ #define __EOPrimaryKeyDictionary_h__ #import @interface EOPrimaryKeyDictionary : NSDictionary { @public NSUInteger fastHash; @protected } + dictionaryWithKeys:(NSArray*)keys fromDictionary:(NSDictionary*)dict; + dictionaryWithObject:(id)object forKey:(id)key; - (unsigned)fastHash; - (BOOL)fastIsEqual:aDict; @end /* EOPrimaryKeyDictionary */ #endif /* __EOPrimaryKeyDictionary_h__ */ /* Local Variables: c-basic-offset: 4 tab-width: 8 End: */ SOPE/sope-gdl1/GDLAccess/GNUmakefile.preamble0000644000000000000000000000303715004363604017511 0ustar rootroot# compilation settings SOPE_ROOT=../.. ADDITIONAL_CPPFLAGS += -Wall ADDITIONAL_CPPFLAGS += \ -DGDL_MAJOR_VERSION=$(MAJOR_VERSION) \ -DGDL_MINOR_VERSION=$(MINOR_VERSION) \ -DGDL_SUBMINOR_VERSION=$(SUBMINOR_VERSION) ADDITIONAL_CPPFLAGS += \ -DSOPE_MAJOR_VERSION=$(SOPE_MAJOR_VERSION) \ -DSOPE_MINOR_VERSION=$(SOPE_MINOR_VERSION) \ -DSOPE_SUBMINOR_VERSION=$(SOPE_SUBMINOR_VERSION) ADDITIONAL_INCLUDE_DIRS += \ -I. -I.. \ -I./FoundationExt \ -I$(SOPE_ROOT)/sope-core/ \ -I$(SOPE_ROOT)/sope-core/NGExtensions/ ifneq ($(CGS_LIBDIR_NAME),) ADDITIONAL_CPPFLAGS += -DCGS_LIBDIR_NAME=\@\"$(CGS_LIBDIR_NAME)\" endif # dependencies libGDLAccess_LIBRARIES_DEPEND_UPON += -lEOControl $(BASE_LIBS) GDLAccess_LIBRARIES_DEPEND_UPON += -framework EOControl ifneq ($(frameworks),yes) ADDITIONAL_TOOL_LIBS += -lGDLAccess -lEOControl else ADDITIONAL_TOOL_LIBS += -framework GDLAccess -framework EOControl endif # library/framework search pathes DEP_DIRS = . $(SOPE_ROOT)/sope-core/EOControl ifneq ($(frameworks),yes) ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),\ -L$(GNUSTEP_BUILD_DIR)/$(dir)/$(GNUSTEP_OBJ_DIR_NAME)) else ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir)) endif SYSTEM_LIB_DIR += $(CONFIGURE_SYSTEM_LIB_DIR) # TODO: add prebinding address ifeq ($(FOUNDATION_LIB),apple) #libGDLAccess_PREBIND_ADDR="0x??" #libGDLAccess_LDFLAGS += -seg1addr $(libGDLAccess_PREBIND_ADDR) #GDLAccess_LDFLAGS += -seg1addr $(libGDLAccess_PREBIND_ADDR) endif SOPE/sope-gdl1/GDLAccess/load-EOAdaptor.m0000644000000000000000000000405515004363604016563 0ustar rootroot/* EOAdaptorChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: load-EOAdaptor.m 1 2004-08-20 10:38:46Z znek $ #import #include #include int main(int argc, char **argv, char **env) { NSAutoreleasePool *pool; NSArray *args; NSString *adaptorName; EOAdaptor *adaptor; pool = [[NSAutoreleasePool alloc] init]; #if LIB_FOUNDATION_LIBRARY [NSProcessInfo initializeWithArguments:argv count:argc environment:env]; #endif args = [[NSProcessInfo processInfo] arguments]; if ([args count] < 2) { fprintf(stderr, "usage: %s adaptorname\n", argv[0]); exit(10); } adaptorName = [args objectAtIndex:1]; NS_DURING { adaptor = [EOAdaptor adaptorWithName:adaptorName]; } NS_HANDLER { fprintf(stderr, "ERROR: %s: %s\n", [[localException name] cString], [[localException reason] cString]); adaptor = nil; } NS_ENDHANDLER; if (adaptor) { printf("did load adaptor: %s\n", [[adaptor name] cString]); exit(0); } [pool release]; fprintf(stderr, "ERROR: failed to load adaptor '%s'.\n", [adaptorName cString]); exit (1); return 1; } SOPE/sope-gdl1/GDLAccess/EOAdaptorOperation.h0000644000000000000000000000030215004363604017511 0ustar rootroot// $If$ #ifndef __EOAdaptorOperation_H__ #define __EOAdaptorOperation_H__ #import @interface EOAdaptorOperation : NSObject @end #endif /* __EOAdaptorOperation_H__ */ SOPE/sope-gdl1/GDLAccess/EOJoinTypes.h0000644000000000000000000000253415004363604016173 0ustar rootroot/* EOSQLExpression.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: September 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOJoinTypes_h__ #define __EOJoinTypes_h__ typedef enum { EOInnerJoin = 0, EOFullOuterJoin, EOLeftOuterJoin, EORightOuterJoin } EOJoinSemantic; typedef enum { EOJoinEqualTo = 0, EOJoinNotEqualTo, EOJoinGreaterThan, EOJoinGreaterThanOrEqualTo, EOJoinLessThan, EOJoinLessThanOrEqualTo } EOJoinOperator; @class EOJoin; #endif /* __EOJoinTypes_h__ */ SOPE/sope-gdl1/GDLAccess/EOAdaptor.h0000644000000000000000000001016215004363604015635 0ustar rootroot/* EOAdaptor.h Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOAdaptor_h__ #define __EOAdaptor_h__ #import @class NSMutableArray, NSArray, NSDictionary, NSString, NSURL; @class EOModel; @class EOAttribute; @class EOAdaptorContext; /* The EOAdaptor class could be overriden for a concrete database adaptor. You have to override only those methods marked in this header with `override'. */ /* Don't make EOAdaptor* classes garbage collectable because we want to make the instances release the database allocated resources immediately when they receive the -release message. */ @interface EOAdaptor : NSObject { @protected EOModel *model; NSString *name; NSDictionary *connectionDictionary; NSDictionary *pkeyGeneratorDictionary; NSMutableArray *contexts; // values with contexts id delegate; // not retained /* Flags used to check if the delegate responds to several messages */ BOOL delegateWillReportError:1; } /* Creating an EOAdaptor */ + (id)adaptorWithModel:(EOModel *)aModel; + (id)adaptorWithName:(NSString *)aName; + (id)adaptorForURL:(id)_url; + (NSString *)libraryDriversSubDir; - (id)initWithName:(NSString *)aName; /* Getting an adaptor's name */ - (NSString*)name; /* Get the library subdir name */ /* Setting connection information */ - (void)setConnectionDictionary:(NSDictionary*)aDictionary; - (NSDictionary*)connectionDictionary; - (BOOL)hasValidConnectionDictionary; // override /* Setting pkey generation info */ - (void)setPkeyGeneratorDictionary:(NSDictionary*)aDictionary; - (NSDictionary*)pkeyGeneratorDictionary; /* Setting the model */ - (void)setModel:(EOModel*)aModel; - (EOModel*)model; /* Creating and removing an adaptor context */ - (EOAdaptorContext*)createAdaptorContext; // override - (NSArray *)contexts; /* Checking connection status */ - (BOOL)hasOpenChannels; /* Getting adaptor-specific information */ - (Class)expressionClass; // override - (Class)adaptorContextClass; // override - (Class)adaptorChannelClass; // override - (BOOL)isValidQualifierType:(NSString*)aTypeName; // override /* Formatting SQL */ - (id)formatAttribute:(EOAttribute*)attribute; // override - (id)formatValue:value forAttribute:(EOAttribute*)attribute; // override /* Reporting errors */ - (void)reportError:(NSString*)anError; /* Setting the delegate */ - (id)delegate; - (void)setDelegate:(id)aDelegate; @end /* EOAdaptor */ @interface EOAdaptor(Private) - (void)contextDidInit:(id)aContext; - (void)contextWillDealloc:(id)aContext; @end @interface NSObject(EOAdaptorDelegate) - (BOOL)adaptor:(EOAdaptor*)anAdaptor willReportError:(NSString*)anError; @end /* NSObject(EOAdaptorDelegate) */ @interface EOAdaptor(MDlinkExtensions) - (NSString *)charConvertExpressionForAttributeNamed:(NSString *)_attrName; - (NSString *)lowerExpressionForTextAttributeNamed:(NSString *)_attrName; - (NSString *)expressionForTextValue:(id)_value; - (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)attribute; @end @interface EOAdaptor(EOF2Additions) - (BOOL)canServiceModel:(EOModel *)_model; @end #endif /* __EOAdaptor_h__*/ SOPE/sope-gdl1/GDLAccess/EOSQLExpression.m0000644000000000000000000011616415004363604017000 0ustar rootroot/* EOSQLExpression.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: September 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOSQLExpression.h" #include "common.h" #include "EOAdaptor.h" #include "EOAdaptorChannel.h" #include "EOAdaptorContext.h" #include "EOAttribute.h" #include "EOAttributeOrdering.h" #include "EOEntity.h" #include "EOFExceptions.h" #include "EOSQLQualifier.h" #include "EORelationship.h" #include #include #include #include #import "NGExtensions/NSException+misc.h" #if LIB_FOUNDATION_LIBRARY # include # include #else # include "DefaultScannerHandler.h" # include "PrintfFormatScanner.h" #endif /* A SQL command is generated for an entity when you fetch, insert, update or delete an object from the database. The command includes all the attributes from entity. The biggest problem in generation of SQL commands is the generation of SELECT statements, because the tables have to be properly aliased. If an entity has only simple attributes then you have a single table in the FROM clause. If the entity has flattened attributes, then several tables appear in the FROM list; each one with a different alias. The algorithm uses a dictionary that has as keys either entities or relationships. The values in dictionary are aliases. For a simple attribute we insert in the above dictionary the attribute's entity as key and an alias for it. For a flattened attribute with the following definition: `toEntity1.toEntity2. ... toEntityn.attribute', we have to assign to each toEntityi object an alias. Let's see how each component of the SELECT command is generated. The columns list is generated by iterating over the attributes of entity. If the attribute is simple, its entity is looked up in the aliases dictionary. If the attribute is flattened, the alias of attribute is the alias of toEntityn. If the attribute is derived, each component of it is generated applying the same rules. The FROM list is generated like this. For each key in the aliases dictionary: * if the key is an entity, its external name is written followed by the alias corresponding to entity * if the key is a relationship, the external name of its destination entity is written followed by the alias corresponding to relationship. A little bit complicated is the WHERE clause. For each flattened attribute we have to generate the logic expression that selects the attribute by expressing the joins over several entities. The algorithm starts with the first relationship. An additional variable, named context is used. Its initial value is the current entity. The expression context-alias.source-attribute join-operator relationship-alias.destination-attribute is added using the AND operator to the where clause. Then the context variable is set to the current relationship. The algorithm continues with the next relationship until there are no more relationships to process. */ static EONull *null = nil; NSString *EOBindVariableNameKey = @"name"; NSString *EOBindVariablePlaceHolderKey = @"placeHolder"; NSString *EOBindVariableAttributeKey = @"attribute"; NSString *EOBindVariableValueKey = @"value"; @interface EOInsertUpdateScannerHandler : DefaultScannerHandler { NSString *value; EOAttribute *attribute; EOAdaptor *adaptor; } - (void)setValue:(NSString*)value attribute:(EOAttribute*)attribute adaptor:(EOAdaptor*)adaptor; @end @implementation EOInsertUpdateScannerHandler - (id)init { [super init]; specHandler['V'] = [self methodForSelector:@selector(convertValue:scanner:)]; return self; } - (void)dealloc { RELEASE(self->value); RELEASE(self->attribute); RELEASE(self->adaptor); [super dealloc]; } - (void)setValue:(NSString *)_value attribute:(EOAttribute*)_attribute adaptor:(EOAdaptor*)_adaptor { ASSIGNCOPY(self->value, _value); ASSIGN(self->attribute, _attribute); ASSIGN(self->adaptor, _adaptor); } - (NSString *)convertValue:(va_list *)pString scanner:(FormatScanner *)scanner{ return (self->adaptor) ? [self->adaptor formatValue:(self->value ? self->value : (NSString *)null) forAttribute:attribute] : (id)self->value; } @end /* EOInsertUpdateScannerHandler */ @implementation EOSQLExpression + (void)initialize { if (null == nil) null = [[NSNull null] retain]; } - (id)initWithEntity:(EOEntity *)_entity { if ((self = [super init])) { ASSIGN(self->entity, _entity); } return self; } - (id)init { return [self initWithEntity:nil]; } + (id)deleteExpressionWithQualifier:(EOSQLQualifier*)qualifier channel:(EOAdaptorChannel*)channel { EOSQLExpression* sqlExpression = AUTORELEASE([[self deleteExpressionClass] new]); [sqlExpression deleteExpressionWithQualifier:qualifier channel:channel]; return sqlExpression; } + (id)insertExpressionForRow:(NSDictionary *)row entity:(EOEntity*)_entity channel:(EOAdaptorChannel*)channel { EOSQLExpression* sqlExpression = AUTORELEASE([[self insertExpressionClass] new]); [sqlExpression insertExpressionForRow:row entity:_entity channel:channel]; return sqlExpression; } - (id)deleteExpressionWithQualifier:(EOSQLQualifier *)qualifier channel:(EOAdaptorChannel*)channel { NSString *sql; self = [self initWithEntity:[qualifier entity]]; self->adaptor = RETAIN([[channel adaptorContext] adaptor]); sql = [self assembleDeleteStatementWithQualifier:qualifier tableList:[entity externalName] whereClause:[self whereClauseForQualifier:qualifier]]; self->content = [sql mutableCopy]; [self finishBuildingExpression]; return self; } - (id)insertExpressionForRow:(NSDictionary *)row entity:(EOEntity*)_entity channel:(EOAdaptorChannel*)channel { NSString *sql; self = [self initWithEntity:_entity]; self->adaptor = RETAIN([[channel adaptorContext] adaptor]); sql = [self assembleInsertStatementWithRow:row tableList:[entity externalName] columnList:[self columnListForRow:row] valueList:[self valueListForRow:row]]; self->content = [sql mutableCopy]; [self finishBuildingExpression]; return self; } + (id)selectExpressionForAttributes:(NSArray *)attributes lock:(BOOL)flag qualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder channel:(EOAdaptorChannel *)channel { EOSQLExpression* sqlExpression = AUTORELEASE([[self selectExpressionClass] new]); [sqlExpression selectExpressionForAttributes:attributes lock:flag qualifier:qualifier fetchOrder:fetchOrder channel:channel]; return sqlExpression; } - (id)selectExpressionForAttributes:(NSArray *)attributes lock:(BOOL)flag qualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder channel:(EOAdaptorChannel *)channel { NSArray *relationshipPaths; NSString *sql; self = [self initWithEntity:[qualifier entity]]; self->adaptor = [[[channel adaptorContext] adaptor] retain]; // self->content = [NSMutableString new]; // mh: BUG!!! relationshipPaths = [self relationshipPathsForAttributes:attributes qualifier:qualifier fetchOrder:fetchOrder]; sql = [self assembleSelectStatementWithAttributes:attributes lock:flag qualifier:qualifier fetchOrder:fetchOrder selectString: [qualifier usesDistinct] ? @"SELECT DISTINCT" : @"SELECT" columnList: [self selectListWithAttributes:attributes qualifier:qualifier] tableList:[self fromClause] whereClause:[self whereClauseForQualifier:qualifier] joinClause: [self joinExpressionForRelationshipPaths:relationshipPaths] orderByClause:[self orderByClauseForFetchOrder:fetchOrder] lockClause:flag ? [self lockClause] : (NSString *)nil]; self->content = [sql mutableCopy]; [self finishBuildingExpression]; return self; } + (id)updateExpressionForRow:(NSDictionary *)row qualifier:(EOSQLQualifier *)qualifier channel:(EOAdaptorChannel *)channel { EOSQLExpression* sqlExpression = AUTORELEASE([[self updateExpressionClass] new]); [sqlExpression updateExpressionForRow:row qualifier:qualifier channel:channel]; return sqlExpression; } - (id)updateExpressionForRow:(NSDictionary *)row qualifier:(EOSQLQualifier *)qualifier channel:(EOAdaptorChannel *)channel { NSString *sql; self = [self initWithEntity:[qualifier entity]]; if (self->entity == nil) { [[[InvalidQualifierException alloc] initWithFormat:@"entity for qualifier %@ is nil", [qualifier expressionValueForContext:nil]] raise]; } self->adaptor = [[[channel adaptorContext] adaptor] retain]; self->content = [[NSMutableString alloc] init]; sql = [self assembleUpdateStatementWithRow:row qualifier:qualifier tableList:[entity externalName] updateList:[self updateListForRow:row] whereClause:[self whereClauseForQualifier:qualifier]]; [self->content appendString:sql]; [self finishBuildingExpression]; return self; } - (void)dealloc { RELEASE(self->bindings); RELEASE(self->listString); RELEASE(self->whereClauseString); RELEASE(self->entity); RELEASE(self->adaptor); RELEASE(self->entitiesAndPropertiesAliases); RELEASE(self->fromListEntities); RELEASE(self->content); [super dealloc]; } - (NSString *)selectListWithAttributes:(NSArray *)attributes qualifier:(EOSQLQualifier *)qualifier { NSMutableString *selectList; NSEnumerator *enumerator; BOOL first = YES; EOAttribute *attribute; selectList = [NSMutableString stringWithCapacity:128]; enumerator = [attributes objectEnumerator]; while ((attribute = [enumerator nextObject])) { if(first) first = NO; else [selectList appendString:@", "]; [selectList appendString:[self expressionValueForAttribute:attribute]]; } return selectList; } - (NSString *)fromClause { NSMutableString *fromClause; NSEnumerator *enumerator; BOOL first = YES; id key; fromClause = [NSMutableString stringWithCapacity:64]; enumerator = [self->fromListEntities objectEnumerator]; /* Compute the FROM list from all the aliases found in entitiesAndPropertiesAliases dictionary. Note that this dictionary contains entities and relationships. The last ones are there for flattened attributes over reflexive relationships. */ while ((key = [enumerator nextObject])) { if (first) first = NO; else [fromClause appendString:@", "]; if ([key isKindOfClass:[EORelationship class]]) { /* This key corresponds to a flattened attribute. */ [fromClause appendFormat:@"%@ %@", [[key destinationEntity] externalName], [entitiesAndPropertiesAliases objectForKey:key]]; } else { /* This is an EOEntity. */ [fromClause appendFormat:@"%@ %@", [key externalName], [entitiesAndPropertiesAliases objectForKey:key]]; } } return fromClause; } - (NSString *)whereClauseForQualifier:(EOSQLQualifier *)_qualifier { return [_qualifier expressionValueForContext:self]; } - (NSString *)joinExpressionForRelationshipPaths:(NSArray *)relationshipPaths { NSMutableString *expression; NSEnumerator *enumerator; NSMutableArray *rels; NSArray *relationshipPath; EORelationship *relationship; BOOL first = YES; expression = [NSMutableString stringWithCapacity:64]; enumerator = [relationshipPaths objectEnumerator]; rels = [[NSMutableArray alloc] initWithCapacity:4]; while ((relationshipPath = [enumerator nextObject]) != nil) { NSEnumerator *componentRelationshipsEnumerator; id context; componentRelationshipsEnumerator = [relationshipPath objectEnumerator]; context = entity; while((relationship = [componentRelationshipsEnumerator nextObject])) { if (![rels containsObject:relationship]) { id sourceAttribute, destinationAttribute; [rels addObject:relationship]; /* Compute the SQL expression string corresponding to each join in the relationship. */ sourceAttribute = [self expressionValueForAttribute: [relationship sourceAttribute] context:context]; destinationAttribute = [self expressionValueForAttribute: [relationship destinationAttribute] context: [relationship destinationEntity]]; //NSLog(@"sourceAttribute %@", sourceAttribute); //NSLog(@"destinationAttribute %@", destinationAttribute); if (first) first = NO; else [expression appendString:@" AND "]; [expression appendString:[sourceAttribute description]]; [expression appendString:@" = "]; [expression appendString:[destinationAttribute description]]; } /* Compute the next context which is the current relationship. */ context = [relationship destinationEntity]; } } [rels release]; return expression; } - (NSString *)orderByClauseForFetchOrder:(NSArray *)fetchOrder { int i, count; NSMutableString *orderBy; if ((count = [fetchOrder count]) == 0) return @""; orderBy = (id)[NSMutableString stringWithCapacity:32]; for(i = 0; i < count; i++) { id eorder; eorder = [fetchOrder objectAtIndex:i]; if (i != 0) [orderBy appendString:@", "]; if ([eorder isKindOfClass:[EOSortOrdering class]]) { EOSortOrdering *order; EOAttribute *attribute; SEL ordering; NSString *fmt; order = eorder; ordering = [order selector]; attribute = [self->entity attributeNamed:[order key]]; if (sel_isEqual(ordering, EOCompareCaseInsensitiveAscending) || sel_isEqual(ordering, EOCompareCaseInsensitiveDescending)) fmt = @"LOWER(%@)"; else fmt = @"%@"; [orderBy appendFormat:fmt, [self expressionValueForAttribute:attribute]]; if (sel_isEqual(ordering, EOCompareCaseInsensitiveAscending) || sel_isEqual(ordering, EOCompareAscending)) { [orderBy appendString:@" ASC"]; } else if (sel_isEqual(ordering, EOCompareCaseInsensitiveDescending) || sel_isEqual(ordering, EOCompareDescending)) { [orderBy appendString:@" DESC"]; } } else { EOAttributeOrdering *order; EOOrdering ordering; order = eorder; ordering = [order ordering]; [orderBy appendFormat:@"%@", [self expressionValueForAttribute:[order attribute]]]; if (ordering != EOAnyOrder) [orderBy appendString: ([order ordering] == EOAscendingOrder ? @" ASC" : @" DESC")]; } } return orderBy; } - (NSString *)literalForAttribute:(EOAttribute *)_attribute withValue:(id)_value fromRow:(NSDictionary *)_row { return (self->adaptor) ? [self->adaptor formatValue:(_value ? _value : (id)null) forAttribute:_attribute] : (id)[_value stringValue]; } - (id)updateListForRow:(NSDictionary *)row { PrintfFormatScanner *formatScanner = nil; EOInsertUpdateScannerHandler *scannerHandler = nil; NSMutableString *expression = nil; NSEnumerator *enumerator; NSString *attributeName = nil; BOOL first = YES; enumerator = [row keyEnumerator]; expression = [NSMutableString stringWithCapacity:256]; formatScanner = [[PrintfFormatScanner alloc] init]; AUTORELEASE(formatScanner); scannerHandler = [[EOInsertUpdateScannerHandler alloc] init]; AUTORELEASE(scannerHandler); [formatScanner setAllowOnlySpecifier:YES]; [formatScanner setFormatScannerHandler:scannerHandler]; while((attributeName = [enumerator nextObject])) { EOAttribute *attribute; NSString *columnName = nil; id value = nil; attribute = [entity attributeNamed:attributeName]; NSAssert1(attribute, @"attribute %@ should be non nil", attributeName); columnName = adaptor ? (NSString *)[adaptor formatAttribute:attribute] : [attribute columnName]; value = [row objectForKey:attributeName]; value = [self literalForAttribute:attribute withValue:value fromRow:row]; if (first) first = NO; else [expression appendString:@", "]; [expression appendString:columnName]; [expression appendString:@" = "]; [expression appendString:value]; } return expression; } - (id)columnListForRow:(NSDictionary *)row { NSMutableString *expression; NSEnumerator *enumerator; NSString *attributeName = nil; BOOL first = YES; expression = [NSMutableString stringWithCapacity:128]; enumerator = [row keyEnumerator]; while ((attributeName = [enumerator nextObject])) { EOAttribute *attribute; NSString *columnName; attribute = [entity attributeNamed:attributeName]; NSAssert1(attribute, @"attribute %@ should be non nil", attributeName); columnName = adaptor ? (NSString *)[adaptor formatAttribute:attribute] : [attribute columnName]; if (first) first = NO; else [expression appendString:@", "]; [expression appendString:columnName]; } return expression; } - (id)valueListForRow:(NSDictionary *)row { EOInsertUpdateScannerHandler *scannerHandler; PrintfFormatScanner *formatScanner; NSEnumerator *enumerator; NSString *attributeName = nil; NSMutableString *expression = nil; BOOL first = YES; formatScanner = [[PrintfFormatScanner alloc] init]; AUTORELEASE(formatScanner); scannerHandler = [[EOInsertUpdateScannerHandler alloc] init]; AUTORELEASE(scannerHandler); expression = [NSMutableString stringWithCapacity:256]; enumerator = [row keyEnumerator]; [formatScanner setAllowOnlySpecifier:YES]; [formatScanner setFormatScannerHandler:scannerHandler]; while ((attributeName = [enumerator nextObject])) { EOAttribute *attribute; id value; attribute = [entity attributeNamed:attributeName]; value = [row objectForKey:attributeName]; NSAssert1(attribute, @"attribute %@ should be non nil", attributeName); value = [self literalForAttribute:attribute withValue:value fromRow:row]; if (first) first = NO; else [expression appendString:@", "]; [expression appendString:value]; } return expression; } - (NSArray *)relationshipPathsForAttributes:(NSArray *)attributes qualifier:(EOSQLQualifier *)qualifier fetchOrder:(NSArray *)fetchOrder { int i, count; NSMutableSet *entities; NSMutableSet *relationshipPaths; NSEnumerator *enumerator; id entityOrRelationship; entities = [NSMutableSet set]; relationshipPaths = [NSMutableSet set]; NSAssert3(self->entity, @"entity should be non nil (attrs=%@, qual=%@, order=%@)", attributes, qualifier, fetchOrder); for (i = 0, count = [attributes count]; i < count; i++) { EOAttribute *attribute; attribute = [attributes objectAtIndex:i]; if ([attribute entity] != entity) { [[[InvalidAttributeException alloc] initWithFormat:@"all attributes must be from the same " @"entity (attribute '%@' is not in '%@')", [attribute name], [entity name]] raise]; } /* attribute is normal. */ [entities addObject:[attribute entity]]; } [relationshipPaths unionSet:[qualifier relationshipPaths]]; [entities unionSet:[qualifier additionalEntities]]; for (i = 0, count = [fetchOrder count]; i < count; i++) { EOAttribute *attribute; id eorder; eorder = [fetchOrder objectAtIndex:i]; attribute = ([eorder isKindOfClass:[EOSortOrdering class]]) ? [self->entity attributeNamed:[(EOSortOrdering *)eorder key]] : [(EOAttributeOrdering *)eorder attribute]; if ([attribute entity] != entity) { [[[InvalidAttributeException alloc] initWithFormat:@"all attributes must be from the same " @"entity (attribute '%@' is not in '%@')", [attribute name], [entity name]] raise]; } } entitiesAndPropertiesAliases = [NSMutableDictionary new]; fromListEntities = [NSMutableArray new]; enumerator = [entities objectEnumerator]; i = 1; while ((entityOrRelationship = [enumerator nextObject])) { NSString* alias = [NSString stringWithFormat:@"t%d", i++]; [entitiesAndPropertiesAliases setObject:alias forKey:entityOrRelationship]; [fromListEntities addObject:entityOrRelationship]; } return [relationshipPaths allObjects]; } - (EOEntity *)entity { return self->entity; } - (id)finishBuildingExpression { return self; } - (NSString *)lockClause { return @""; } - (NSString *)expressionValueForAttribute:(EOAttribute *)attribute context:(id)context { NSString *alias = [entitiesAndPropertiesAliases objectForKey:context]; NSString *columnName = nil; columnName = adaptor ? (NSString *)[adaptor formatAttribute:attribute] : [attribute columnName]; return alias ? (NSString *)[NSString stringWithFormat:@"%@.%@", alias, columnName] : columnName; } - (NSString *)expressionValueForAttribute:(EOAttribute *)attribute { /* attribute is a normal attribute. Its alias is the alias of its entity. */ return [self expressionValueForAttribute:attribute context:[attribute entity]]; } - (NSString *)expressionValueForAttributePath:(NSArray *)definitionArray { /* Take the alias of the last relationship. */ id relationship; NSString *alias; relationship = [definitionArray objectAtIndex:([definitionArray count] - 2)]; alias = [entitiesAndPropertiesAliases objectForKey:relationship]; return AUTORELEASE(([[NSString alloc] initWithFormat:@"%@.%@", alias, [[definitionArray lastObject] columnName]])); } - (NSString *)expressionValueForContext:(id)context { return self->content; } + (Class)selectExpressionClass { return [EOSelectSQLExpression class]; } + (Class)insertExpressionClass { return [EOInsertSQLExpression class]; } + (Class)deleteExpressionClass { return [EODeleteSQLExpression class]; } + (Class)updateExpressionClass { return [EOUpdateSQLExpression class]; } - (EOAdaptor *)adaptor { return self->adaptor; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:\n", self, NSStringFromClass([self class])]; if (self->entity) [ms appendFormat:@" entity=%@\n", self->entity]; if (self->adaptor) [ms appendFormat:@" adaptor=%@\n", self->adaptor]; if (self->content) [ms appendFormat:@" content='%@\n'", self->content]; if (self->entitiesAndPropertiesAliases) [ms appendFormat:@" aliases=%@\n", self->entitiesAndPropertiesAliases]; if (self->fromListEntities) [ms appendFormat:@" from-entities=%@\n", self->fromListEntities]; if (self->whereClauseString) [ms appendFormat:@" where=%@\n", self->whereClauseString]; if (self->listString) [ms appendFormat:@" list=%@\n", self->listString]; if (self->bindings) [ms appendFormat:@" bindings=%@\n", self->bindings]; [ms appendString:@">"]; return ms; } @end /* EOSQLExpression */ @implementation EOInsertSQLExpression @end /* EOInsertSQLExpression */ @implementation EOUpdateSQLExpression @end /* EOUpdateSQLExpression */ @implementation EODeleteSQLExpression @end /* EODeleteSQLExpression */ @implementation EOSQLExpression(NewInEOF2) + (EOSQLExpression *)selectStatementForAttributes:(NSArray *)_attributes lock:(BOOL)_flag fetchSpecification:(EOFetchSpecification *)_fspec entity:(EOEntity *)_entity { if (_fspec == nil) { [NSException raise:NSInvalidArgumentException format:@"missing fetch specification argument .."]; } if ([_attributes count] == 0) { [NSException raise:NSInvalidArgumentException format:@"missing attributes for select .."]; } return [self selectExpressionForAttributes:_attributes lock:_flag qualifier:[[_fspec qualifier] sqlQualifierForEntity:_entity] fetchOrder:[_fspec sortOrderings] channel:nil]; } + (EOSQLExpression *)expressionForString:(NSString *)_sql { EOSQLExpression *se; se = [[EOSQLExpression alloc] init]; [se setStatement:_sql]; return AUTORELEASE(se); } /* accessors */ - (void)setStatement:(NSString *)_stmt { id tmp; tmp = self->content; self->content = [_stmt mutableCopy]; RELEASE(tmp); } - (NSString *)statement { return self->content; } - (NSString *)whereClauseString { return self->whereClauseString; } /* tables */ - (NSString *)tableListWithRootEntity:(EOEntity *)_entity { return ([self->fromListEntities count] > 0) ? [self fromClause] : [_entity externalName]; } /* assembly */ - (NSString *)assembleDeleteStatementWithQualifier:(EOQualifier *)_qualifier tableList:(NSString *)_tableList whereClause:(NSString *)_whereClause { NSMutableString *s; s = [NSMutableString stringWithCapacity:64]; [s appendString:@"DELETE FROM "]; [s appendString:_tableList]; [s appendString:@" WHERE "]; [s appendString:_whereClause]; return s; } - (NSString *)assembleInsertStatementWithRow:(NSDictionary *)_row tableList:(NSString *)_tables columnList:(NSString *)_columns valueList:(NSString *)_values { NSMutableString *s; s = [NSMutableString stringWithCapacity:256]; [s appendString:@"INSERT INTO "]; [s appendString:_tables]; [s appendString:@" ("]; [s appendString:_columns]; [s appendString:@") VALUES ("]; [s appendString:_values]; [s appendString:@")"]; return s; } - (NSString *)assembleSelectStatementWithAttributes:(NSArray *)_attributes lock:(BOOL)_lock qualifier:(EOQualifier *)_qualifier fetchOrder:(NSArray *)_fetchOrder selectString:(NSString *)_selectString columnList:(NSString *)_columns tableList:(NSString *)_tables whereClause:(NSString *)_whereClause joinClause:(NSString *)_joinClause orderByClause:(NSString *)_orderByClause lockClause:(NSString *)_lockClause { NSMutableString *s; unsigned wlen, jlen; #if 0 #warning DEBUG LOG, REMOVE! [self logWithFormat:@"%s: '%@': %@", __PRETTY_FUNCTION__, _whereClause,self]; #endif s = [NSMutableString stringWithCapacity:256]; [s appendString:_selectString ? _selectString : (NSString *)@"SELECT"]; [s appendString:@" "]; [s appendString:_columns]; [s appendString:@" FROM "]; [s appendString:_tables]; if ([_lockClause length] > 0) { [s appendString:@" "]; [s appendString:_lockClause]; } wlen = [_whereClause length]; jlen = [_joinClause length]; if ((wlen > 0) || (jlen > 0)) [s appendString:@" WHERE "]; if (wlen > 0) [s appendString:_whereClause]; if ((wlen > 0) && (jlen > 0)) [s appendString:@" AND "]; if (jlen > 0) [s appendString:_joinClause]; if ([_orderByClause length] > 0) { [s appendString:@" ORDER BY "]; [s appendString:_orderByClause]; } return s; } - (NSString *)assembleUpdateStatementWithRow:(NSDictionary *)_row qualifier:(EOQualifier *)_qualifier tableList:(NSString *)_tables updateList:(NSString *)_updates whereClause:(NSString *)_whereClause { NSMutableString *s; s = [NSMutableString stringWithCapacity:256]; [s appendString:@"UPDATE "]; [s appendString:_tables]; [s appendString:@" SET "]; [s appendString:_updates]; [s appendString:@" WHERE "]; [s appendString:_whereClause]; return s; } - (NSString *)assembleJoinClauseWithLeftName:(NSString *)_leftName rightName:(NSString *)_rightName joinSemantic:(EOJoinSemantic)_semantic { NSMutableString *s; s = [NSMutableString stringWithCapacity:64]; [s appendString:_leftName]; switch (_semantic) { case EOInnerJoin: [s appendString:@" = "]; break; case EOFullOuterJoin: [s appendString:@" *=* "]; break; case EOLeftOuterJoin: [s appendString:@" *= "]; break; case EORightOuterJoin: [s appendString:@" =* "]; break; } [s appendString:_rightName]; return s; } /* attributes */ - (NSString *)sqlStringForAttribute:(EOAttribute *)_attribute { NSLog(@"ERROR(%s): subclasses need to override this method!", __PRETTY_FUNCTION__); return nil; } - (NSString *)sqlStringForAttributePath:(NSString *)_attrPath { NSLog(@"ERROR(%s): subclasses need to override this method!", __PRETTY_FUNCTION__); return nil; } - (NSString *)sqlStringForAttributeNamed:(NSString *)_attrName { EOAttribute *a; if ((a = [[self entity] attributeNamed:_attrName])) return [self sqlStringForAttribute:a]; return [self sqlStringForAttributePath:_attrName]; } /* bind variables */ + (BOOL)useBindVariables { return NO; } - (BOOL)mustUseBindVariableForAttribute:(EOAttribute *)_attr { return NO; } - (BOOL)shouldUseBindVariableForAttribute:(EOAttribute *)_attr { return NO; } - (NSMutableDictionary *)bindVariableDictionaryForAttribute:(EOAttribute *)_a value:(id)_value { NSMutableDictionary *d; d = [NSMutableDictionary dictionaryWithCapacity:8]; [d setObject:_a forKey:EOBindVariableAttributeKey]; [d setObject:_value ? _value : (id)null forKey:EOBindVariableValueKey]; return d; } - (void)addBindVariableDictionary:(NSMutableDictionary *)_dictionary { if (self->bindings == nil) self->bindings = [[NSMutableArray alloc] init]; } - (NSArray *)bindVariableDictionaries { return self->bindings; } /* values */ + (NSString *)formatValue:(id)_value forAttribute:(EOAttribute *)_attribute { return _value != nil ? _value : (id)null; } - (NSString *)sqlStringForValue:(id)_value attributeNamed:(NSString *)_attrName { NSMutableDictionary *bindVars; EOAttribute *attribute; attribute = [[self entity] attributeNamed:_attrName]; if ([self mustUseBindVariableForAttribute:attribute]) bindVars = [self bindVariableDictionaryForAttribute:attribute value:_value]; else if ([[self class] useBindVariables] && [self shouldUseBindVariableForAttribute:attribute]) { bindVars = [self bindVariableDictionaryForAttribute:attribute value:_value]; } else bindVars = nil; if (bindVars) { [self addBindVariableDictionary:bindVars]; return [bindVars objectForKey:EOBindVariablePlaceHolderKey]; } return [[self class] formatValue:(_value ? _value : (id)null) forAttribute:attribute]; } + (NSString *)sqlPatternFromShellPattern:(NSString *)_pattern { unsigned len; if ((len = [_pattern length]) > 0) { unsigned cstrLen = [_pattern cStringLength]; char cstrBuf[cstrLen + 1]; const char *cstr; char buf[len * 3 + 1]; unsigned i; BOOL didSomething = NO; [_pattern getCString:cstrBuf]; cstr = cstrBuf; for (i = 0; *cstr; cstr++) { switch (*cstr) { case '*': buf[i] = '%'; i++; didSomething = YES; break; case '?': buf[i] = '_'; i++; didSomething = YES; break; case '%': buf[i] = '%'; i++; didSomething = YES; break; case '_': buf[i] = '\\'; i++; buf[i] = '_'; i++; didSomething = YES; break; default: buf[i] = *cstr; i++; break; } } buf[i] = '\0'; return (didSomething) ? (NSString *)[NSString stringWithCString:buf length:i] : (NSString *)_pattern; } return _pattern; } /* SQL formats */ + (NSString *)formatSQLString:(NSString *)_sqlString format:(NSString *)_fmt { return _sqlString; } /* qualifier operators */ - (NSString *)sqlStringForSelector:(SEL)_selector value:(id)_value { if ((_value == null) || (_value == nil)) { if (sel_isEqual(_selector, EOQualifierOperatorEqual)) return @"is"; else if (sel_isEqual(_selector, EOQualifierOperatorNotEqual)) return @"is not"; } else { if (sel_isEqual(_selector, EOQualifierOperatorEqual)) return @"="; else if (sel_isEqual(_selector, EOQualifierOperatorNotEqual)) return @"<>"; } if (sel_isEqual(_selector, EOQualifierOperatorLessThan)) return @"<"; else if (sel_isEqual(_selector, EOQualifierOperatorGreaterThan)) return @">"; else if (sel_isEqual(_selector, EOQualifierOperatorLessThanOrEqualTo)) return @"<="; else if (sel_isEqual(_selector, EOQualifierOperatorGreaterThanOrEqualTo)) return @">="; else if (sel_isEqual(_selector, EOQualifierOperatorLike)) return @"LIKE"; else { return [NSString stringWithFormat:@"UNKNOWN<%@>", NSStringFromSelector(_selector)]; } } /* qualifiers */ - (NSString *)sqlStringForKeyComparisonQualifier:(EOKeyComparisonQualifier *)_q { NSMutableString *s; NSString *sql; s = [NSMutableString stringWithCapacity:64]; sql = [self sqlStringForAttributeNamed:[_q leftKey]]; sql = [[self class] formatSQLString:sql format:nil]; [s appendString:sql]; [s appendString:@" "]; [s appendString:[self sqlStringForSelector:[_q selector] value:nil]]; [s appendString:@" "]; sql = [self sqlStringForAttributeNamed:[_q rightKey]]; sql = [[self class] formatSQLString:sql format:nil]; [s appendString:sql]; return s; } - (NSString *)sqlStringForKeyValueQualifier:(EOKeyValueQualifier *)_q { NSMutableString *s; NSString *sql; id v; v = [_q value]; s = [NSMutableString stringWithCapacity:64]; sql = [self sqlStringForAttributeNamed:[_q key]]; sql = [[self class] formatSQLString:sql format:nil]; [s appendString:sql]; [s appendString:@" "]; sql = [self sqlStringForSelector:[_q selector] value:v]; [s appendString:sql]; [s appendString:@" "]; if (([_q selector] == EOQualifierOperatorLike) || ([_q selector] == EOQualifierOperatorCaseInsensitiveLike)) v = [[self class] sqlPatternFromShellPattern:v]; sql = [self sqlStringForValue:v attributeNamed:[_q key]]; [s appendString:sql]; return s; } - (NSString *)sqlStringForNegatedQualifier:(EOQualifier *)_q { NSMutableString *s; NSString *sql; sql = [(id)_q sqlStringForSQLExpression:self]; s = [NSMutableString stringWithCapacity:[sql length] + 8]; [s appendString:@"NOT ("]; [s appendString:sql]; [s appendString:@")"]; return s; } - (NSString *)sqlStringForConjoinedQualifiers:(NSArray *)_qs { NSMutableString *s; unsigned i, count; id (*objAtIdx)(id,SEL,unsigned); objAtIdx = (void *)[_qs methodForSelector:@selector(objectAtIndex:)]; for (i = 0, count = [_qs count], s = nil; i < count; i++) { id q; q = objAtIdx(self, @selector(objectAtIndex:), i); if (s == nil) s = [NSMutableString stringWithCapacity:128]; else [s appendString:@" AND "]; [s appendString:[q sqlStringForSQLExpression:self]]; } return s; } - (NSString *)sqlStringForDisjoinedQualifiers:(NSArray *)_qs { NSMutableString *s; unsigned i, count; id (*objAtIdx)(id,SEL,unsigned); objAtIdx = (void *)[_qs methodForSelector:@selector(objectAtIndex:)]; for (i = 0, count = [_qs count], s = nil; i < count; i++) { id q; q = objAtIdx(self, @selector(objectAtIndex:), i); if (s == nil) s = [NSMutableString stringWithCapacity:128]; else [s appendString:@" OR "]; [s appendString:[q sqlStringForSQLExpression:self]]; } return s; } /* list strings */ - (NSMutableString *)listString { if (self->listString == nil) self->listString = [[NSMutableString alloc] initWithCapacity:128]; return self->listString; } - (void)appendItem:(NSString *)_itemString toListString:(NSMutableString *)_ls { if ([_ls length] > 0) [_ls appendString:@","]; [_ls appendString:_itemString]; } /* deletes */ - (void)prepareDeleteExpressionForQualifier:(EOQualifier *)_qual { NSString *tableList, *sql; self->whereClauseString = [[(id)_qual sqlStringForSQLExpression:self] copy]; tableList = [self tableListWithRootEntity:[self entity]]; sql = [self assembleDeleteStatementWithQualifier:_qual tableList:tableList whereClause:[self whereClauseString]]; [self setStatement:sql]; } /* updates */ - (void)addUpdateListAttribute:(EOAttribute *)_attr value:(NSString *)_value { NSMutableString *s; s = [[NSMutableString alloc] initWithCapacity:32]; [s appendString:[_attr columnName]]; [s appendString:@"="]; _value = [[self class] formatSQLString:_value format:nil]; [s appendString:_value]; [self appendItem:s toListString:[self listString]]; RELEASE(s); } - (void)prepareUpdateExpressionWithRow:(NSDictionary *)_row qualifier:(EOQualifier *)_qual { NSEnumerator *keys; NSString *key; NSString *tableList, *sql; keys = [_row keyEnumerator]; while ((key = [keys nextObject])) { EOAttribute *attribute; id value; attribute = [self->entity attributeNamed:key]; value = [_row objectForKey:key]; [self addUpdateListAttribute:attribute value:value]; } self->whereClauseString = [[(id)_qual sqlStringForSQLExpression:self] copy]; tableList = [self tableListWithRootEntity:[self entity]]; sql = [self assembleUpdateStatementWithRow:_row qualifier:_qual tableList:tableList updateList:[self listString] whereClause:[self whereClauseString]]; [self setStatement:sql]; } @end /* EOSQLExpression(NewInEOF2) */ SOPE/sope-gdl1/GDLAccess/EOAndQualifier+SQL.m0000644000000000000000000000402015004363604017243 0ustar rootroot/* EOAttributeOrdering.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOAndQualifier+SQL.m 1 2004-08-20 10:38:46Z znek $ #import "EOSQLQualifier.h" #include "common.h" @implementation EOAndQualifier(SQLQualifier) /* SQL qualifier generation */ - (EOSQLQualifier *)sqlQualifierForEntity:(EOEntity *)_entity { unsigned cc = [self->qualifiers count]; if (cc == 0) { return nil; } else if (cc == 1) { return [[self->qualifiers objectAtIndex:0] sqlQualifierForEntity:_entity]; } else if (cc == 2) { id left; id right; left = [[self->qualifiers objectAtIndex:0] sqlQualifierForEntity:_entity]; right = [[self->qualifiers objectAtIndex:1] sqlQualifierForEntity:_entity]; [left conjoinWithQualifier:right]; return left; } else { EOSQLQualifier *masterQ; unsigned i; for (i = 0, masterQ = nil; i < cc; i++) { EOSQLQualifier *q; q = [[self->qualifiers objectAtIndex:i] sqlQualifierForEntity:_entity]; if (masterQ == nil) masterQ = q; else [masterQ conjoinWithQualifier:q]; } return masterQ; } } @end /* EOAndQualifier */ SOPE/sope-gdl1/GDLAccess/EOSQLQualifier.m0000644000000000000000000004455215004363604016563 0ustar rootroot/* EOSQLQualifier.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Helge Hess Date: September 1996 November 1999 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #import "common.h" #import "EOSQLQualifier.h" #import "EOAdaptor.h" #import "EOAttribute.h" #import "EOEntity.h" #import "EOExpressionArray.h" #import "EOFExceptions.h" #import "EORelationship.h" #import "EOSQLExpression.h" #include #include #import "EOQualifierScanner.h" #import "NGExtensions/NSException+misc.h" #if LIB_FOUNDATION_LIBRARY # include # include #else # include "DefaultScannerHandler.h" # include "PrintfFormatScanner.h" #endif @interface EOQualifierJoinHolder : NSObject { id source; id destination; } + (id)valueForSource:(id)source destination:(id)destination; - (NSString*)expressionValueForContext:(EOSQLExpression*)context; - (id)source; - (id)destination; @end @implementation EOQualifierJoinHolder static Class AttributeClass = Nil; static EONull *null = nil; + (void)initialize { AttributeClass = [EOAttribute class]; null = [[NSNull null] retain]; } + (id)valueForSource:(id)_source destination:(id)_destination { EOQualifierJoinHolder *value; value = [[[self alloc] init] autorelease]; value->source = [_source retain]; value->destination = [_destination retain]; return value; } - (NSString *)expressionValueForContext:(EOSQLExpression *)context { NSMutableString *result = nil; EOAdaptor *adaptor = nil; NSString *formattedLeft = nil; NSString *formattedRight = nil; BOOL checkNull = NO; adaptor = [context adaptor]; if ([source isKindOfClass:AttributeClass]) { formattedLeft = [(EOAttribute *)source expressionValueForContext:context]; } else { NSAssert([destination isKindOfClass:AttributeClass], @"either one of source or destination should be EOAttribute"); if ([source isEqual:null] || (source == nil)) checkNull = YES; formattedLeft = [adaptor formatValue:(source ? source : (id)null) forAttribute:destination]; } if ([destination isKindOfClass:AttributeClass]) { NSString *tmp = formattedLeft; formattedLeft = [(EOAttribute *)destination expressionValueForContext:context]; formattedRight = tmp; } else { NSAssert([source isKindOfClass:AttributeClass], @"either one of source or destination should be EOAttribute"); if ([destination isEqual:null] || (destination == nil)) checkNull = YES; formattedRight = [adaptor formatValue:(destination ? destination :(id)null) forAttribute:source]; } result = [NSMutableString stringWithCapacity:64]; [result appendString:formattedLeft]; [result appendString:checkNull ? @" IS " : @"="]; [result appendString:formattedRight]; return result; } - (id)source { return self->source; } - (id)destination { return self->destination; } @end /* EOQualifierJoinHolder */ @implementation EOSQLQualifier + (EOSQLQualifier*)qualifierForRow:(NSDictionary*)row entity:(EOEntity*)_entity { EOSQLQualifier *qualifier = nil; NSEnumerator *enumerator = nil; NSString *attributeName = nil; EOAttribute *attribute = nil; id value = nil; BOOL first = YES; enumerator = [row keyEnumerator]; qualifier = [[[EOSQLQualifier alloc] init] autorelease]; while ((attributeName = [enumerator nextObject])) { attribute = [_entity attributeNamed:attributeName]; value = [row objectForKey:attributeName]; if ((value == nil) || (attribute == nil)) /* return nil when is unable to build a qualifier for all keys in the given row */ return nil; if (first) first = NO; else [qualifier->content addObject:@" AND "]; [qualifier->content addObject: [EOQualifierJoinHolder valueForSource:attribute destination:value]]; } qualifier->entity = RETAIN(_entity); [qualifier _computeRelationshipPaths]; return qualifier; } + (EOSQLQualifier*)qualifierForPrimaryKey:(NSDictionary*)dictionary entity:(EOEntity*)_entity { NSDictionary *pkey = nil; pkey = [_entity primaryKeyForRow:dictionary]; /* return nil when is unable to build a complete qualifier for all primary key attributes */ return pkey != nil ? [self qualifierForRow:pkey entity:_entity] : (EOSQLQualifier *)nil; } + (EOSQLQualifier*)qualifierForRow:(NSDictionary*)row relationship:(EORelationship*)relationship { NSArray *componentRelationships = nil; EOSQLQualifier *qualifier = nil; id tmpRelationship = nil; EOAttribute *sourceAttribute = nil; EOAttribute *destinationAttribute = nil; id value = nil; int j = 0; int count2 = 0; componentRelationships = [relationship componentRelationships]; tmpRelationship = relationship; qualifier = [[[EOSQLQualifier alloc] init] autorelease]; /* Make a qualifier string in the following manner. If the relationship is not flattened we must join using the join operator the values from `row' and the foreign keys taken from the destination entity of relatioship. If the relationship is flattend we must append then joins between the components of relationship. */ if (componentRelationships) { tmpRelationship = [componentRelationships objectAtIndex:0]; } sourceAttribute = [tmpRelationship sourceAttribute]; value = [row objectForKey:[sourceAttribute name]]; if (value == nil) /* Returns nil if `row' does not contain all the values needed to create a complete qualifier */ return nil; destinationAttribute = [tmpRelationship destinationAttribute]; [qualifier->content addObject: [EOQualifierJoinHolder valueForSource:destinationAttribute destination:value]]; if (componentRelationships) { EOEntity *tempEntity = [tmpRelationship destinationEntity]; /* The relationship is flattened. Iterate over the components and add joins that `link' the components between them. */ count2 = [componentRelationships count]; for (j = 1; j < count2; j++) { relationship = [componentRelationships objectAtIndex:j]; if ([relationship sourceAttribute]) { [qualifier->content addObject:@" AND "]; [qualifier->content addObject: [EOQualifierJoinHolder valueForSource: [relationship sourceAttribute] destination: [relationship destinationAttribute]]]; } } /* Here we make a hack because later we need to use this qualifier in a SELECT expression in which the qualifier's entity should be the final destination entity of the flattened relationship. In addition we need in the FROM clause all the entities corresponding to the components of the relationship to be able to insert the joins between the values given in row and the final attributes from the destination entity of the last component of relationship. */ ASSIGN(qualifier->entity, tempEntity); [qualifier _computeRelationshipPaths]; ASSIGN(qualifier->entity, [relationship destinationEntity]); return qualifier; } else { ASSIGN(qualifier->entity, [relationship destinationEntity]); return qualifier; } } + (EOSQLQualifier *)qualifierForObject:sourceObject relationship:(EORelationship *)relationship { return [self qualifierForRow: [sourceObject valueForKey:[[relationship sourceAttribute] name]] relationship:relationship]; } - (id)init { NSZone *z = [self zone]; RELEASE(self->content); self->content = nil; RELEASE(self->relationshipPaths); self->relationshipPaths = nil; RELEASE(self->additionalEntities); self->additionalEntities = nil; self->content = [[EOExpressionArray allocWithZone:z] init]; self->relationshipPaths = [[NSMutableSet allocWithZone:z] init]; self->additionalEntities = [[NSMutableSet allocWithZone:z] init]; return self; } - (id)initWithEntity:(EOEntity *)_entity qualifierFormat:(NSString *)_qualifierFormat argumentsArray:(NSArray *)_args { PrintfFormatScanner *formatScanner = nil; EOQualifierEnumScannerHandler *scannerHandler = nil; NSString *qualifierString = nil; NSMutableArray *myRelationshipPaths = nil; NSEnumerator *args = nil; myRelationshipPaths = [[NSMutableArray allocWithZone:[self zone]] init]; [self init]; ASSIGN(self->entity, _entity); if (_qualifierFormat == nil) return self; formatScanner = [[PrintfFormatScanner alloc] init]; scannerHandler = [[EOQualifierEnumScannerHandler alloc] init]; [formatScanner setAllowOnlySpecifier:YES]; args = [_args objectEnumerator]; [scannerHandler setEntity:_entity]; [formatScanner setFormatScannerHandler:scannerHandler]; /* Note: This is an ugly hack. Arguments is supposed to be a va_args structure, but an NSArray is passed in. It works because the value is casted to -parseFormatString:context: which gives control to the scannerHandler which casts the va_args back to an array (the EOQualifierEnumScannerHandler does that). Works on ix86, but *NOT* on iSeries or zServer !! */ #if defined(__s390__) || defined(__arm__) || defined(__aarch64__) || defined(__alpha__) || defined(__sh__) qualifierString = [formatScanner performSelector:@selector(stringWithFormat:arguments:) withObject:_qualifierFormat withObject:args]; #else // TODO: args is an NSArray, PrintfFormatScanner expects a va_list? // I think that this is OK because we use EOQualifierEnumScannerHandler qualifierString = [formatScanner stringWithFormat:_qualifierFormat arguments:(void *)args]; #endif [formatScanner release]; formatScanner = nil; [scannerHandler release]; scannerHandler = nil; [self->content release]; self->content = nil; self->content = [[EOExpressionArray parseExpression:qualifierString entity:entity replacePropertyReferences:YES relationshipPaths:myRelationshipPaths] retain]; [self _computeRelationshipPaths:myRelationshipPaths]; [myRelationshipPaths release]; myRelationshipPaths = nil; return self; } - (id)initWithEntity:(EOEntity*)_entity qualifierFormat:(NSString *)qualifierFormat, ... { va_list ap; id formatScanner = nil; id scannerHandler = nil; NSString *qualifierString = nil; NSMutableArray *myRelationshipPaths = nil; if ((self = [self init]) == nil) return nil; myRelationshipPaths = [[NSMutableArray alloc] init]; ASSIGN(self->entity, _entity); if (qualifierFormat == nil) { return self; } formatScanner = [[PrintfFormatScanner alloc] init]; scannerHandler = [[EOQualifierScannerHandler alloc] init]; [formatScanner setAllowOnlySpecifier:YES]; va_start(ap, qualifierFormat); [scannerHandler setEntity:_entity]; [formatScanner setFormatScannerHandler:scannerHandler]; qualifierString = [formatScanner stringWithFormat:qualifierFormat arguments:ap]; va_end(ap); [formatScanner release]; [scannerHandler release]; [self->content release]; self->content = nil; self->content = [[EOExpressionArray parseExpression:qualifierString entity:entity replacePropertyReferences:YES relationshipPaths:myRelationshipPaths] retain]; [self _computeRelationshipPaths:myRelationshipPaths]; [myRelationshipPaths release]; myRelationshipPaths = nil; return self; } - (void)_computeRelationshipPaths { [self _computeRelationshipPaths:nil]; } static void handle_attribute(EOSQLQualifier *self, id object, id _relationshipPaths) { [self->additionalEntities addObject:[object entity]]; } - (void)_computeRelationshipPaths:(NSArray *)_relationshipPaths { int i, count; [relationshipPaths removeAllObjects]; if (_relationshipPaths) { NSEnumerator *pathEnum = [_relationshipPaths objectEnumerator]; NSArray *relPath = nil; while ((relPath = [pathEnum nextObject])) { NSEnumerator *relEnum = nil; EORelationship *rel = nil; relEnum = [relPath objectEnumerator]; while ((rel = [relEnum nextObject])) { [additionalEntities addObject:[rel destinationEntity]]; } } [relationshipPaths addObjectsFromArray:_relationshipPaths]; } for (i = 0, count = [content count]; i < count; i++) { id object = [content objectAtIndex:i]; /* The objects from content can only be NSString, values or EOAttribute. */ if ([object isKindOfClass:[EOAttribute class]]) { handle_attribute (self, object, _relationshipPaths); } else if ([object isKindOfClass:[EOQualifierJoinHolder class]]) { id source = nil; id destination = nil; source = [object source]; destination = [object destination]; if ([source isKindOfClass:[EOAttribute class]]) handle_attribute (self, source, _relationshipPaths); if ([destination isKindOfClass:[EOAttribute class]]) handle_attribute (self, destination, _relationshipPaths); } else if ([object isKindOfClass:[EORelationship class]]) { [[[InvalidPropertyException alloc] initWithFormat:@"cannot refer a EORelat" @"ionship in a EOSQLQualifier: '%@'", [(EORelationship*)object name]] raise]; } } } - (void)dealloc { RELEASE(self->relationshipPaths); RELEASE(self->additionalEntities); RELEASE(self->entity); RELEASE(self->content); [super dealloc]; } - (id)copy { return [self copyWithZone:NSDefaultMallocZone()]; } - (id)copyWithZone:(NSZone*)zone { EOSQLQualifier* copy = nil; copy = [[object_getClass(self) allocWithZone:zone] init]; copy->entity = RETAIN(self->entity); copy->content = [self->content mutableCopyWithZone:zone]; copy->relationshipPaths = [self->relationshipPaths mutableCopyWithZone:zone]; copy->usesDistinct = self->usesDistinct; return copy; } - (void)negate { [self->content insertObject:@"NOT (" atIndex:0]; [self->content addObject:@")"]; } - (void)conjoinWithQualifier:(EOSQLQualifier*)qualifier { if (![qualifier isKindOfClass:[EOSQLQualifier class]]) { [NSException raise:NSInvalidArgumentException format:@"argument of conjoinWithQualifier: method must " @"be EOSQLQualifier"]; } if (self->entity != qualifier->entity) { [NSException raise:NSInvalidArgumentException format:@"qualifier argument of conjoinWithQualifier: " @"must have the same entity as receiver"]; } [self->content insertObject:@"(" atIndex:0]; [self->content addObject:@") AND ("]; [self->content addObjectsFromExpressionArray:qualifier->content]; [self->content addObject:@")"]; [self->relationshipPaths unionSet:qualifier->relationshipPaths]; } - (void)disjoinWithQualifier:(EOSQLQualifier*)qualifier { if (![qualifier isKindOfClass:[EOSQLQualifier class]]) { [NSException raise:NSInvalidArgumentException format:@"argument of disjoinWithQualifier: method must " @"be EOSQLQualifier"]; } if (self->entity != qualifier->entity) { [NSException raise:NSInvalidArgumentException format:@"qualifier argument of disjoinWithQualifier: " @"must have the same entity as receiver"]; } [self->content insertObject:@"(" atIndex:0]; [self->content addObject:@") OR ("]; [self->content addObjectsFromExpressionArray:qualifier->content]; [self->content addObject:@")"]; [self->relationshipPaths unionSet:qualifier->relationshipPaths]; } - (EOEntity*)entity { return self->entity; } - (BOOL)isEmpty { return (self->entity == nil) ? YES : NO; } - (void)setUsesDistinct:(BOOL)flag { self->usesDistinct = flag; } - (BOOL)usesDistinct { return self->usesDistinct; } - (NSMutableSet*)relationshipPaths { return self->relationshipPaths; } - (NSMutableSet*)additionalEntities { return self->additionalEntities; } - (NSString*)expressionValueForContext:(id)ctx { return [self->content expressionValueForContext:ctx]; } - (EOSQLQualifier *)sqlQualifierForEntity:(EOEntity *)_entity { NSAssert3(self->entity == _entity, @"passed invalid entity to %@ (contains %@, got %@)", self, self->entity, _entity); return (EOSQLQualifier *)self; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:\n", self, NSStringFromClass([self class])]; [ms appendFormat:@" entity=%@", [self->entity name]]; if (self->content) [ms appendFormat:@" content=%@", self->content]; if (self->usesDistinct) [ms appendString:@" distinct"]; [ms appendString:@">"]; return ms; } @end /* EOSQLQualifier */ SOPE/ChangeLog.old0000644000000000000000000005435015004363604012661 0ustar rootroot2012-09-06 Ludovic Marcotte * sope-mime/NGImap4/NGImap4Connection.m - reworked a bit the code to have more cache hits. Also added a cache of enabled extensions to avoid enabling them over and over using the same IMAP connection. 2012-08-08 Wolfgang Sourdeau * sope-appserver/NGObjWeb/WOCoreApplication.m (-shouldSetupSignalHandlers): new method that gives the possibility for the applications not to setup the signal handlers for SIGTERM/-INT/-ILL ... 2012-05-09 Ludovic Marcotte * sope-core/NGStreams/NGCTextStream.m and:1 sope-mime/NGImap4/NGImap4Client.m - we now permit setting the encoding instead of using the default one in NGCTextStream as whenever we APPEND a message over IMAP, we use NSISOLatin1StringEncoding while SOGo forces NSUTF8StringEncoding. This create size mismatches and literal errors during the APPEND operation. 2012-05-01 Wolfgang Sourdeau * sope-mime/NGMime/NSData+RFC822.m: new category module for rfc822 utility methods. 2012-04-19 Wolfgang Sourdeau * sope-gdl1/PostgreSQL/PGConnection.m (-connectWithHostName:port:options:tty:database:login:password:) (-connectWithInfo:): make sure that "standard_conforming_strings" is set to 'on' for new connections. 2012-03-23 Ludovic Marcotte * Applied patch for bug http://www.sogo.nu/bugs/view.php?id=1670 * Applied patch for bug http://www.sogo.nu/bugs/view.php?id=1671 * Applied patch for bug http://www.sogo.nu/bugs/view.php?id=1672 2012-03-22 Ludovic Marcotte * sope-appserver/NGObjWeb/UnixSignalHandler.{h,m} - entirely dropped that class as it was utterly broken. Replaced the callers with standard signal() calls. 2012-02-29 Wolfgang Sourdeau * sope-mime/NGImap4/NGImap4Client.m (-login): when "useUTF8" is set to YES, we need to specify the password length using the NSUTF8StringEncoding. 2012-02-28 Wolfgang Sourdeau * sope-mime/NGImap4/NGImap4Client.m (-login): when the password is empty, use a simple pair of dquotes as password parameter, as servers consider "{0}" as missing string instead of just an empty one. 2012-02-27 Wolfgang Sourdeau * sope-mime/NGImap4/NGImap4Client.m (-enable:): now takes an array instead of a single string and populate the new "enabledExtensions" ivar with the name of enabled extensions, ensuring first that they are not listed more than once. (-closeConnection): released and nilify the new "enabledExtensions" ivar. (-reconnect): when the enabledExtensions ivar is not empty, reenable the extensions after relogin. * sope-mime/NGImap4/NGImap4Connection.m (-enableExtensions:): now takes an array instead of a single string. (-init): removed the "enabledExtensions" ivar. 2012-02-14 Wolfgang Sourdeau * sope-gdl1/Oracle8/OracleValues.m (-[NSStringstringValueForOracleType:attribute:]): return the escaped value rather than "self", in order for the code to be actually effective. Accept additional types SQLT_VCS and SQLT_LVC. * sope-gdl1/Oracle8/OracleAdaptor.m (-typeForName:): fixed mapping for VARCHAR, added VARCHAR2 and LONG VARCHAR and a fallback to SQLT_CHR if the type in question is not supported. Enhanced type detection with hasPrefix, to enable count for fix values. 2012-02-15 Wolfgang Sourdeau * sope-gdl1/PostgreSQL/NSString+PGVal.m (-stringValueForPostgreSQLType:attribute:): properly escape and quote strings in a way that is supported by all know versions of PostgreSQL, from 8.1 (or even before) up to 9.1. * sope-gdl1/PostgreSQL/PGConnection.m (-_setupPrivateOptions): removed method, made obsolete by the above. 2012-02-14 Wolfgang Sourdeau * sope-gdl1/Oracle8/OracleValues.m (-[NSString stringValueForOracleType:attribute:]): propertly escape quote ("'") characters in strings and return the result between a new pair of quotes. 2012-02-13 Wolfgang Sourdeau * sope-mime/NGImap4/NGImap4ResponseParser.m: added parsing of untagged response to the "ENABLE" command. 2012-02-06 Wolfgang Sourdeau * sope-appserver/NGObjWeb/WebDAV/SoObjectDataSource.m (-davFlatQuery:inContext:): don't escape url components from here, as they will be re-escaped in the webdav renderer. 2012-02-06 Wolfgang Sourdeau * sope-ldap/NGLdap/NSString+DN.m (-escapedForLDAPDN): new helper method to properly escape dn members following rfc. 2012-01-31 Ludovic Marcotte * sope-mime/NGImap4/NGImap4ResponseParser.m (_parseBodyHeaderFields:) We now correctly handle responses with no size parameters. 2012-01-10 Wolfgang Sourdeau * sope-mime/NGMail/NGMailAddressParser.m: perform a check on the char pointer to ensure the buffer is never read beyond its bounds. 2011-12-30 Wolfgang Sourdeau * sope-ldap/NGLdap/NGLdapEntry.m (-initWithDN:attributes:): use the original attributes array, in order to enable further modifications thereof. * sope-ldap/NGLdap/NGLdapAttribute.m (-allStringValues): do not attempt to create an array when the resulting string is nil. (-isEqual:): overridden comparator method in order to take the attribute name and values into account. 2011-12-30 Ludovic Marcotte * sope-mime/NGImap4/NSString+Imap4.m - dropped the IMAP4 password escaping method - it was just plain braindead * sope-mime/NGImap4/NGImap4Client.m - now use IMAP4 continuation when sending over the password 2011-12-19 Wolfgang Sourdeau * sope-ldap/NGLdap/NGLdapSearchResultEnumerator.m (-nextObject): initialise rptr and ctrl to NULL in order to make sure they are initialised even when the search did not succeed. 2011-12-15 Ludovic Marcotte * sope-mime/NGImap4/NGSieveClient.{h,m} - added TLS support to the Sieve code. 2011-12-06 Wolfgang Sourdeau * sope-gdl1/PostgreSQL/PGConnection.m (-connectWithInfo:) (-connectWithHostName:port:options:tty:database:login:password:): set "standard_conforming_strings" pg options to "on" to avoid warnings on < 9.x and useless interpretation of backslashes as escaping sequences. 2011-11-29 Wolfgang Sourdeau * sope-appserver/NGObjWeb/WOMessage.m (-init): set version to "HTTP/1.1" instead of "...1.0". * sope-appserver/NGObjWeb/WOResponse.m (-init): set version to "HTTP/1.1" instead of "...1.0". * sope-appserver/NGObjWeb/WebDAV/SoWebDAVRenderer.m (-stringForValue:ofProperty:prefixes:requireTagValue:): don't append a space to singletons tags as html clients from the 90's are no longer used for anything serious nowadays. 2011-11-25 Wolfgang Sourdeau * sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m (-deliverResponse:toRequest:onStream:): capitalize header names if "WOHTTPAdaptorCapitalizeHeaders" is set. (-_reasonForStatus:): improved certain "reasons" for picky clients. 2011-11-10 Wolfgang Sourdeau * sope-gdl1/PostgreSQL/NSString+PGVal.m (stringValueForPostgreSQLType:attribute:): we don't need to escape "\" with postgres. 2011-10-31 Wolfgang Sourdeau * sope-mime/NGImap4/NGImap4Connection.m (-fetchContentOfBodyPart:atURL:withPeek:): new method that enables the use of either "BODY" or "BODY.PEEK" as body part prefixes. 2011-10-28 Wolfgang Sourdeau * sope-mime/NGMime/NGMimeMultipartBody.m (-initWithPart:): removed useless constraint on the _part parameter, since it's not even used. 2011-10-26 Wolfgang Sourdeau * sope-mime/NGMail/NGMimeMessage.m (-initWithHeader:): invoke "retain" rather than copy on the header hashmap, in order to enable further modifications in the client code. 2011-09-21 Wolfgang Sourdeau * sope-mime/NGImap4/NGImap4Connection.m: made imap4FolderNameForURL: and imap4FolderNameForURL:removeFileName: public. 2011-09-04 Ludovic Marcotte * sope-core/NGStreams/NGActiveSocket.m (-_unixWriteBytes:count:) - we tell send() to not emit any signal such as SIGPIPE. This cause havoc in OpenChange if the remote peer closes the socket for inactivity. 2011-07-29 Ludovic Marcotte * Added patch from http://www.sogo.nu/bugs/view.php?id=1390 to add GNU TLS support. 2011-07-27 Ludovic Marcotte * Dropped useless stuff in SOPE * Made sure everything would compile and work on GCC's runtime (< 4.6 and >= 4.6) and the GNUstep runtime (libobjc2-1.5). This is an initial effort as things should still be cleaned up in SOPE. 2011-07-18 Francis Lachapelle * NGUrlFormCoder.m (NGDecodeUrlFormParameters): applied a patch from bug #1369 which fixes a buffer overflow. 2011-07-06 Ludovic Marcotte * sope-mime/NGImap4/NGImap4ResponseParser.m (-_parseSearchResponseIntoHashMap:) we make sure that we've got a MSN before adding it to the array of MSNs. This can happen when servers just return "* SEARCH" with no MSN. 2011-07-05 Ludovic Marcotte * sope-mime/NGImap4/NGImap4ResponseParser.m Applied a patch from bug #1358 which fixes ACLs for names containing spaces. 2011-06-29 Ludovic Marcotte * sope-mime/NGImap4/NGSieveClient.{h,m}: Implemented correctly the PLAIN authentication to support proxying 2011-04-08 Wolfgang Sourdeau * sope-core/NGExtensions/FdExt.subproj/NSString+URLEscaping.m (-containsURLInvalidCharacters): we wander the string as an array of utf8 bytes, replacing the previous method that wrongfully casted "unichar" into "char" data, leading to false negatives for certain characters. (-stringByEscapingURL): simplified and fixed method, that wrongfully used the generic "-cStringXXX" methods. From now on, the string is converted to an NSData, and the encoding is either latin-1 or utf-8 based on doUseUTF8Encoding(). 2011-04-04 Wolfgang Sourdeau * sope-mime/NGImap4/NGImap4Connection.m (-doesMailboxExistAtURL:): if the mailbox is already counted as selected by the NGImap4Client instance, we return YES directly to avoid a costly UIDVALIDITY operation. * sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpAdaptor.m (+iniitialize): we no longer make use of "WOHttpAllowHost". (-_accept): included remote address verification code from _checkAccessOnConnection: (-_checkAccessOnConnection:): removed obsolete method. 2011-04-01 Wolfgang Sourdeau * sope-appserver/NGObjWeb/Defaults.plist: WOHttpAllowHost now set to an empty array. * sope-appserver/NGObjWeb/WOWatchDogApplicationMain.m (-_listeningAddress): don't warn about WOHttpAllowHost when its value is an empty array. 2011-03-29 Wolfgang Sourdeau * sope-core/NGStreams/configure: updated config.guess and config.sub in order to support more modern architectures. Removed useless creation of arch-dependent subdirs containing config.h. * sope-mime/NGImap4/NGImap4ResponseParser.m (_parseSingleBody): be even more tolerant with responses from dbmail. * sope-appserver/NGObjWeb/DynamicElements/DynamicElements/WOString.m (-[_WOSimpleStaticString initWithValue:escapeHTML:]): perform string manipulations on an array of unichar instead of using the "cString" methods, which return a wrong number of bytes in a non 8bit environments. * sope-appserver/NGObjWeb/WOWatchDogApplicationMain.m (-[WOWatchDogChild readMessage]): don't set the watchdog timeout if watchDogRequestTimeout is less than 1. (-[WOWatchDogChild _safetyBeltIteration:]): renamed from "_killKill" and made a multi-iteration callback. Warns the user each minute about request still hanging. Kills the child once watchDogRequestTimeout has been reached for "killTimerIteration". When occurring from a child, display a warning and invalidate the faulty timer, although this should never occur. (-[WOWatchDog _spawnChild:]): make all children release their kill timer as they will otherwise be retained and their timer will be triggered. This fixes a bug that was introduced in the last change where children would attempt to kill one another. (WOWatchDogApplicationMain): invoke "applicationWillStart" on the WOApplication class when available, in order to let it perform initialization tasks after the user defaults and the logging channels have been setup propertly. 2011-03-24 Wolfgang Sourdeau * sope-mime/NGMime/NGMimeType.m (classForType): accept "text/vcard" type. * sope-mime/NGImap4/NGImap4ResponseParser.m (_parseSingleBody): be tolerant for mail servers that don't separate the response member with a space character (like dbmail): don't use consumeIfMatch, which raises an exception if the requested char is not found. 2011-03-17 Wolfgang Sourdeau * sope-mime/NGImap4/NGImap4ResponseParser.m (_purifyQuotedString): fixed to accept spaces between quoted and unquoted chunks (bug #723). * sope-core/NGExtensions/NGQuotedPrintableCoding.m (NGDecodeQuotedPrintableX): be tolerant for certain mailers that define the final line as a folded one... * sope-mime/NGImap4/NGImap4Connection.m (-fetchContentOfBodyPart): wander through the whole list of responses since the requested body part might be returned after one or more untagged responses. * sope-appserver/NGObjWEb/WOWatchDogApplicationMain.m (-[WOWatchDogChild terminate]): no longer release the control socket from here as the child's signal handle will try to notify us that it is terminating. The control socket is released later in -handleProcessStatus. (-[WOWatchDog _cleanupSignalHandlers]): no longer release the control sockets from here as the excessive children will be released fully when releasing the children accounting arrays. (-[WOWatchDog _spawnChild]): the children accounting arrays are released and the current child is retained so that the excessive control sockets, watchdog timers and memory are all removed from memory. 2011-02-24 Wolfgang Sourdeau * sope-mime/NGMail/NGImap4Connection.m (-selectFolder:): compare folder names in their utf-7 form. 2011-02-23 Ludovic Marcotte * sope-mime/NGMail/NGSmtpClient.m Removed the Bcc stripping code as it's now done within SOGo. 2011-01-05 Ludovic Marcotte * sope-core/NGExtensions/NGQuotedPrintableCoding.m Applied a patch from Marcel Waldvogel Marcel.Waldvogel@uni-konstanz.de which fixes bug #1009. 2010-12-30 Wolfgang Sourdeau * sope-mime/NGImap4/EOQualifier+IMAPAdditions.m (-[EOKeyValueQualifier imap4OperatorForDateKeyword:andComparisonSelector:]): consider the EOQualifierOperatorGreaterThanOrEqualTo and EOQualifierOperatorLessThanOrEqualTo operators. (-[EOKeyValueQualifier appendToImap4SearchString:insertNot:]): Use a minimalist english locale for generating date description to avoid taking the active locale into account. The locale is generated from the new function below. Consider the EOQualifierOperatorCaseInsensitiveLike operator where appropriate. (initDateLocale): new function that generates a minimalist english locale with the "NSShortMonthNameArray" key/value. 2010-12-17 Ludovic Marcotte * sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m Fixed a braindead error where the data lenght was verified after the strdup() call when it was equal to 0 - generating a segfault in rare occasions. 2010-11-10 Ludovic Marcotte * sope-mime/NGImap4/NGImap4Client.m If we use Courier, we now avoid using UTF-8 SORT as it's a compile-time option not that common This can be nonetheless forced using the ImapSortEncoding. 2010-11-02 Ludovic Marcotte * sope-mime/NGMime/NGMimeHeaderFieldGeneratorSet.m We no longer use NGMimeAddressHeaderFieldGenerator for in-reply-to fields as they aren't "email addresses" but rather "message ids". 2010-11-01 Wolfgang Sourdeau * sope-json/SBJSon/: Inclusion of Stig Brautaset's SBJson library. 2010-10-08 Ludovic Marcotte * sope-mime/NGImap4/NGImap4Client.m We "assume" the server returns us UIDs sorted by date when we only ask for this. This is the case for GMail and Courier and makes initial mail loading much faster * sope-mime/NGImap4/NGImap4ResponseParser.m Fixed a _consume(self, 1); in _parseEnvelopeAddressStructures when _parseEnvelopeAddressStructure returns nil in order to consume the space. 2010-09-23 Ludovic Marcotte * sope-mime/NGImap4/NGImap4ResponseParser.m We now try harder to get a string out of an encoded string by trying the supplied encoding, trying next UTF-8 and finally giving up with ISO-8859-1. 2010-08-30 Wolfgang Sourdeau * sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m (parseTimeZone): we must use signed types for time units to avoid a sign-bit "overflow". * sope-appserver/NGObjWeb/Associations/WOKeyPathAssociation.m: enhanced to support the "long long" fundamental type. * sope-appserver/NGObjWeb/DynamicElements/_WOStaticHTMLElement.m, sope-appserver/NGObjWeb/NGHttp+WO.m, sope-appserver/NGObjWeb/SoObjects/SoObjectMethodDispatcher.m, sope-appserver/NGObjWeb/SoObjects/SoProductLoader.m, sope-appserver/NGObjWeb/Templates/WOWrapperTemplateBuilder.m, sope-appserver/NGObjWeb/WOResponse.m, sope-appserver/NGObjWeb/WOStatisticsStore.m, sope-appserver/NGObjWeb/WOWatchDogApplicationMain.m, sope-appserver/NGObjWeb/WebDAV/SoWebDAVRenderer.m, sope-appserver/WEExtensions/WEPageView.m, sope-appserver/WEExtensions/WETableMatrix.m, sope-core/EOControl/EOKeyGlobalID.m, sope-core/EOControl/EOQualifier.m, sope-core/NGExtensions/FdExt.subproj/NSRunLoop+FileObjects.m, sope-core/NGExtensions/NGBitSet.m, sope-core/NGExtensions/NGBundleManager.m, sope-core/NGExtensions/NGExtensions.m, sope-core/NGExtensions/NGHashMap.m, sope-core/NGExtensions/NGObjCRuntime.m, sope-core/NGExtensions/NGStack.m, sope-core/NGStreams/NGInternetSocketAddress.m, sope-gdl1/GDLAccess/EOExpressionArray.m, sope-gdl1/GDLAccess/EOFault.m, sope-gdl1/GDLAccess/EOFaultHandler.m, sope-gdl1/GDLAccess/EOObjectUniquer.m, sope-gdl1/GDLAccess/EOPrimaryKeyDictionary.m, sope-gdl1/GDLAccess/EORecordDictionary.m, sope-ldap/NGLdap/NGLdapConnection.m, sope-mime/NGMime/NGMimeContentDispositionHeaderFieldGenerator.m, sope-mime/NGMime/NGMimeFileData.m, sope-mime/NGMime/NGMimeJoinedData.m, sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m, sope-xml/DOM/DOMCharacterData.m, sope-xml/DOM/DOMElement.m, sope-xml/DOM/DOMSaxHandler.m, sope-xml/DOM/DOMText.m, sope-xml/SaxObjC/SaxAttributeList.m, sope-xml/SaxObjC/SaxAttributes.m, sope-xml/SaxObjC/SaxLocator.m, sope-xml/libxmlSAXDriver/TableCallbacks.m, sope-xml/libxmlSAXDriver/libxmlHTMLSAXDriver.m, sope-appserver/NGObjWeb/DynamicElements/_WOStaticHTMLElement.m, sope-appserver/NGObjWeb/NGHttp+WO.m, sope-appserver/NGObjWeb/SoObjects/SoObjectMethodDispatcher.m, sope-appserver/NGObjWeb/SoObjects/SoProductLoader.m, sope-appserver/NGObjWeb/Templates/WOWrapperTemplateBuilder.m, sope-appserver/NGObjWeb/WOResponse.m, sope-appserver/NGObjWeb/WOStatisticsStore.m, sope-appserver/NGObjWeb/WOWatchDogApplicationMain.m, sope-appserver/NGObjWeb/WebDAV/SoWebDAVRenderer.m, sope-appserver/WEExtensions/WEPageView.m, sope-appserver/WEExtensions/WETableMatrix.m, sope-core/EOControl/EOKeyGlobalID.m, sope-core/EOControl/EOQualifier.m, sope-core/NGExtensions/FdExt.subproj/NSRunLoop+FileObjects.m, sope-core/NGExtensions/NGBitSet.m, sope-core/NGExtensions/NGBundleManager.m, sope-core/NGExtensions/NGExtensions.m, sope-core/NGExtensions/NGHashMap.m, sope-core/NGExtensions/NGObjCRuntime.m, sope-core/NGExtensions/NGStack.m, sope-core/NGStreams/NGInternetSocketAddress.m, sope-gdl1/GDLAccess/EOExpressionArray.m, sope-gdl1/GDLAccess/EOFault.m, sope-gdl1/GDLAccess/EOFaultHandler.m, sope-gdl1/GDLAccess/EOObjectUniquer.m, sope-gdl1/GDLAccess/EOPrimaryKeyDictionary.m, sope-gdl1/GDLAccess/EORecordDictionary.m, sope-ldap/NGLdap/NGLdapConnection.m, sope-mime/NGMime/NGMimeContentDispositionHeaderFieldGenerator.m, sope-mime/NGMime/NGMimeFileData.m, sope-mime/NGMime/NGMimeJoinedData.m, sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m, sope-xml/DOM/DOMCharacterData.m, sope-xml/DOM/DOMElement.m, sope-xml/DOM/DOMSaxHandler.m, sope-xml/DOM/DOMText.m, sope-xml/SaxObjC/SaxAttributeList.m, sope-xml/SaxObjC/SaxAttributes.m, sope-xml/SaxObjC/SaxLocator.m, sope-xml/libxmlSAXDriver/TableCallbacks.m, sope-xml/libxmlSAXDriver/libxmlHTMLSAXDriver.m: adapted classes to use "NSInteger" and "NSUInteger" instead of "int" and "unsigned int" for compatibility with versions of GNUstep base >= 1.20. * NGExtensions/NSMethodSignature+misc.[hm]: dropped useless and cumbersome category module. 2010-08-26 Wolfgang Sourdeau * NGBundleManager.m (+load): removed method. (+defaultBundleManager): removed the hack with the objective-c class load hook since it uses memory and slows SOPE down for nothing. (_addMainBundlePathToPathArray:): we now ignore empty paths, since we actually don't want to scan the CWD for bundles. * sope-appserver/NGObjWeb/SNSConnection.m: removed obsolete class. * sope-mime/NGMime/NGMimeAddressHeaderFieldGenerator.m (-generateDataForHeaderFieldNamed:value:): fixed a bug where the buffer was treated as an unicode buffer (right) but where bytes were extracted as an UTF-8 string (wrong). The "obj" variable is now named "address" as a more explicit name. * sope-mime/NGMime/NGMimeHeaderFieldGenerator.m (NGEncodeQuotedPrintableMime): we encode ' ' as '_'. 2010-08-24 Ludovic Marcotte * sope-mime/NGImap4/NGImap4Client.m, sope-core/NGStreams/NGActiveSSLSocket.m, sope-core/NGStreams/NGSocket.m Added TLS support for IMAP4 clients. 2010-08-12 Ludovic Marcotte * Dropped the sope-tools debian package and all references to it 2010-07-29 Ludovic Marcotte * Initial import of the SOPE source based on the r1664 revision. * Added the sope-patchset and the sope-gsmake2 patches * Added the sope-debian patch * Dropped a bunch of useless stuff SOPE/sope-appserver/0000755000000000000000000000000015004363604013276 5ustar rootrootSOPE/sope-appserver/mod_ngobjweb/0000755000000000000000000000000015004363604015732 5ustar rootrootSOPE/sope-appserver/mod_ngobjweb/handler.c0000644000000000000000000006006215004363604017517 0ustar rootroot/* Copyright (C) 2000-2008 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #define BUFSIZE 2048 /* ap_http_method is deprecated in Apache 2.2.x */ #if MODULE_MAGIC_NUMBER_MAJOR >= 20051115 #define ap_http_method ap_http_scheme #endif extern int HEAVY_LOG; #if WITH_LOGGING static void _logTable(const char *text, apr_table_t *table); #endif static ngobjweb_dir_config *_getConfig(request_rec *r) { ngobjweb_dir_config *cfg; if (r == NULL) { fprintf(stderr, "%s: missing request !\n", __PRETTY_FUNCTION__); return NULL; } if (r->per_dir_config == NULL) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, r->server, "missing directory config in request ..."); return NULL; } cfg = (ngobjweb_dir_config *) ap_get_module_config(r->per_dir_config, &ngobjweb_module); return cfg; } static void _extractAppName(const char *uri, char *appName, int maxLen) { char *tmp; /* extract name of application */ if ((tmp = index(uri + 1, '/'))) { int len; len = (tmp - (uri + 1)); strncpy(appName, (uri + 1), len); appName[len] = '\0'; } else { strncpy(appName, (uri + 1), maxLen - 1); appName[maxLen - 1] = '\0'; } /* cut off .woa extension from application name */ if ((tmp = strstr(appName, ".woa"))) *tmp = '\0'; /* cut off .sky extension from application name */ if ((tmp = strstr(appName, ".sky"))) *tmp = '\0'; } static void *_readRequestBody(request_rec *r, int *requestContentLength) { const char *clen; int contentLength; void *ptr; int readBytes, toBeRead; void *requestBody; clen = apr_table_get(r->headers_in, "content-length"); contentLength = clen ? atoi(clen) : 0; *requestContentLength = contentLength; /* no content to read ... */ if (contentLength == 0) return NULL; /* read content */ if (HEAVY_LOG) { ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, r->server, "going to read %i bytes from browser ...", contentLength); } requestBody = apr_palloc(r->pool, contentLength + 2); ptr = requestBody; for (toBeRead = contentLength; toBeRead > 0;) { #ifdef AP_VERSION_1 readBytes = ap_bread(r->connection->client, ptr, toBeRead); #else ap_setup_client_block(r,REQUEST_CHUNKED_DECHUNK); readBytes = ap_get_client_block(r, ptr, toBeRead); #endif toBeRead -= readBytes; ptr += readBytes; if (readBytes == 0) break; } ptr = NULL; if (toBeRead > 0) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, r->server, "couldn't read complete HTTP req body from browser " "(read %i of %i bytes)", (contentLength - toBeRead), contentLength); return NULL; } return requestBody; } static void _copyHeadersToRequest(request_rec *r, apr_table_t *headers, int *contentLength) { const apr_array_header_t *array; apr_table_entry_t *entries; int i; const char *value; if (headers == NULL) return; value = apr_table_get(headers, "content-type"); if (value) r->content_type = value; value = apr_table_get(headers, "content-encoding"); if (value) r->content_encoding = value; value = apr_table_get(headers, "content-length"); *contentLength = value ? atoi(value) : 0; array = apr_table_elts(headers); entries = (apr_table_entry_t *)array->elts; for (i = 0; i < array->nelts; i++) { apr_table_entry_t *entry = entries + i; apr_table_add(r->headers_out, entry->key, entry->val); } // _logTable("out", r->headers_out); } static void _logInstanceAddress(request_rec *r, struct sockaddr *address, size_t addressLen, int domain) { char buf[1024]; if (!HEAVY_LOG) return; apr_snprintf(buf, sizeof(buf), " => address len=%li domain=%i<", (long int) addressLen, domain); switch (domain) { case AF_INET: strcat(buf, "inet"); break; case AF_UNIX: strcat(buf, "unix"); break; default: strcat(buf, "unknown"); break; } strcat(buf, ">"); if (domain == AF_UNIX) { strcat(buf, " path=\""); strcat(buf, ((struct sockaddr_un *)address)->sun_path); strcat(buf, "\""); } else if (domain == AF_INET) { char *ptr = NULL; int port; char sport[256]; ptr = inet_ntoa(((struct sockaddr_in *)address)->sin_addr); port = ntohs(((struct sockaddr_in *)address)->sin_port); apr_snprintf(sport, sizeof(sport), "host=\"%s\" port=%i", ptr, port); strcat(buf, sport); } ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, r->server, buf); } static int _connectInstance(request_rec *r, int appFd, struct sockaddr *address, size_t addressLen) { int result; int tryCount = 0; char isConnected = 0; result = connect(appFd, address, addressLen); if (result >= 0) return result; while (tryCount < 3) { char *pdelay = NULL; /* pblock_findval("delay", _paras) */ int delay = pdelay ? atoi(pdelay) : 3; // default: 3s ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, r->server, "sleeping %is ..", delay); #ifdef AP_VERSION_1 apr_sleep(delay); /* should be in seconds for Apache 1? */ #else apr_sleep(delay * 1000 * 1000 /* in microseconds now! */); #endif ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, r->server, "retry connect .."); result = connect(appFd, address, addressLen); if (result >= 0) { isConnected = 1; break; } tryCount++; } if (isConnected == 0) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, r->server, "connect to application instance failed, tried %i times.", tryCount); close(appFd); return -1; } return result; } static int _writeInHeaders(NGBufferedDescriptor *toApp, request_rec *r) { const apr_array_header_t *array; apr_table_entry_t *entries; int i; if (r->headers_in == NULL) return 1; array = apr_table_elts(r->headers_in); entries = (apr_table_entry_t *)array->elts; for (i = 0; i < array->nelts; i++) { apr_table_entry_t *entry = &(entries[i]); if (!NGBufferedDescriptor_writeHttpHeader(toApp, entry->key, (void*)entry->val)) { return 0; } } return 1; } int ngobjweb_handler(request_rec *r) { struct sockaddr *address = NULL; size_t addressLen; int domain; char appName[256]; NGBufferedDescriptor *toApp = NULL; int appFd; int result; int writeError = 0; int contentLength = 0; int statusCode = 500; ngobjweb_dir_config *cfg; const char *uri; unsigned requestContentLength; void *requestBody; uri = r->uri; requestContentLength = 0; requestBody = NULL; #ifndef AP_VERSION_1 if (r->handler == NULL) return DECLINED; if (strcmp(r->handler, "ngobjweb-adaptor") != 0) return DECLINED; #endif if (uri == NULL) return DECLINED; if (uri[0] != '/') return DECLINED; if (strstr(uri, "WebServerResources")) return DECLINED; /* get directory configuration */ if ((cfg = _getConfig(r))) { if (cfg->appPrefix) { if (HEAVY_LOG) { ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, r->server, "using prefix '%s'\n", cfg->appPrefix); } uri += strlen(cfg->appPrefix); } } else { return 500; } /* find app name in url */ _extractAppName(uri, appName, sizeof(appName)); /* before continuing, read request body */ requestBody = _readRequestBody(r, &contentLength); requestContentLength = contentLength; if ((requestBody == NULL) && (contentLength > 0)) /* read failed, error is logged in function */ return 500; /* ask SNS for server address */ if (cfg->snsPort) { address = _sendSNSQuery(r, r->the_request, apr_table_get(r->headers_in, "cookie"), &domain, &addressLen, appName, cfg); if (address == NULL) { /* did not find an appropriate application server */ ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, r->server, "did not find SOPE instance using SNS."); return DECLINED; } } else if (cfg->appPort) { domain = cfg->appPortDomain; if (cfg->appPortDomain == AF_UNIX) { addressLen = sizeof(struct sockaddr_un); address = apr_palloc(r->pool, sizeof(struct sockaddr_un)); memset(address, 0, sizeof(struct sockaddr_un)); ((struct sockaddr_un *)address)->sun_family = AF_UNIX; strncpy(((struct sockaddr_un *)address)->sun_path, cfg->appPort, sizeof(((struct sockaddr_un *)address)->sun_path) - 1); } else { struct sockaddr_in *snsi; char *host, *pos; int port; if ((pos = index(cfg->appPort, ':'))) { host = apr_palloc(r->pool, (pos - cfg->appPort) + 3); strncpy(host, cfg->appPort, (pos - cfg->appPort)); host[pos - cfg->appPort] = '\0'; port = atoi(pos + 1); } else { host = "127.0.0.1"; port = atoi(cfg->appPort); } #if HEAVY_LOG ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, r->server, "appPort: '%s' host: %s port %d, cfg 0x%p", cfg->appPort, host, port, cfg); #endif addressLen = sizeof(struct sockaddr_in); address = apr_palloc(r->pool, sizeof(struct sockaddr_in)); memset(address, 0, sizeof(struct sockaddr_in)); snsi = (struct sockaddr_in *)address; snsi->sin_addr.s_addr = apr_inet_addr(host); snsi->sin_family = AF_INET; snsi->sin_port = htons((short)(port & 0xFFFF)); if (snsi->sin_addr.s_addr == -1) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, r->server, "could not convert IP address: %s", host); } if (HEAVY_LOG && 0) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, r->server, "connect IP address: %s", host); } } } else { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, r->server, "neither SNS port nor app port are set for request ..."); return 500; } if (addressLen > 10000) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, r->server, "suspect instance port length (%li) ...", (long int) addressLen); return 500; } _logInstanceAddress(r, address, addressLen, domain); /* setup connection to application server */ if ((appFd = socket(domain, SOCK_STREAM, 0)) < 0) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, r->server, "could not create socket in domain %i.", domain); return DECLINED; } if ((result = _connectInstance(r, appFd, address, addressLen)) < 0) return 500; toApp = NGBufferedDescriptor_newWithOwnedDescriptorAndSize(appFd, 512); if (toApp == NULL) { close(appFd); ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, r->server, "could not alloc socket buffer for " "application server connection"); return 500; } /* write request to application server */ if (HEAVY_LOG) { ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, r->server, "transfer reqline"); } { char *reqLine; unsigned toGo; reqLine = r->the_request; toGo = reqLine ? strlen(reqLine) : 0; ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, r->server, "req is %s(len=%i)", reqLine, toGo); if (!NGBufferedDescriptor_safeWrite(toApp, reqLine, reqLine ? strlen(reqLine) : 0)) { writeError = 1; goto writeErrorHandler; } if (!NGBufferedDescriptor_safeWrite(toApp, "\r\n", 2)) { writeError = 1; goto writeErrorHandler; } } /* transfer headers */ if (writeError == 0) { if (HEAVY_LOG) { ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, r->server, "transfer hdrs"); } /* extended adaptor headers */ { char tmp[256]; const char *value; value = r->protocol; value = (value != NULL) ? value : "http"; if (!NGBufferedDescriptor_writeHttpHeader(toApp, "x-webobjects-server-protocol", (unsigned char *)value)) { writeError = 1; goto writeErrorHandler; } if ((value = r->connection->remote_ip) != NULL) { if (!NGBufferedDescriptor_writeHttpHeader(toApp, "x-webobjects-remote-addr", (unsigned char *)value)) { writeError = 1; goto writeErrorHandler; } } value = r->connection->remote_host; if (value == NULL) value = r->connection->remote_ip; if (value != NULL) { if (!NGBufferedDescriptor_writeHttpHeader(toApp, "x-webobjects-remote-host", (unsigned char *)value)) { writeError = 1; goto writeErrorHandler; } } #ifdef AP_VERSION_1 if ((value = r->connection->ap_auth_type) != NULL) { #else if ((value = r->ap_auth_type) != NULL) { #endif if (!NGBufferedDescriptor_writeHttpHeader(toApp, "x-webobjects-auth-type", (unsigned char *)value)) { writeError = 1; goto writeErrorHandler; } } #ifdef AP_VERSION_1 if ((value = r->connection->user) != NULL) { #else if ((value = r->user) != NULL) { #endif if (!NGBufferedDescriptor_writeHttpHeader(toApp, "x-webobjects-remote-user", (unsigned char *)value)) { writeError = 1; goto writeErrorHandler; } } if (cfg != NULL) { if (cfg->appPrefix != NULL) { if (!NGBufferedDescriptor_writeHttpHeader(toApp, "x-webobjects-adaptor-prefix", (unsigned char *)cfg->appPrefix)) { writeError = 1; goto writeErrorHandler; } } } if (!NGBufferedDescriptor_writeHttpHeader(toApp, "x-webobjects-server-name", (unsigned char *) r->server->server_hostname)) { writeError = 1; goto writeErrorHandler; } if (r->server->port != 0) { apr_snprintf(tmp, sizeof(tmp), "%i", r->server->port); if (!NGBufferedDescriptor_writeHttpHeader(toApp, "x-webobjects-server-port", (unsigned char *)tmp)) { writeError = 1; goto writeErrorHandler; } } // TODO: this seems to be broken with some Apache's! // see: http://www.mail-archive.com/modssl-users@modssl.org/msg16396.html if (r->server->port != 0) { apr_snprintf(tmp, sizeof(tmp), "%s://%s:%i", ap_http_method(r), r->server->server_hostname, r->server->port); } else { apr_snprintf(tmp, sizeof(tmp), "%s://%s", ap_http_method(r), r->server->server_hostname); } if (!NGBufferedDescriptor_writeHttpHeader(toApp, "x-webobjects-server-url", (unsigned char *)tmp)) { writeError = 1; goto writeErrorHandler; } /* SSL environment */ if (r->subprocess_env != NULL) { apr_table_t *env = r->subprocess_env; const char *s; s = apr_table_get(env, "HTTPS"); if (s != NULL && strncasecmp(s, "on", 2) == 0) { // SSL is one if (!NGBufferedDescriptor_writeHttpHeader(toApp, "x-webobjects-https-enabled", (unsigned char *)"1")) { writeError = 1; goto writeErrorHandler; } } s = apr_table_get(env, "SSL_CLIENT_CERT"); if (s != NULL) { const apr_array_header_t *array; apr_table_entry_t *entries; int i; if (!NGBufferedDescriptor_writeHttpHeader(toApp, "x-webobjects-clients-cert", (unsigned char *)s)) { writeError = 1; goto writeErrorHandler; } /* deliver all SSL_CLIENT_ env-vars as headers */ array = apr_table_elts(env); entries = (apr_table_entry_t *)array->elts; for (i = 0; i < array->nelts; i++) { apr_table_entry_t *entry = &(entries[i]); if (strncmp(entry->key, "SSL_CLIENT_", 11) != 0) continue; if (strncmp(entry->key, "SSL_CLIENT_CERT", 15) == 0) continue; /* already avail as x-webobjects-clients-cert" */ if (!NGBufferedDescriptor_writeHttpHeader(toApp, entry->key, (void *)entry->val)) { writeError = 1; goto writeErrorHandler; } } } /* keysize, don't know whether mapping is correct? */ if ((s = apr_table_get(env, "SSL_CIPHER_ALGKEYSIZE")) != NULL) { if (!NGBufferedDescriptor_writeHttpHeader(toApp, "x-webobjects-https-secret-keysize", (unsigned char *)s)) { writeError = 1; goto writeErrorHandler; } } if ((s = apr_table_get(env, "SSL_CIPHER_USEKEYSIZE")) != NULL) { if (!NGBufferedDescriptor_writeHttpHeader(toApp, "x-webobjects-https-keysize", (unsigned char *)s)) { writeError = 1; goto writeErrorHandler; } } } } /* http headers */ if (!_writeInHeaders(toApp, r)) { writeError = 1; goto writeErrorHandler; } if (!NGBufferedDescriptor_safeWrite(toApp, "\r\n", 2)) { writeError = 1; goto writeErrorHandler; } if (!NGBufferedDescriptor_flush(toApp)) writeError = 1; } writeErrorHandler: if (writeError == 1) { if (toApp) { NGBufferedDescriptor_free(toApp); toApp = NULL; } ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, r->server, "socket write error during transfer of HTTP header section"); return 500; } /* transfer request body */ if (requestContentLength > 0) { if (!NGBufferedDescriptor_safeWrite(toApp, requestBody, requestContentLength)) { if (toApp) { NGBufferedDescriptor_free(toApp); toApp = NULL; } ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, r->server, "couldn't transfer HTTP req body to app server (%i bytes)", contentLength); return 500; } NGBufferedDescriptor_flush(toApp); } else { if (HEAVY_LOG) { ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, r->server, "no content in request to transfer"); } } /* read response line */ if (!NGScanResponseLine(toApp, NULL, &statusCode, NULL)) { if (toApp) { NGBufferedDescriptor_free(toApp); toApp = NULL; } ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, r->server, "error during reading of response line .."); return 500; } r->status = statusCode; r->status_line = NULL; /* process response headers */ { apr_table_t *headers = NULL; if (HEAVY_LOG) ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, r->server, "scan headers"); if ((headers = NGScanHeaders(r->pool, toApp)) == NULL) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, r->server, "error during parsing of response headers .."); } _copyHeadersToRequest(r, headers, &contentLength); #ifdef AP_VERSION_1 ap_send_http_header(r); #endif } /* send response content */ if (!r->header_only) { if (contentLength > 0) { void *buffer = NULL; if ((buffer = apr_pcalloc(r->pool, contentLength + 1)) == NULL) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, r->server, "could not allocate response buffer (size=%i)", contentLength); } // read whole response NGBufferedDescriptor_safeRead(toApp, buffer, contentLength); ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, r->server, "send response (size=%i)", contentLength); // send response to client ap_rwrite(buffer, contentLength, r); ap_rflush(r); } else if (contentLength == 0) { // no content length header, read until EOF unsigned char buffer[4096]; int result = 0; int writeCount = 0; while ((result = NGBufferedDescriptor_read(toApp, buffer, sizeof(buffer)) > 0)) { ap_rwrite(buffer, result, r); ap_rflush(r); writeCount += result; } if (HEAVY_LOG && (writeCount > 0)) { ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, r->server, "write %i bytes (without content-length header)", writeCount); } } } // close connection to app if (toApp) { NGBufferedDescriptor_free(toApp); toApp = NULL; } return OK; } #if WITH_LOGGING #if 0 static void test(void) { fprintf(stderr, "%s: called:\n" " app: %s\n" " uri: %s\n" " pathinfo: %s\n" " method: %s\n" " protocol: %s\n" " 1st: %s\n" " host: %s\n" " type: %s\n" " handler: %s\n", __PRETTY_FUNCTION__, appName, r->uri, r->path_info, r->method, r->protocol, r->the_request, apr_table_get(r->headers_in, "content-length"), r->content_type, r->handler ); _logTable(" out", r->headers_out); _logTable(" err", r->err_headers_out); _logTable(" env", r->subprocess_env); _logTable(" in", r->headers_in); } #endif static void _logTable(const char *text, apr_table_t *table) { const apr_array_header_t *array; apr_table_entry_t *entries; int i; if (table == NULL) { fprintf(stderr, "%s: log NULL table.\n", text); return; } array = apr_table_elts(table); entries = (apr_table_entry_t *)array->elts; if (array->nelts == 0) { fprintf(stderr, "%s: empty\n", text); return; } for (i = 0; i < array->nelts; i++) { apr_table_entry_t *entry = &(entries[i]); fprintf(stderr, "%s: %s: %s\n", text, entry->key, entry->val); } } #endif SOPE/sope-appserver/mod_ngobjweb/CHANGES0000644000000000000000000000116215004363604016725 0ustar rootrootFri Jan 31 13:04:03 CET 2003 Helge Hess ------------------------------------------------------------- - fixed a small bug in the configuration of SNSAppPrefix => not used in SkyrixGreen ------------------------------------------------------------- Tue Dec 10 12:33:00 CET 2002 Helge Hess - created CHANGES file to document changes on a higher level ------------------------------------------------------------- Tue Jul 2 16:09:56 2002 Jan Reichmann - fixed SuSE Bug 13871 (improper handling of umlauts in HTTP header fields - required for filenames in downloads) SOPE/sope-appserver/mod_ngobjweb/config.c0000644000000000000000000001406515004363604017351 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #define LOG_CONFIG 0 static char *_makeString(char *buf, char *str, int max) { if (buf == NULL) buf = calloc(max + 10, sizeof(char)); strncpy(buf, str, max); buf[max] = '\0'; return buf; } static char *_makePort(char *port, char *str) { return _makeString(port, str, MAX_PORTNAME_SIZE); } static int _domainFromPort(char *port) { if (port == NULL) return AF_INET; return *port == '/' ? AF_UNIX : AF_INET; } const char *ngobjweb_set_sns_port(cmd_parms *cmd, ngobjweb_dir_config *cfg, char *arg) { cfg->snsPort = _makePort(cfg->snsPort, arg); cfg->snsPortDomain = _domainFromPort(cfg->snsPort); #if LOG_CONFIG fprintf(stderr, "%s: 0x%08X set snsport to %s, domain %i (http=%s)\n", __PRETTY_FUNCTION__, (unsigned)cfg, cfg->snsPort, cfg->snsPortDomain, cfg->useHTTP ? "yes" : "no"); #endif return NULL; } const char *ngobjweb_set_app_port(cmd_parms *cmd, ngobjweb_dir_config *cfg, char *arg) { cfg->appPort = _makePort(cfg->appPort, arg); cfg->appPortDomain = _domainFromPort(cfg->appPort); #if LOG_CONFIG fprintf(stderr, "%s: 0x%08X set appPort to %s, domain %i (http=%s)\n", __PRETTY_FUNCTION__, (unsigned)cfg, cfg->appPort, cfg->snsPortDomain, cfg->useHTTP ? "yes" : "no"); #endif return NULL; } const char *ngobjweb_set_app_prefix(cmd_parms *cmd, ngobjweb_dir_config *cfg, char *arg) { cfg->appPrefix = _makeString(cfg->appPrefix, arg, MAX_APP_PREFIX_SIZE); return NULL; } const char *ngobjweb_set_use_http(cmd_parms *cmd, ngobjweb_dir_config *cfg) { #if LOG_CONFIG fprintf(stderr, "%s: using HTTP.\n", __PRETTY_FUNCTION__); #endif cfg->useHTTP = 1; return NULL; } void *ngobjweb_create_dir_config(apr_pool_t *p, char *dummy) { ngobjweb_dir_config *new; new = apr_palloc(p, sizeof(ngobjweb_dir_config)); new->snsPort = NULL; new->snsPortDomain = AF_UNIX; new->appPort = NULL; new->appPortDomain = AF_INET; new->appPrefix = NULL; new->useHTTP = 0; #if LOG_CONFIG fprintf(stderr,"%s: created directory config 0x%08X ...\n", __PRETTY_FUNCTION__, (unsigned)new); #endif return new; } void *ngobjweb_merge_dir_configs(apr_pool_t *p, void *basev, void *addv) { ngobjweb_dir_config *base; ngobjweb_dir_config *add; ngobjweb_dir_config *new; base = (ngobjweb_dir_config *)basev; add = (ngobjweb_dir_config *)addv; if (add == NULL) add = base; if ((new = apr_palloc(p, sizeof(ngobjweb_dir_config))) == NULL) { fprintf(stderr, "%s: couldn't allocate memory of size %ld\n", __PRETTY_FUNCTION__, (long int) sizeof(ngobjweb_dir_config)); return NULL; } new->snsPort = NULL; new->snsPortDomain = 0; new->appPort = NULL; new->appPortDomain = 0; new->appPrefix = NULL; new->useHTTP = 0; if ((add == NULL) && (base == NULL)) goto finish; /* copy base stuff */ if (add) { if (add->useHTTP) new->useHTTP = 1; if (add->snsPortDomain) new->snsPortDomain = add->snsPortDomain; else new->snsPortDomain = base ? base->snsPortDomain : 0; if (add->appPortDomain) new->appPortDomain = add->appPortDomain; else new->appPortDomain = base ? base->appPortDomain : 0; } if (base) { if (base->useHTTP) new->useHTTP = 1; } /* copy SNS port */ if ((add != NULL) && (add->snsPort != NULL)) { if ((new->snsPort = _makePort(NULL, add->snsPort))) new->snsPortDomain = _domainFromPort(new->snsPort); } else if ((base != NULL) && (base->snsPort != NULL)) { if ((new->snsPort = _makePort(NULL, base->snsPort))) new->snsPortDomain = _domainFromPort(new->snsPort); } /* copy app port */ if ((add != NULL) && (add->appPort != NULL)) { if ((new->appPort = _makePort(NULL, add->appPort))) new->appPortDomain = _domainFromPort(new->appPort); } else if ((base != NULL) && (base->appPort != NULL)) { if ((new->appPort = _makePort(NULL, base->appPort))) new->appPortDomain = _domainFromPort(new->appPort); } /* copy app prefix */ if (add->appPrefix) { new->appPrefix = _makeString(NULL, add->appPrefix, MAX_APP_PREFIX_SIZE); } else if (base->appPrefix) { new->appPrefix = _makeString(NULL, base->appPrefix, MAX_APP_PREFIX_SIZE); } finish: #if LOG_CONFIG fprintf(stderr, "MERGE: (base=0x%08X, add=0x%08X, new=0x%08X\n" " BASE: sns:'%s'%i app:'%s'%i prefix:'%s' http:%s\n" " ADD: sns:'%s'%i app:'%s'%i prefix:'%s' http:%s\n" " NEW: sns:'%s'%i app:'%s'%i prefix:'%s' http:%s\n", (unsigned)base, (unsigned)add, (unsigned)new, base->snsPort, base->snsPortDomain, base->appPort, base->appPortDomain, base->appPrefix, base->useHTTP ? "on" : "off", add->snsPort, add->snsPortDomain, add->appPort, add->appPortDomain, add->appPrefix, add->useHTTP ? "on" : "off", new->snsPort, new->snsPortDomain, new->appPort, new->appPortDomain, new->appPrefix, new->useHTTP ? "on" : "off" ); #endif return new; } SOPE/sope-appserver/mod_ngobjweb/500mod_ngobjweb.info0000644000000000000000000000022415004363604021466 0ustar rootrootLoadModule ngobjweb_module /usr/lib/apache/1.3/mod_ngobjweb.so Description: Enables apache to handle HTTP requests for the SOPE application server SOPE/sope-appserver/mod_ngobjweb/ngobjweb_module.c0000644000000000000000000000605515004363604021246 0ustar rootroot/* Copyright (C) 2000-2008 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" static command_rec ngobjweb_cmds[] = { { "SetSNSPort", ngobjweb_set_sns_port, NULL, OR_FILEINFO, TAKE1, "the path of the Unix domain address to use (eg /tmp/.snsd)" }, { "SetAppPort", ngobjweb_set_app_port, NULL, OR_FILEINFO, TAKE1, "the path of the Unix domain address to use (eg /tmp/.snsd)" }, { "SetAppPrefix", ngobjweb_set_app_prefix, NULL, OR_FILEINFO, TAKE1, "any prefix that is before the app name (eg /MyDir with /MyDir/MyApp.woa)" }, { "SNSUseHTTP", ngobjweb_set_use_http, NULL, OR_FILEINFO, 0, "use HTTP protocol to query snsd (on,off) ?" }, { NULL } }; #ifdef AP_VERSION_1 static handler_rec ngobjweb_handlers[] = { { "ngobjweb-adaptor", ngobjweb_handler }, { NULL } }; static void ngobjweb_init(server_rec *_server, pool *_pool) { } module ngobjweb_module = { STANDARD_MODULE_STUFF, ngobjweb_init, /* initializer */ ngobjweb_create_dir_config, /* dir config creater */ ngobjweb_merge_dir_configs, /* dir merger --- default is to override */ NULL, /* server config */ NULL, /* merge server config */ ngobjweb_cmds, /* command table */ ngobjweb_handlers, /* handlers */ NULL, /* filename translation */ NULL, /* check_user_id */ NULL, /* check auth */ NULL, /* check access */ NULL, /* type_checker */ NULL, /* fixups */ NULL, /* logger */ NULL /* header parser */ }; #else static void ngobjweb_register_hooks(apr_pool_t *p) { ap_hook_handler(ngobjweb_handler, NULL, NULL, APR_HOOK_LAST); } module AP_MODULE_DECLARE_DATA ngobjweb_module = { STANDARD20_MODULE_STUFF, ngobjweb_create_dir_config, /* create per-directory config structures */ ngobjweb_merge_dir_configs, /* merge per-directory config structures */ NULL, /* create per-server config structures */ NULL, /* merge per-server config structures */ ngobjweb_cmds, /* command handlers */ ngobjweb_register_hooks /* register hooks */ }; #endif SOPE/sope-appserver/mod_ngobjweb/GNUmakefile0000644000000000000000000000474315004363604020014 0ustar rootroot# custom makefile -include ../../config.make -include $(GNUSTEP_MAKEFILES)/common.make # config APACHE = /usr APXS = $(APACHE)/sbin/apxs APR = # lowercase are commandline args (eg make apxs=/usr/bin/apxs) ifneq ($(apxs),no) ifneq ($(apxs),yes) ifneq ($(apxs),) APXS=$(apxs) else APXS=$(shell which apxs 2>/dev/null) endif else APXS=$(shell which apxs 2>/dev/null) endif else APXS= endif # lowercase are commandline args (eg make apr=/usr/bin/apr) ifneq ($(apr),no) ifneq ($(apr),yes) ifneq ($(apr),) APR=$(apr) else APR=$(shell which apr-config 2>/dev/null) endif else APR=$(shell which apr-config 2>/dev/null) endif else APR= endif ifeq ($(APXS),) APXS=$(shell which apxs2 2>/dev/null) ifeq ($(APXS),) APXS = $(APACHE)/sbin/apxs2 endif endif ifneq ($(APXS),) ifneq ($(shared),no) APXS_CFLAGS = $(shell $(APXS) -q CFLAGS_SHLIB) $(shell $(APXS) -q CFLAGS) APXS_INCLUDE_DIRS = -I$(shell $(APXS) -q INCLUDEDIR) APXS_LIBS = $(shell$ (APXS) -q LIBS_SHLIB) APXS_LDFLAGS = $(shell $(APXS) -q LDFLAGS_SHLIB) else ifneq ($(APXS),) APXS_CFLAGS = $(shell $(APXS) -q CFLAGS) APXS_INCLUDE_DIRS = -I$(shell $(APXS) -q INCLUDEDIR) else APXS_CFLAGS = APXS_INCLUDE_DIRS = endif endif else # no apxs available APXS_CFLAGS="-DSHARED_MODULE -O2 -DEAPI_MM -fPIC -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DHARD_SERVER_LIMIT=2048 -DDYNAMIC_MODULE_LIMIT=128 -DLINUX=22 -DMOD_SSL=208103 -DEAPI -DUSE_EXPAT" endif ifneq ($(APR),) APR_INCLUDE_DIRS = -I$(shell $(APR) --includedir) APR_CFLAGS = $(shell $(APR) --cppflags) APR_LDFLAGS = $(shell $(APR) --ldflags) APR_LIBS = $(shell $(APR) --libs) endif GNUSTEP_INSTALLATION_DIR = $(GNUSTEP_SYSTEM_ROOT)/Library/WOAdaptors/Apache CC = gcc LD = gcc SHARED_LIBEXT = .so CFLAGS = -Wall -I. -fPIC \ $(APXS_CFLAGS) $(APR_CFLAGS) \ $(APXS_INCLUDE_DIRS) $(APR_INCLUDE_DIRS) -O0 -ggdb LDFLAGS = $(APXS_LDFLAGS) $(APR_LDFLAGS) -shared -fPIC LDLIBS = $(APXS_LIBS) $(APR_LIBS) # adaptor OFILES = \ globals.o \ handler.o \ NGBufferedDescriptor.o \ scanhttp.o \ sns.o \ config.o \ ngobjweb_module.o \ module = ngobjweb product = mod_$(module)$(SHARED_LIBEXT) all :: $(product) clean :: rm -f *.o $(product) *.so *~ distclean :: clean apache-dir : $(MKDIRS) $(GNUSTEP_INSTALLATION_DIR) install :: $(APXS) -i -n $(module) $(product) install-usr-libexec :: all $(INSTALL_PROGRAM) $(product) /usr/libexec/httpd/ $(product) : $(OFILES) $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ $(OFILES) $(LDLIBS) SOPE/sope-appserver/mod_ngobjweb/ChangeLog0000644000000000000000000001251715004363604017512 0ustar rootroot2010-11-23 Wolfgang Sourdeau * scanhttp.c (NGScanHeaders): make use of apr_table_add, rather than .._set to make sure "set-cookie" headers are put each in their individual slot, as many browsers break the HTTP spec and ignore such headers in merged form. * handler.c (_copyHeadersToRequest): same as above. 2008-03-29 Wolfgang Sourdeau * config.c, NGBufferedDescriptor.c: include common.h, minor code cleanups 2008-03-29 Wolfgang Sourdeau * handler.c: fixed more potential socket leaks 2008-03-26 Helge Hess * handler.c: fixed a double free() crasher, as reported by Stephane * NGBufferedDescriptor.c (NGBufferedDescriptor_read): fixed a potential crasher, discovered by Stephane 2007-07-19 Wolfgang Sourdeau * GNUmakefile: include APR CFLAGS and LDFLAGS in compilation (fixes OGo bug #1886) 2007-07-06 Marcus Mueller * handler.c: fixed compilation for Apache 2.2.x. No heavy testing has gone into using mod_ngobjweb with Apache 2.2 currently, but first tests indicate that it just works. 2007-01-15 Helge Hess * added ngobjweb.load configuration file for Apache2 setups which support a2enmod (eg Ubuntu) 2006-08-21 Helge Hess * handler.c: added ability to forward app requests to other hosts (using IP:port syntax) 2005-10-04 Helge Hess * GNUmakefile: add APR include dirs if apr-config can be found (this is for Apache2 only) (OGo bug #900) 2005-08-01 Helge Hess * scanhttp.c, sns.c: fixed gcc 4.0 warnings 2005-07-31 Helge Hess * NGBufferedDescriptor.[hc]: fixed some gcc 4.0 warnings * added an Xcode 2.1 project for building the adaptor * GNUmakefile: added a distclean and an install-usr-libexec target * NGBufferedDescriptor.c: fixed some gcc 4.0 warnings 2005-04-15 Helge Hess * handler.c: deliver Apache SSL environment as HTTP headers, either using x-webobjects- headers or using SSL_CLIENT_xxx headers (when no proper x-webobjects- header is known) * NGBufferedDescriptor.c: escape headers containing '\r' or '\n' (using %10, %13), required for transporting the certificate header ... * GNUmakefile: autolocate apxs2 (tested on SuSE 9.1) * handler.c: minor code cleanups 2005-02-24 Helge Hess * handler.c: only write the x-webobjects-port if the Apache variable is not 0 (need to find out how this can happen ...) 2004-11-17 Helge Hess * handler.c (_connectInstance): fixed apr_sleep for Apache 2 which now requires microseconds (thanks Christophe Bernard for pointing that out!) 2004-09-20 Helge Hess * scanhttp.c (NGScanResponseLine): changed char types to unsigned char * GNUmakefile: remove version and EAPI marker from generated module, the result is now called mod_ngobjweb.so 2004-09-08 Helge Hess * handler.c: fixed some log text 2004-04-02 Marcus Mueller * README: Minor additions/changes for Apache 1.3.x 2003-12-22 Frank Reppin * handler.c: ap_setup_client_block before ap_get_client_block which fixes the issue reported in Bug #354. Tested with 2.0.40/2.0.47/2.0.48 * thanks to Frank Wuebbeling for pointing! 2003-08-08 Helge Hess * handler.c: if r->handler is NULL on Apache2, decline request - might have been the cause for some crashes with Apache2 2003-08-01 Bjoern Stierand * globals.c, common.h: added some missing headers to remove compilation warnings on FreeBSD RELENG_4 (thanks to Frank Reppin ) 2003-07-15 Thomas Woerner * port to apache 2.x * thanks to Ricardo Cerqueira for testing 2003-02-05 Helge Hess * globals.c: disable HEAVY_LOG per default 2003-01-31 Helge Hess * config.c: fixed a bug in the configuration of SNSAppPrefix 2002-12-10 Helge Hess * added CHANGES Tue Jul 2 16:09:56 2002 Jan Reichmann * NGBufferedDescriptor.c: char -> unsigned char (fixes SuSE Bug 13871),umlauts in HTTP were not correctly handled by the ngobjweb proxy module Sat Mar 23 17:18:58 2002 Helge Hess * removed "global" sns config (you need to specify the sns explicitly using SetSNSPort * handler.c: major cleanups 2001-11-12 Helge Hess * sns.c (_sendSNSQuery): added fail-codes Tue Oct 9 15:42:07 2001 Helge Hess * sns.c: removed support for SNS over HTTP Wed Feb 28 16:03:14 2001 Helge Hess * sns.c (_sendSNSQuery): fixed bugs in HTTP support Fri Dec 1 16:08:00 2000 Helge Hess * added apxs support Tue Aug 3 16:35:38 1999 Helge Hess * sns.c (_sendSNSQuery): fixed bug, returned Unix-domain addresses were not null terminated (the SUN_LEN of an address is excluding the zero byte which is therefore not transferred by snsd) SOPE/sope-appserver/mod_ngobjweb/common.h0000644000000000000000000000765615004363604017411 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGObjWeb_Adaptors_apache_H__ #define __NGObjWeb_Adaptors_apache_H__ /* System includes */ #include #include #include #include #include #include #include /* Apache includes */ #include #include #include #include #include #if MODULE_MAGIC_NUMBER_MAJOR >= 20010224 /* apache ap version 2 */ #include "apr.h" #include "apr_buckets.h" #include "apr_strings.h" #include "apr_portable.h" #include "apr_optional.h" #include "apr_lib.h" #include "ap_config.h" #include "ap_listen.h" #else /* for compatibility */ #define AP_VERSION_1 #define apr_array_header_t array_header #define apr_inet_addr inet_addr #define apr_isalnum isalnum #define apr_isspace isspace #define apr_palloc ap_palloc #define apr_pcalloc ap_pcalloc #define apr_pool_t pool #define apr_table_elts ap_table_elts #define apr_table_entry_t table_entry #define apr_table_get ap_table_get #define apr_table_make ap_make_table #define apr_table_set ap_table_set #define apr_table_t table #define apr_sleep sleep #define apr_snprintf snprintf #define ap_log_error(file, line, level, status, vars...) \ ap_log_error(file, line, level, ## vars) #endif #include "NGBufferedDescriptor.h" module ngobjweb_module; typedef struct { char *snsPort; /* the port of the SNS daemon */ int snsPortDomain; char *appPort; /* a single pass-through port of an instance */ int appPortDomain; char *appPrefix; int useHTTP; } ngobjweb_dir_config; #define MAX_PORTNAME_SIZE 140 #define MAX_SNS_PATH_SIZE MAX_PORTNAME_SIZE #define MAX_APP_PREFIX_SIZE 256 /* SNS */ extern void * _sendSNSQuery(request_rec *_rq, const char *_line, const char *_cookie, int *_domain, size_t *_len, const char *_appName, ngobjweb_dir_config *_cfg); /* HTTP */ extern unsigned char NGScanResponseLine(NGBufferedDescriptor *_in, unsigned char *_version, int *_status, unsigned char *_text); extern apr_table_t *NGScanHeaders(apr_pool_t *_pool, NGBufferedDescriptor *_in); /* handlers */ extern int ngobjweb_handler(request_rec *r); /* commands */ extern const char *ngobjweb_set_sns_port(cmd_parms *cmd, ngobjweb_dir_config *cfg, char *arg); extern const char *ngobjweb_set_app_port(cmd_parms *cmd, ngobjweb_dir_config *cfg, char *arg); extern const char *ngobjweb_set_app_prefix(cmd_parms *cmd, ngobjweb_dir_config *cfg, char *arg); extern const char *ngobjweb_set_use_http(cmd_parms *cmd, ngobjweb_dir_config *cfg); /* configuration */ extern void *ngobjweb_create_dir_config(apr_pool_t *p, char *dummy); extern void *ngobjweb_merge_dir_configs(apr_pool_t *p, void *basev, void *addv); #endif /* __NGObjWeb_Adaptors_apache_H__ */ SOPE/sope-appserver/mod_ngobjweb/skyrix.conf0000644000000000000000000000257415004363604020142 0ustar rootroot# # SKYRIX configurations # Alias /SNSMonitor.woa/WebServerResources/ /HOME/helge/mdev/MOF2/Web/sns/SNSMonitor.woa/WebServerResources/ Alias /Skyrix.woa/WebServerResources/ /HOME/helge/mdev/LSOffice/LSWebInterface/Skyrix.woa/WebServerResources/ Alias /MyApp2.woa/WebServerResources/ /HOME/helge/mdev/MOF2/Web/Examples/MyApp2/MyApp2.woa/ Alias /ClassBrowser.woa/WebServerResources/ /HOME/helge/mdev/MOF2/Web/Examples/ClassBrowser/ClassBrowser.woa/ Alias /LSCatalog.woa/WebServerResources/ /HOME/helge/mdev/LSCatalog/LSCatalog.woa/ Alias /ArticleImages /tmp/skyrix-news LoadModule ngobjweb_module /HOME/helge/mdev/MOF2/Web/Adaptors/apache/ngobjweb_1.3.4.so SetSNSPort /tmp/.helge.snsd SetHandler ngobjweb-adaptor SetSNSPort /tmp/.helge.snsd SetAppPrefix /OtherRoot SetHandler ngobjweb-adaptor SetSNSPort /tmp/.helge.snsd2 SetAppPrefix /OtherRoot2 SetHandler ngobjweb-adaptor SetSNSPort /tmp/.helge.snsd SetHandler ngobjweb-adaptor SetHandler ngobjweb-adaptor SetHandler ngobjweb-adaptor SetHandler ngobjweb-adaptor SOPE/sope-appserver/mod_ngobjweb/sns.c0000644000000000000000000002441215004363604016704 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #include "NGBufferedDescriptor.h" extern int HEAVY_LOG; //#define HTTP_DETAIL_LOG 1 #define SNS_HTTP_METHOD "POST" #define SNS_LOOKUP_URL "/snsd2/wa/lookupSession" #define SNS_REQLINE "reqline" #define SNS_APPNAME "appname" #define SNS_COOKIES "cookies" static inline int _isPlistBreakChar(unsigned char c) { if (!apr_isalnum(c)) return 1; switch (c) { case '_': case '@': case '#': case '$': case '.': case '=': case ';': case ',': case '{': case '}': case '(': case ')': case '<': case '>': case '/': case '\\': case '"': return 1; default: return 0; } } static void _getSNSAddressForRequest(request_rec *_rq, struct sockaddr **_sns, ngobjweb_dir_config *_cfg) { //extern struct sockaddr *sns; struct sockaddr *result = NULL; //sns; const char *socket; *_sns = NULL; if (_rq == NULL) { fprintf(stderr, "%s: missing request ...\n", __PRETTY_FUNCTION__); return; } if (_cfg == NULL) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server, "SNS: missing directory config for request .."); return; } if ((socket = _cfg->snsPort)) { long int port; char *end, *pos; if (_cfg->snsPortDomain == AF_UNIX) { result = apr_palloc(_rq->pool, sizeof(struct sockaddr_un)); memset(result, 0, sizeof(struct sockaddr_un)); ((struct sockaddr_un *)result)->sun_family = AF_UNIX; strncpy(((struct sockaddr_un *)result)->sun_path, socket, sizeof(((struct sockaddr_un *)result)->sun_path) - 1); } else if (_cfg->snsPortDomain == AF_INET) { /* the string contained a number - the port of an IP address */ struct sockaddr_in *snsi; unsigned char *host; /* try to convert port to number */ if ((pos = index(socket, ':'))) { /* contains a ':' */ port = strtol((pos + 1), &end, 10); host = apr_palloc(_rq->pool, (pos - socket) + 3); strncpy((char *)host, socket, (pos - socket)); host[pos - socket] = '\0'; } else { host = (unsigned char *)"127.0.0.1"; port = strtol(socket, &end, 10); } result = apr_palloc(_rq->pool, sizeof(struct sockaddr_in)); memset(result, 0, sizeof(struct sockaddr_in)); snsi = (struct sockaddr_in *)result; snsi->sin_addr.s_addr = apr_inet_addr((char *)host); snsi->sin_family = AF_INET; snsi->sin_port = htons((short)(port & 0xFFFF)); if (snsi->sin_addr.s_addr == -1) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server, "SNS: couldn't convert snsd IP address: %s", host); } if (HEAVY_LOG && 0) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server, "SNS: connect IP address: %s", host); } } else { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server, "SNS: unknown socket domain %i for SNS server " "(address=%s) !!!", _cfg->snsPortDomain, _cfg->snsPort); } } *_sns = result; } static void _logSNSConnect(request_rec *_rq, struct sockaddr *sns) { if (sns == NULL) { ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server, "found no SNS socket address ..."); return; } if (sns->sa_family == AF_INET) { struct sockaddr_in *snsi = (struct sockaddr_in *)sns; if (HEAVY_LOG) { ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server, "SNS: connecting INET socket (family=%d, ip=%s:%i) ...", sns->sa_family, inet_ntoa(snsi->sin_addr), ntohs(snsi->sin_port)); } } else if (sns->sa_family == AF_UNIX) { if (HEAVY_LOG) { ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server, "SNS: connect UNIX socket (family=%d) ...", sns->sa_family); } } else { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server, "SNS: unknown socket address family: %d.", sns->sa_family); } } void *_sendSNSQuery(request_rec *_rq, const char *_line, const char *_cookie, int *_domain, size_t *_len, const char *_appName, ngobjweb_dir_config *_cfg) { /* Sends a query for the instance socket address to the session name server. */ NGBufferedDescriptor *toSNS = NULL; int fd; struct sockaddr *sns; int failed = 0; _getSNSAddressForRequest(_rq, &sns, _cfg); if (sns == NULL) { return NULL; } *_domain = 0; *_len = 0; if (_line == NULL) _line = ""; if (_cookie == NULL) _cookie = ""; /* setup connection */ { _logSNSConnect(_rq, sns); fd = socket(sns->sa_family, SOCK_STREAM, 0); if (fd < 0) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server, "SNS: could not setup socket to SNS: %s.", strerror(errno)); return NULL; } if (connect(fd, sns, (sns->sa_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_un)) != 0) { if (HEAVY_LOG) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server, "could not connect sns daemon %s: %s.", sns->sa_family == AF_UNIX ? ((struct sockaddr_un *)sns)->sun_path : "via ip", strerror(errno)); } close(fd); return NULL; } toSNS = NGBufferedDescriptor_newWithOwnedDescriptorAndSize(fd, 1024); if (toSNS == NULL) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server, "could not allocate buffered descriptor."); close(fd); return NULL; } } /* send request */ { char c = 50; // SNSLookupSession int len = strlen(_line); if (HEAVY_LOG) { ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server, "SNS: line %s cookie '%s'", _line, _cookie); } /* send message code */ if (!NGBufferedDescriptor_safeWrite(toSNS, &c, 1)) { failed = 1; goto finish; } /* send request line + space + appname */ len = strlen(_line) + 1 + strlen(_appName); if (!NGBufferedDescriptor_safeWrite(toSNS, &len, sizeof(len))) { failed = 2; goto finish; } if ((len = strlen(_line)) > 0) { if (!NGBufferedDescriptor_safeWrite(toSNS, _line, len)) { failed = 3; goto finish; } } if (!NGBufferedDescriptor_safeWrite(toSNS, " ", 1)) { failed = 4; goto finish; } if ((len = strlen(_appName)) > 0) { if (!NGBufferedDescriptor_safeWrite(toSNS, _appName, len)) { failed = 5; goto finish; } } // send cookie len = strlen(_cookie); if (len > 2000) { ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server, "WARNING: cookie length > 2000 bytes (%i bytes): %s", len, _cookie); } if (!NGBufferedDescriptor_safeWrite(toSNS, &len, sizeof(len))) { failed = 6; goto finish; } if (len > 0) { if (!NGBufferedDescriptor_safeWrite(toSNS, _cookie, len)) { failed = 7; goto finish; } } if (!NGBufferedDescriptor_flush(toSNS)) { failed = 8; goto finish; } if (HEAVY_LOG) { ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server, "SNS: reading response .."); } // recv response { char *buffer; int domain; int size; buffer = apr_palloc(_rq->pool, 1000); memset(buffer, 0, 1000); if (!NGBufferedDescriptor_safeRead(toSNS, &domain, sizeof(domain))) { failed = 9; goto finish; } if (HEAVY_LOG) { ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server, "SNS: domain: %i ..", domain); } if (!NGBufferedDescriptor_safeRead(toSNS, &size, sizeof(size))) { failed = 10; goto finish; } if (HEAVY_LOG) { ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server, "SNS: size: %i ..", size); } if (size > 1024) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server, "SNS: size of returned address is too big (%i bytes) !", size); goto finish; } if (!NGBufferedDescriptor_safeRead(toSNS, buffer, size)) { failed = 11; goto finish; } if (HEAVY_LOG) { ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server, "SNS: got address in domain %i, size is %i bytes !", domain, size); } *_domain = domain; *_len = size; if (toSNS) { NGBufferedDescriptor_free(toSNS); toSNS = NULL; } return buffer; } finish: if (failed) { ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server, "SNS: lookup request failed (code=%i) !", failed); } if (toSNS) { NGBufferedDescriptor_free(toSNS); toSNS = NULL; } } return NULL; } SOPE/sope-appserver/mod_ngobjweb/ngobjweb.load0000644000000000000000000000032415004363604020367 0ustar rootroot# # ngobjweb.load for Ubuntu # # You can copy this to /etc/apache2/mods-available/ and then enable # mod_ngobjweb using: # a2enmod ngobjweb # LoadModule ngobjweb_module /usr/lib/apache2/modules/mod_ngobjweb.so SOPE/sope-appserver/mod_ngobjweb/README0000644000000000000000000000406115004363604016613 0ustar rootrootmod_ngobjweb ============ This is an Apache module for forwarding HTTP requests to SOPE application server instances. It has the ability to ask the snsd load balancer to distribute requests between processes and/or hosts. Apache Config Directives ------------------------ SetSNSPort SetAppPrefix SetAppPort SNSUseHTTP (experimental) Loading the Module with apache 1.3.x ------------------------------------ LoadModule ngobjweb_module modules/ngobjweb_1.3.x.so AddModule ngobjweb_module.c Loading the Module with apache 2.0.x ------------------------------------ LoadModule ngobjweb_module modules/ngobjweb_2.0.x.so Example Apache Config --------------------- SetHandler ngobjweb-adaptor SetAppPort 20000 Apache on Debian SID ==================== Apache is not named 'httpd' on Debian, so you need to invoke make with a parameter. Compilation for Apache2: make HTTPD=/usr/sbin/apache Afterwards move the build module to /usr/lib/apache/1.3/mod_ngobjweb.so and copy the *.info file to the same directory. Then run: modules-config apache enable mod_ngobjweb Finally create a proper OGo.conf in /etc/apache/conf.d. Apache2 on MacOSX 10.5 ====================== So you need to add the APR include dir to the make call, eg: make apxs=/usr/sbin/apxs apr=/usr/bin/apr-1-config \ EXTRA_LDFLAGS="-bundle -undefined error -dynamic" Apache2 on SuSE 9.0 =================== Compilation for Apache2: make \ apxs=/usr/sbin/apxs2 \ HTTPD=/usr/sbin/httpd2 Just create a new config file in "/etc/apache2/conf.d/OGo.conf" and add the directives you need. Be sure to use "apache2" to restart instead of "apache" (which will restart Apache 1.3 ...). You should probably not use a threaded Apache 2 MPM, which may have issues with mod_ngobjweb but something like prefork. And finally: in the long run you should remove SuSE 9.0 from your machine and rather install a free distribution like Debian. Note: /etc/rc.d/apache2 stop does not work on SuSE 9.0 ... you need to killall the httpd-prefork processes manually, sigh. SOPE/sope-appserver/mod_ngobjweb/NGBufferedDescriptor.c0000644000000000000000000002445015004363604022111 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include "common.h" #include "NGBufferedDescriptor.h" // returns the number of bytes which where read from the buffer #define numberOfConsumedReadBufferBytes(self) \ ((self->readBufferSize == 0) ? 0 : (self->readBufferPos - self->readBuffer)) // returns the number of bytes which can be read from buffer (without source access) #define numberOfAvailableReadBufferBytes(self) \ (self->readBufferFillSize - numberOfConsumedReadBufferBytes(self)) // look whether all bytes in the buffer where consumed, if so, reset the buffer #define checkReadBufferFillState(self) \ if (numberOfAvailableReadBufferBytes(self) == 0) { \ self->readBufferPos = self->readBuffer; \ self->readBufferFillSize = 0; \ } // implementation NGBufferedDescriptor * NGBufferedDescriptor_newWithDescriptorAndSize(int _fd, int _size) { NGBufferedDescriptor *self = malloc(sizeof(NGBufferedDescriptor)); if (self) { self->fd = _fd; self->readBuffer = malloc(_size); self->writeBuffer = malloc(_size); self->readBufferPos = self->readBuffer; self->readBufferSize = _size; self->readBufferFillSize = 0; // no bytes are read from source self->writeBufferFillSize = 0; self->writeBufferSize = _size; self->ownsFd = 0; } return self; } NGBufferedDescriptor *NGBufferedDescriptor_newWithDescriptor(int _fd) { return NGBufferedDescriptor_newWithDescriptorAndSize(_fd, 1024); } NGBufferedDescriptor * NGBufferedDescriptor_newWithOwnedDescriptorAndSize(int _fd, int _size) { NGBufferedDescriptor *self = NULL; if ((self = NGBufferedDescriptor_newWithDescriptorAndSize(_fd, _size))) self->ownsFd = 1; else close(_fd); return self; } void NGBufferedDescriptor_free(NGBufferedDescriptor *self) { if (self) { NGBufferedDescriptor_flush(self); if (self->ownsFd && self->fd != -1) { close(self->fd); self->fd = -1; } if (self->readBuffer) { free(self->readBuffer); self->readBuffer = NULL; self->readBufferPos = NULL; } self->readBufferFillSize = 0; self->readBufferSize = 0; if (self->writeBuffer) { free(self->writeBuffer); self->writeBuffer = NULL; } self->writeBufferFillSize = 0; self->writeBufferSize = 0; free(self); } } int NGBufferedDescriptor_getReadBufferSize(NGBufferedDescriptor *self) { if (self == NULL) return 0; return self->readBufferSize; } int NGBufferedDescriptor_getWriteBufferSize(NGBufferedDescriptor *self) { if (self == NULL) return 0; return self->writeBufferSize; } int NGBufferedDescriptor_read(NGBufferedDescriptor *self, void *_buf, int _len) { register int availBytes; if (self == NULL) return 0; if (self->readBufferSize == 0) // no read buffering is done (buffersize==0) return read(self->fd, _buf, _len); availBytes = numberOfAvailableReadBufferBytes(self); if (availBytes >= _len) { // there are enough bytes in the buffer to fulfill the request if (_len == 1) { *(unsigned char *)_buf = *(unsigned char *)self->readBufferPos; self->readBufferPos++; } else { memcpy(_buf, self->readBufferPos, _len); self->readBufferPos += _len; // update read position (consumed-size) } checkReadBufferFillState(self); // check whether all bytes where consumed return _len; } else if (availBytes > 0) { // there are some bytes in the buffer, these are returned memcpy(_buf, self->readBufferPos, availBytes); // copy all bytes from buffer self->readBufferPos = self->readBuffer; // reset position self->readBufferFillSize = 0; // no bytes available in buffer anymore return availBytes; } else if (_len > self->readBufferSize) { // requested _len is bigger than the buffersize, so we can bypass the // buffer (which is empty, as guaranteed by the previous 'ifs' return read(self->fd, _buf, _len); } else { // no bytes are available and the requested _len is smaller than the possible // buffer size, we have to read the next block of input from the source self->readBufferFillSize = read(self->fd, self->readBuffer, self->readBufferSize); // no comes a section which is roughly the same like the first to conditionals // in this method if (self->readBufferFillSize >= _len) { // there are enough bytes in the buffer to fulfill the request memcpy(_buf, self->readBufferPos, _len); self->readBufferPos += _len; // update read position (consumed-size) checkReadBufferFillState(self); // check whether all bytes where consumed return _len; } else { // (readBufferFillSize > 0) (this is ensured by the above assert) // there are some bytes in the buffer, these are returned availBytes = self->readBufferFillSize; memcpy(_buf, self->readBufferPos, self->readBufferFillSize); // copy all bytes from buffer self->readBufferPos = self->readBuffer; // reset position self->readBufferFillSize = 0; // no bytes available in buffer anymore return availBytes; } } } int NGBufferedDescriptor_write(NGBufferedDescriptor *self, const void *_buf, int _len) { register int tmp = 0; register int remaining = _len; register void *track = (void *)_buf; if (self == NULL) return 0; while (remaining > 0) { // how much bytes available in buffer ? tmp = self->writeBufferSize - self->writeBufferFillSize; tmp = (tmp > remaining) ? remaining : tmp; memcpy((self->writeBuffer + self->writeBufferFillSize), track, tmp); track += tmp; remaining -= tmp; self->writeBufferFillSize += tmp; if (self->writeBufferFillSize == self->writeBufferSize) { void *pos = self->writeBuffer; while (self->writeBufferFillSize > 0) { int result; result = write(self->fd, pos, self->writeBufferFillSize); if ((result == 0) || (result < 0)) { // socket closed || error self->writeBufferFillSize = 0; // content is lost .. return result; } self->writeBufferFillSize -= result; pos += result; } } } #if 0 if (self->flags._flushOnNewline == 1) { // scan buffer for newlines, if one is found, flush buffer for (tmp = 0; tmp < _len; tmp++) { if (tmp == '\n') { NGBufferedDescriptor_flush(self); break; } } } #endif // clean up for GC tmp = 0; track = NULL; // clean up for GC remaining = 0; return _len; } char NGBufferedDescriptor_flush(NGBufferedDescriptor *self) { if (self == NULL) return 0; if (self->writeBufferFillSize > 0) { int toGo = self->writeBufferFillSize; void *pos = self->writeBuffer; while (toGo > 0) { int result = write(self->fd, pos, toGo); if (result == 0) // socket was closed return 0; else if (result < 1) // socket error return 0; toGo -= result; pos += result; } self->writeBufferFillSize = 0; } return 1; } unsigned char NGBufferedDescriptor_safeRead(NGBufferedDescriptor *self, void *_buffer, int _len) { if (self == NULL) return 0; if (_len > 0) { while (_len > 0) { int result = NGBufferedDescriptor_read(self, _buffer, _len); if (result == 0) // socket was closed return 0; else if (result < 1) // socket error return 0; _len -= result; _buffer += result; } } return 1; } char NGBufferedDescriptor_safeWrite(NGBufferedDescriptor *self, const void *_buffer, int _len) { if (self == NULL) return 0; if (_len > 0) { while (_len > 0) { int result; result = NGBufferedDescriptor_write(self, _buffer, _len); if (result == 0) // socket was closed return 0; else if (result < 1) // socket error return 0; _len -= result; _buffer += result; } } return 1; } int NGBufferedDescriptor_readChar(NGBufferedDescriptor *self) { unsigned char c; return (NGBufferedDescriptor_safeRead(self, &c, 1)) ? c : -1; } char NGBufferedDescriptor_writeHttpHeader(NGBufferedDescriptor *self, const char *_key, const unsigned char *_value) { register unsigned int len; if (!NGBufferedDescriptor_safeWrite(self, _key, strlen((char *)_key))) return 0; if (!NGBufferedDescriptor_safeWrite(self, ": ", 2)) return 0; len = strlen((char *)_value); /* Required for deliverying certificates, we encode \n and \r as %10 and %13 assuming that the certficiate is in base64. To safeguard, we also encode % as %25. */ if (len > 0 && (index((char *)_value, '\n') != NULL || index((char *)_value, '\r') !=NULL)) { for (len = 0; _value[len] != '\0'; len++) { switch (_value[len]) { case '%': case '\r': case '\n': { char buf[4]; sprintf(buf, "%%%02i", _value[len]); if (NGBufferedDescriptor_write(self, buf, 3) <= 0) return 0; break; } default: if (NGBufferedDescriptor_write(self, &(_value[len]), 1) <= 0) return 0; break; } } } else { if (!NGBufferedDescriptor_safeWrite(self, _value, len)) return 0; } if (!NGBufferedDescriptor_safeWrite(self, "\r\n", 2)) return 0; return 1; } SOPE/sope-appserver/mod_ngobjweb/apversion.sh0000755000000000000000000000104115004363604020273 0ustar rootroot#!/bin/sh # determines the Apache version number if test x"-v" = x"${1}"; then if test x = x"${2}"; then echo "usage: ${0} -v httpd" exit 1 else ${2} -v|grep 'ersion:*'|awk '{print $3}'|awk -F/ '{print $2}' fi fi if test x"-iseapi" = x"${1}"; then if test x = x"${2}"; then echo "usage: ${0} -iseapi httpd" exit 1 else eapi=`${2} -V|grep -c EAPI` if test x0 = x"${eapi}"; then echo "no" exit 0 else echo "yes" exit 0 fi fi fi echo "usage: ${0} -iseapi|-v httpd" exit 1 SOPE/sope-appserver/mod_ngobjweb/scanhttp.c0000644000000000000000000001077215004363604017731 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #include "NGBufferedDescriptor.h" unsigned char NGScanResponseLine(NGBufferedDescriptor *_in, unsigned char *_version, int *_status, unsigned char *_text) { if (_in == NULL) return 0; if (_version) *_version = '\0'; if (_text) *_text = '\0'; if (_status) *_status = '\0'; { int c; int i; /* scan HTTP Version */ { c = NGBufferedDescriptor_readChar(_in); i = 0; while ((c > 0) && !apr_isspace(c) && (i < 16)) { if (_version) _version[i] = c; i++; c = NGBufferedDescriptor_readChar(_in); } if (_version) _version[i] = '\0'; if (c < 1) return 0; // read error } /* skip spaces */ while ((c > 0) && apr_isspace(c)) c = NGBufferedDescriptor_readChar(_in); if (c < 1) return 0; // read error /* scan code */ { char buf[10]; i = 0; while ((c > 0) && !apr_isspace(c) && (c != '\r') && (c != '\n') && (i < 6)) { buf[i] = c; i++; c = NGBufferedDescriptor_readChar(_in); } buf[i] = '\0'; if (_status) *_status = atoi(buf); } /* skip spaces */ while ((c > 0) && apr_isspace(c)) c = NGBufferedDescriptor_readChar(_in); if (c < 1) return 0; // read error /* check for EOL */ if (c == '\n') return 1; // response without reason if (c == '\r') { // response without reason c = NGBufferedDescriptor_readChar(_in); // c=='\n' return 1; } /* scan reason */ { i = 0; while ((c > 0) && !apr_isspace(c) && (c != '\r') && (c != '\n') && (i < 6)) { if (_text) _text[i] = c; i++; c = NGBufferedDescriptor_readChar(_in); } if (_text) _text[i] = '\0'; if (c < 1) return 0; // read error } /* scan until line end */ while ((c > 0) && (c != '\n')) c = NGBufferedDescriptor_readChar(_in); if (c < 1) return 0; // read error } return 1; } apr_table_t *NGScanHeaders(apr_pool_t *_pool, NGBufferedDescriptor *_in) { apr_table_t *headers = NULL; if (_in == NULL) return NULL; headers = apr_table_make(_pool, 64); if (headers) { char name[256]; char value[8000]; int c; while (1) { int i, j; c = NGBufferedDescriptor_readChar(_in); if (c <= 0) // error break; // test for end of HTTP header { if (c == '\n') // end line '\n' break; if (c == '\r') { // end line '\r\n' c = NGBufferedDescriptor_readChar(_in); // c should be '\n' break; } } // scan name { i = 0; while ((c > 0) && (c != ':') && (i < 255)) { name[i] = c; i++; c = NGBufferedDescriptor_readChar(_in); } name[i] = '\0'; if (i < 1) break; // empty header name ?! } if (c != ':') break; // missing separator ? // skip spaces following separator c = NGBufferedDescriptor_readChar(_in); while ((c > 0) && (apr_isspace(c))) c = NGBufferedDescriptor_readChar(_in); // scan value { j = 0; while ((c > 0) && (c != '\r') && (j < 7999)) { value[j] = c; j++; c = NGBufferedDescriptor_readChar(_in); } value[j] = '\0'; if (j < 1) break; // empty header value ?! } if (c == '\n') // '\n' header end ; else if (c == '\r') { // '\r\n' header end c = NGBufferedDescriptor_readChar(_in); if (c != '\n') break; } else // no valid header end break; // store value apr_table_add(headers, name, value); } } return headers; } SOPE/sope-appserver/mod_ngobjweb/httpd.conf0000644000000000000000000003741715004363604017740 0ustar rootroot## ## httpd.conf -- Apache HTTP server configuration file ## ### Section 1: Global Environment # # The directives in this section affect the overall operation of Apache, # such as the number of concurrent requests it can handle or where it # can find its configuration files. # # # ServerType is either inetd, or standalone. Inetd mode is only supported on # Unix platforms. # ServerType standalone # # ServerRoot: The top of the directory tree under which the server's # configuration, error, and log files are kept. # # NOTE! If you intend to place this on an NFS (or otherwise network) # mounted filesystem then please read the LockFile documentation # (available at ); # you will save yourself a lot of trouble. # # Do NOT add a slash at the end of the directory path. # ServerRoot "/tmp/httpd-8888" # # The LockFile directive sets the path to the lockfile used when Apache # is compiled with either USE_FCNTL_SERIALIZED_ACCEPT or # USE_FLOCK_SERIALIZED_ACCEPT. This directive should normally be left at # its default value. The main reason for changing it is if the logs # directory is NFS mounted, since the lockfile MUST BE STORED ON A LOCAL # DISK. The PID of the main server process is automatically appended to # the filename. # LockFile /tmp/httpd.accept.lock # # PidFile: The file in which the server should record its process # identification number when it starts. # PidFile /tmp/httpd.pid # # ScoreBoardFile: File used to store internal server process information. # Not all architectures require this. But if yours does (you'll know because # this file will be created when you run Apache) then you *must* ensure that # no two invocations of Apache share the same scoreboard file. # ScoreBoardFile /tmp/httpd.apache_runtime_status # # In the standard configuration, the server will process httpd.conf, # srm.conf, and access.conf in that order. The latter two files are # now distributed empty, as it is recommended that all directives # be kept in a single file for simplicity. The commented-out values # below are the built-in defaults. You can have the server ignore # these files altogether by using "/dev/null" (for Unix) or # "nul" (for Win32) for the arguments to the directives. # #ResourceConfig conf/srm.conf #AccessConfig conf/access.conf ResourceConfig /dev/null AccessConfig /dev/null # # Timeout: The number of seconds before receives and sends time out. # Timeout 300 # # KeepAlive: Whether or not to allow persistent connections (more than # one request per connection). Set to "Off" to deactivate. # KeepAlive On # # MaxKeepAliveRequests: The maximum number of requests to allow # during a persistent connection. Set to 0 to allow an unlimited amount. # We recommend you leave this number high, for maximum performance. # MaxKeepAliveRequests 100 # # KeepAliveTimeout: Number of seconds to wait for the next request from the # same client on the same connection. # KeepAliveTimeout 15 # # Server-pool size regulation. Rather than making you guess how many # server processes you need, Apache dynamically adapts to the load it # sees --- that is, it tries to maintain enough server processes to # handle the current load, plus a few spare servers to handle transient # load spikes (e.g., multiple simultaneous requests from a single # Netscape browser). # # It does this by periodically checking how many servers are waiting # for a request. If there are fewer than MinSpareServers, it creates # a new spare. If there are more than MaxSpareServers, some of the # spares die off. The default values in httpd.conf-dist are probably OK # for most sites. # MinSpareServers 1 MaxSpareServers 10 # # Number of servers to start initially --- should be a reasonable ballpark # figure. # StartServers 1 # # Limit on total number of servers running, i.e., limit on the number # of clients who can simultaneously connect --- if this limit is ever # reached, clients will be LOCKED OUT, so it should NOT BE SET TOO LOW. # It is intended mainly as a brake to keep a runaway server from taking # the system with it as it spirals down... # MaxClients 150 # # MaxRequestsPerChild: the number of requests each child process is # allowed to process before the child dies. The child will exit so # as to avoid problems after prolonged use when Apache (and maybe the # libraries it uses) leak memory or other resources. On most systems, this # isn't really needed, but a few (such as Solaris) do have notable leaks # in the libraries. # MaxRequestsPerChild 30 # # Dynamic Shared Object (DSO) Support # # To be able to use the functionality of a module which was built as a DSO you # have to place corresponding `LoadModule' lines at this location so the # directives contained in it are actually available _before_ they are used. # Please read the file README.DSO in the Apache 1.3 distribution for more # details about the DSO mechanism and run `httpd -l' for the list of already # built-in (statically linked and thus always available) modules in your httpd # binary. # # Note: The order is which modules are loaded is important. Don't change # the order below without expert advice. # # Example: # LoadModule foo_module libexec/mod_foo.so LoadModule mmap_static_module /usr/lib/apache/mod_mmap_static.so LoadModule env_module /usr/lib/apache/mod_env.so LoadModule config_log_module /usr/lib/apache/mod_log_config.so LoadModule mime_module /usr/lib/apache/mod_mime.so LoadModule includes_module /usr/lib/apache/mod_include.so LoadModule alias_module /usr/lib/apache/mod_alias.so LoadModule access_module /usr/lib/apache/mod_access.so LoadModule auth_module /usr/lib/apache/mod_auth.so LoadModule setenvif_module /usr/lib/apache/mod_setenvif.so # Reconstruction of the complete module list from all available modules # (static and shared ones) to achieve correct module execution order. # [WHENEVER YOU CHANGE THE LOADMODULE SECTION ABOVE UPDATE THIS, TOO] ClearModuleList AddModule mod_mmap_static.c AddModule mod_env.c AddModule mod_log_config.c AddModule mod_mime.c AddModule mod_include.c AddModule mod_alias.c AddModule mod_access.c AddModule mod_auth.c AddModule mod_so.c AddModule mod_setenvif.c # # ExtendedStatus controls whether Apache will generate "full" status # information (ExtendedStatus On) or just basic information (ExtendedStatus # Off) when the "server-status" handler is called. The default is Off. # #ExtendedStatus On ### Section 2: 'Main' server configuration # # The directives in this section set up the values used by the 'main' # server, which responds to any requests that aren't handled by a # definition. These values also provide defaults for # any containers you may define later in the file. # # All of these directives may appear inside containers, # in which case these default settings will be overridden for the # virtual host being defined. # # # If your ServerType directive (set earlier in the 'Global Environment' # section) is set to "inetd", the next few directives don't have any # effect since their settings are defined by the inetd configuration. # Skip ahead to the ServerAdmin directive. # # # Port: The port to which the standalone server listens. For # ports < 1023, you will need httpd to be run as root initially. # Port 8888 # # If you wish httpd to run as a different user or group, you must run # httpd as root initially and it will switch. # # User/Group: The name (or #number) of the user/group to run httpd as. # . On SCO (ODT 3) use "User nouser" and "Group nogroup". # . On HPUX you may not be able to use shared memory as nobody, and the # suggested workaround is to create a user www and use that user. # NOTE that some kernels refuse to setgid(Group) or semctl(IPC_SET) # when the value of (unsigned)Group is above 60000; # don't use Group nogroup on these systems! # User helge Group dev # # ServerAdmin: Your address, where problems with the server should be # e-mailed. This address appears on some server-generated pages, such # as error documents. # ServerAdmin root@localhost # # ServerName allows you to set a host name which is sent back to clients for # your server if it's different than the one the program would get (i.e., use # "www" instead of the host's real name). # # Note: You cannot just invent host names and hope they work. The name you # define here must be a valid DNS name for your host. If you don't understand # this, ask your network administrator. # If your host doesn't have a registered DNS name, enter its IP address here. # You will have to access it by its address (e.g., http://123.45.67.89/) # anyway, and this will make redirections work in a sensible way. # #ServerName Euklid.suse.de # # DocumentRoot: The directory out of which you will serve your # documents. By default, all requests are taken from this directory, but # symbolic links and aliases may be used to point to other locations. # DocumentRoot "/HOME/helge/mdev/LSOffice3/LSWebInterface/Skyrix" # # Each directory to which Apache has access, can be configured with respect # to which services and features are allowed and/or disabled in that # directory (and its subdirectories). # # First, we configure the "default" to be a very restrictive set of # permissions. # Options FollowSymLinks AllowOverride None # # Note that from this point forward you must specifically allow # particular features to be enabled - so if something's not working as # you might expect, make sure that you have specifically enabled it # below. # # # This should be changed to whatever you set DocumentRoot to. # # # This may also be "None", "All", or any combination of "Indexes", # "Includes", "FollowSymLinks", "ExecCGI", or "MultiViews". # # Note that "MultiViews" must be named *explicitly* --- "Options All" # doesn't give it to you. # Options Indexes FollowSymLinks # # This controls which options the .htaccess files in directories can # override. Can also be "All", or any combination of "Options", "FileInfo", # "AuthConfig", and "Limit" # AllowOverride None # # Controls who can get stuff from this server. # Order allow,deny Allow from all # # UseCanonicalName: (new for 1.3) With this setting turned on, whenever # Apache needs to construct a self-referencing URL (a URL that refers back # to the server the response is coming from) it will use ServerName and # Port to form a "canonical" name. With this setting off, Apache will # use the hostname:port that the client supplied, when possible. This # also affects SERVER_NAME and SERVER_PORT in CGI scripts. # UseCanonicalName On # # TypesConfig describes where the mime.types file (or equivalent) is # to be found. # TypesConfig /etc/httpd/mime.types # # DefaultType is the default MIME type the server will use for a document # if it cannot otherwise determine one, such as from filename extensions. # If your server contains mostly text or HTML documents, "text/plain" is # a good value. If most of your content is binary, such as applications # or images, you may want to use "application/octet-stream" instead to # keep browsers from trying to display binary files as though they are # text. # DefaultType text/plain # # HostnameLookups: Log the names of clients or just their IP addresses # e.g., www.apache.org (on) or 204.62.129.132 (off). # The default is off because it'd be overall better for the net if people # had to knowingly turn this feature on, since enabling it means that # each client request will result in AT LEAST one lookup request to the # nameserver. # HostnameLookups Off # # ErrorLog: The location of the error log file. # If you do not specify an ErrorLog directive within a # container, error messages relating to that virtual host will be # logged here. If you *do* define an error logfile for a # container, that host's errors will be logged there and not here. # ErrorLog /tmp/httpd-8888/httpd.error_log # # LogLevel: Control the number of messages logged to the error_log. # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. # LogLevel info # # The following directives define some format nicknames for use with # a CustomLog directive (see below). # LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %l %u %t \"%r\" %>s %b" common LogFormat "%{Referer}i -> %U" referer LogFormat "%{User-agent}i" agent # # The location and format of the access logfile (Common Logfile Format). # If you do not define any access logfiles within a # container, they will be logged here. Contrariwise, if you *do* # define per- access logfiles, transactions will be # logged therein and *not* in this file. # CustomLog /tmp/httpd-8888/httpd.access_log common # # Optionally add a line containing the server version and virtual host # name to server-generated pages (error documents, FTP directory listings, # mod_status and mod_info output etc., but not CGI generated documents). # Set to "EMail" to also include a mailto: link to the ServerAdmin. # Set to one of: On | Off | EMail # ServerSignature On # # SKYRIX configurations # Include skyrix.conf # # Redirect allows you to tell clients about documents which used to exist in # your server's namespace, but do not anymore. This allows you to tell the # clients where to look for the relocated document. # Format: Redirect old-URI new-URL # # # Directives controlling the display of server-generated directory listings. # # # AddEncoding allows you to have certain browsers (Mosaic/X 2.1+) uncompress # information on the fly. Note: Not all browsers support this. # Despite the name similarity, the following Add* directives have nothing # to do with the FancyIndexing customization directives above. # AddEncoding x-compress Z AddEncoding x-gzip gz # # Customizable error response (Apache style) # these come in three flavors # # 1) plain text #ErrorDocument 500 "The server made a boo boo. # n.b. the (") marks it as text, it does not get output # # 2) local redirects #ErrorDocument 404 /missing.html # to redirect to local URL /missing.html #ErrorDocument 404 /cgi-bin/missing_handler.pl # N.B.: You can redirect to a script or a document using server-side-includes. # # 3) external redirects #ErrorDocument 402 http://some.other_server.com/subscription_info.html # N.B.: Many of the environment variables associated with the original # request will *not* be available to such a script. # # The following directives modify normal HTTP response behavior. # The first directive disables keepalive for Netscape 2.x and browsers that # spoof it. There are known problems with these browser implementations. # The second directive is for Microsoft Internet Explorer 4.0b2 # which has a broken HTTP/1.1 implementation and does not properly # support keepalive when it is used on 301 or 302 (redirect) responses. # BrowserMatch "Mozilla/2" nokeepalive BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 # # The following directive disables HTTP/1.1 responses to browsers which # are in violation of the HTTP/1.0 spec by not being able to grok a # basic 1.1 response. # BrowserMatch "RealPlayer 4\.0" force-response-1.0 BrowserMatch "Java/1\.0" force-response-1.0 BrowserMatch "JDK/1\.0" force-response-1.0 # # Allow server status reports, with the URL of http://servername/server-status # Change the ".your_domain.com" to match your domain to enable. # SetHandler server-status Order deny,allow Deny from all Allow from localhost # # Allow remote server configuration reports, with the URL of # http://servername/server-info (requires that mod_info.c be loaded). # Change the ".your_domain.com" to match your domain to enable. # # # SetHandler server-info # Order deny,allow # Deny from all # Allow from .your_domain.com # SOPE/sope-appserver/mod_ngobjweb/COPYRIGHT0000644000000000000000000000010615004363604017222 0ustar rootrootCopyright (C) 2000-2005 SKYRIX Software AG Contact: info@skyrix.com SOPE/sope-appserver/mod_ngobjweb/NGBufferedDescriptor.h0000644000000000000000000000513715004363604022117 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGBufferedDescriptor_H__ #define __NGBufferedDescriptor_H__ typedef struct _NGBufferedDescriptor { int fd; // descriptor void *readBuffer; void *readBufferPos; // current position (ptr) in buffer int readBufferFillSize; // number of 'read' bytes in the buffer int readBufferSize; // maximum capacity in bytes void *writeBuffer; int writeBufferFillSize; int writeBufferSize; char ownsFd; } NGBufferedDescriptor; NGBufferedDescriptor * NGBufferedDescriptor_newWithOwnedDescriptorAndSize(int _fd, int _size); NGBufferedDescriptor * NGBufferedDescriptor_newWithDescriptorAndSize(int _fd, int _size); NGBufferedDescriptor * NGBufferedDescriptor_newWithDescriptor(int _fd); void NGBufferedDescriptor_free(NGBufferedDescriptor *self); // accessors int NGBufferedDescriptor_getReadBufferSize(NGBufferedDescriptor *self); int NGBufferedDescriptor_getWriteBufferSize(NGBufferedDescriptor *self); // primary read functions int NGBufferedDescriptor_read(NGBufferedDescriptor *self, void *_buffer, int _len); int NGBufferedDescriptor_write(NGBufferedDescriptor *self, const void *_buffer, int _len); // following functions return 1 on success and 0 and error/close char NGBufferedDescriptor_flush(NGBufferedDescriptor *self); unsigned char NGBufferedDescriptor_safeRead(NGBufferedDescriptor *self, void *_buffer, int _len); char NGBufferedDescriptor_safeWrite(NGBufferedDescriptor *self, const void *_buffer, int _len); int NGBufferedDescriptor_readChar(NGBufferedDescriptor *self); char NGBufferedDescriptor_writeHttpHeader(NGBufferedDescriptor *self, const char *_key, const unsigned char *_value); #endif SOPE/sope-appserver/mod_ngobjweb/globals.c0000644000000000000000000000155615004363604017530 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include int HEAVY_LOG = 0; //struct sockaddr *sns = 0; SOPE/sope-appserver/NGObjWeb/0000755000000000000000000000000015004363604014673 5ustar rootrootSOPE/sope-appserver/NGObjWeb/WOResourceRequestHandler.m0000644000000000000000000001270315004363604021760 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include @interface WOResourceRequestHandler : WORequestHandler @end #include #include #include #include #include "common.h" @interface WOResourceManager(PrivateKeyedAccess) - (id)_dataForKey:(NSString *)_key sessionID:(NSString *)_sid; @end @implementation WOResourceRequestHandler static BOOL debugOn = NO; - (WOResponse *)_handleWebServerResourcesRequest:(WORequest *)_request { WOApplication *app; NSArray *handlerPath = nil; WOResponse *response = nil; NSArray *languages; NSString *resourceName; NSString *resourcePath; NSData *data; if (debugOn) [self logWithFormat:@"handle WS request: %@", _request]; if (_request == nil) return nil; *(&app) = [WOApplication application]; handlerPath = [_request requestHandlerPathArray]; /* check for WebServerResources requests ... */ if ([handlerPath count] < 1) { if (debugOn) [self logWithFormat:@"path to short: '%@'", handlerPath]; return nil; } if (debugOn) [self logWithFormat:@" check path: '%@'", handlerPath]; /* ok, found a resource request */ if ([handlerPath count] > 1) { NSString *lang; lang = [handlerPath objectAtIndex:0]; lang = [lang stringByDeletingPathExtension]; languages = [NSArray arrayWithObject:lang]; languages = [languages arrayByAddingObjectsFromArray:languages]; resourceName = [handlerPath objectAtIndex:1]; } else { languages = [_request browserLanguages]; resourceName = [handlerPath objectAtIndex:0]; } resourcePath = [[app resourceManager] pathForResourceNamed:resourceName inFramework:nil languages:languages]; if (debugOn) [self logWithFormat:@" resource path: '%@'", resourcePath]; data = (resourcePath != nil) ? [NSData dataWithContentsOfFile:resourcePath] : nil; if (data == nil) { response = [WOResponse responseWithRequest:_request]; [response setStatus:404]; /* not found */ [response setHeader:@"text/html" forKey:@"content-type"]; [response appendContentString:@"

    Resource not found

    "];
        [response appendContentHTMLString:@"Name: "];
        [response appendContentHTMLString:resourceName];
        [response appendContentHTMLString:@"\nLanguages: "];
        [response appendContentHTMLString:[languages description]];
        [response appendContentHTMLString:@"\nResourceManager: "];
        [response appendContentHTMLString:[[app resourceManager] description]];
        [response appendContentString:@"
    "]; return response; } //NSLog(@"shall deliver %@", resourcePath); response = [WOResponse responseWithRequest:_request]; /* determine content-type */ { NSString *ctype; NSString *pathExtension; pathExtension = [resourcePath pathExtension]; ctype = @"application/octet-stream"; if ([pathExtension isEqualToString:@"html"]) ctype = @"text/html"; else if ([pathExtension isEqualToString:@"gif"]) ctype = @"image/gif"; [response setHeader:ctype forKey:@"content-type"]; } [response setContent:data]; return response; } - (WOResponse *)handleRequest:(WORequest *)_request { NSArray *handlerPath = nil; if (debugOn) [self logWithFormat:@"handle request: %@", _request]; if ([[_request requestHandlerKey] isEqualToString:@"WebServerResources"]) return [self _handleWebServerResourcesRequest:_request]; handlerPath = [_request requestHandlerPathArray]; if ([handlerPath count] > 0) { NSString *rmkey; rmkey = [handlerPath objectAtIndex:0]; if ([rmkey length] > 0) { WOResourceManager *rm; NSDictionary *data; rm = [[WOApplication application] resourceManager]; if ((data = [rm _dataForKey:rmkey sessionID:nil]) != nil) { WOResponse *response; response = [WOResponse responseWithRequest:_request]; [response setHeader:[data objectForKey:@"mimeType"] forKey:@"content-type"]; [response setContent:[data objectForKey:@"data"]]; return response; } else { [[WOApplication application] logWithFormat:@"WOResourceRequestHandler: " @"didn't find data for resource key '%@'", rmkey]; } } } /* if everything fails, try locating resource in WebServerResources */ return [self _handleWebServerResourcesRequest:_request]; } /* logging */ - (NSString *)loggingPrefix { return @"[resource-handler]"; } @end /* WOResourceRequestHandler */ SOPE/sope-appserver/NGObjWeb/WOHttpAdaptor/0000755000000000000000000000000015004363604017373 5ustar rootrootSOPE/sope-appserver/NGObjWeb/WOHttpAdaptor/WORecordRequestStream.m0000644000000000000000000000416215004363604023765 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "WORecordRequestStream.h" #include "common.h" #define ReadLogInitSize 1024 #define WriteLogInitSize 128*1024 @implementation WORecordRequestStream - (id)initWithSource:(id)_source { if ((self = [super initWithSource:_source]) != nil) { self->readLog = [[NSMutableData alloc] initWithCapacity:ReadLogInitSize]; self->writeLog = [[NSMutableData alloc] initWithCapacity:WriteLogInitSize]; } return self; } - (void)dealloc { [self->readLog release]; [self->writeLog release]; [super dealloc]; } /* accessors */ - (NSData *)readLog { return self->readLog; } - (NSData *)writeLog { return self->writeLog; } - (void)resetReadLog { [self->readLog setLength:0]; } - (void)resetWriteLog { [self->writeLog setLength:0]; } - (void)reset { [self resetReadLog]; [self resetWriteLog]; } /* implementation */ - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { unsigned len; len = [super readBytes:_buf count:_len]; if (len == NGStreamError) return NGStreamError; [self->readLog appendBytes:_buf length:len]; return len; } - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len { unsigned len; len = [super writeBytes:_buf count:_len]; if (len == NGStreamError) return NGStreamError; [self->writeLog appendBytes:_buf length:len]; return len; } @end /* WORecordRequestStream */ SOPE/sope-appserver/NGObjWeb/WOHttpAdaptor/WORequest+Adaptor.m0000644000000000000000000000240215004363604023033 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "WORequest+Adaptor.h" #include "common.h" @implementation WORequest(TakeStartDate) - (BOOL)isCodeRedAttack { return [[self uri] hasPrefix:CODE_RED_PREFIX]; } - (void)takeStartDate:(NSDate *)_startDate { static NSProcessInfo *pi = nil; id tmp; if (pi == nil) pi = [[NSProcessInfo processInfo] retain]; tmp = [pi procStatDictionary]; ASSIGN(self->startDate, (NSCalendarDate*)_startDate); ASSIGN(self->startStatistics, tmp); } @end /* WORequest(TakeStartDate) */ SOPE/sope-appserver/NGObjWeb/WOHttpAdaptor/GNUmakefile0000644000000000000000000000063115004363604021445 0ustar rootroot# GNUstep makefile include ../../../config.make include $(GNUSTEP_MAKEFILES)/common.make SUBPROJECT_NAME = WOHttpAdaptor WOHttpAdaptor_PCH_FILE = common.h WOHttpAdaptor_OBJC_FILES = \ WOHttpAdaptor.m \ WORecordRequestStream.m \ WOHttpTransaction.m \ WORequest+Adaptor.m \ WORequestParser.m \ -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/subproject.make -include GNUmakefile.postamble SOPE/sope-appserver/NGObjWeb/WOHttpAdaptor/common.h0000644000000000000000000000167315004363604021043 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #include #include #include #include SOPE/sope-appserver/NGObjWeb/WOHttpAdaptor/WORecordRequestStream.h0000644000000000000000000000224115004363604023754 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __WORecordRequestStream_H__ #define __WORecordRequestStream_H__ #include @class NSData, NSMutableData; @interface WORecordRequestStream : NGFilterStream { NSMutableData *readLog; NSMutableData *writeLog; } - (NSData *)readLog; - (NSData *)writeLog; - (void)reset; - (void)resetReadLog; - (void)resetWriteLog; @end #endif /* __WORecordRequestStream_H__ */ SOPE/sope-appserver/NGObjWeb/WOHttpAdaptor/WORequestParser.m0000644000000000000000000001654215004363604022634 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "WORequestParser.h" #include #include #include "common.h" @implementation WORequestParser static NGLogger *logger = nil; + (void)initialize { NGLoggerManager *lm; static BOOL didInit = NO; if (didInit) return; didInit = YES; lm = [NGLoggerManager defaultLoggerManager]; logger = [lm loggerForDefaultKey:@"WORequestParserDebugEnabled"]; if (!logger) { logger = [lm loggerForClass:self]; } } - (id)initWithBufferedStream:(NGBufferedStream *)_in { if (_in == nil) { [self release]; return nil; } self->in = [_in retain]; self->readByte = (void *)[self->in methodForSelector:@selector(readByte)]; return self; } - (void)dealloc { [self->lastException release]; [self->in release]; [super dealloc]; } /* parsing */ - (void)takeLastException { ASSIGN(self->lastException, [self->in lastException]); } static inline int nextChar(WORequestParser *self) { int c; if (self->pushBack != 0) { c = self->pushBack; self->pushBack = 0; return c; } if ((c = self->readByte(self->in, @selector(readByte))) < 0) [self takeLastException]; return c; } static inline int nextCharAfterSpaces(WORequestParser *self) { int c; if (self->pushBack != 0) { if (self->pushBack == ' ' || self->pushBack == '\t') self->pushBack = 0; else { c = self->pushBack; self->pushBack = 0; return c; } } do { c = self->readByte(self->in, @selector(readByte)); if (c < 0) { [self takeLastException]; return c; } } while ((c == ' ') || (c == '\t')); return c; } static inline BOOL skipSpaces(WORequestParser *self) { int c; if ((c = nextCharAfterSpaces(self)) > 0) return NO; self->pushBack = c; return YES; } - (BOOL)readCRLF { int c; c = nextChar(self); if (c < 0) return NO; if (c == '\n') return YES; if (c != '\r') return NO; c = nextChar(self); if (c < 0) return NO; if (c == '\n') return YES; return NO; } /* header line */ - (NSString *)parseMethod { unsigned count; unsigned char m[32]; int c; count = 0; for (c = nextChar(self); isalpha(c) && (count < 30); c = nextChar(self)) { m[count] = c; count++; } m[count] = '\0'; if (count == 30) { /* method name too long */ [self logWithFormat:@"method name got too long"]; return nil; } else if (count == 0) { /* method name too short */ [self logWithFormat:@"method name got too short"]; return nil; } return [NSString stringWithCString:(char *)m length:count]; } - (NSString *)parseURI { unsigned char *uri; unsigned count; NSString *s; int c; if ((c = nextCharAfterSpaces(self)) < 0) return nil; uri = calloc(4096, sizeof(unsigned char)); for (count = 0; count < 4001 && (c > 0); count++) { if (c == ' ' || c == '\t') break; if (c == '\r' || c == '\n') break; uri[count] = c; c = nextChar(self); } if (c < 0) return nil; if (count == 4001) { [self logWithFormat:@"uri got too long (max 4000 chars)"]; return nil; } /* feed last char to next parsing step */ self->pushBack = c; s = [NSString stringWithCString:(char *)uri length:count]; if (uri) free(uri); return s; } - (NSString *)parseVersion { unsigned count; unsigned char m[16]; int c; c = nextCharAfterSpaces(self); if (c == '\r' || c == '\n') { /* no version specified */ self->pushBack = c; return @"HTTP/0.9"; } count = 0; for (; isprint(c) && (count < 15); c = nextChar(self)) { m[count] = c; count++; } m[count] = '\0'; if (count == 15) { /* version too long */ [self logWithFormat:@"http version got too long"]; return nil; } else if (count == 0) { /* version too short, guessing HTTP/0.9 */ return @"HTTP/0.9"; } return [NSString stringWithCString:(char *)m length:count]; } /* headers */ - (NSDictionary *)parseHeaders { return nil; } /* body */ - (unsigned)ramDataSizeLimitation { // 64KB TODO: make default return (64 * 1064); } - (unsigned)spoolDataSizeLimitation { // 64MB TODO: make default return (64 * 1024 * 1064); } - (NSData *)readContentUntilEOF { // TODO return nil; } - (NSData *)readContentOfLength:(unsigned int)_count { if (_count == 0) { static NSData *emptyData = nil; if (emptyData == nil) emptyData = [[NSData alloc] init]; return emptyData; } if (_count <= [self ramDataSizeLimitation]) return [self->in safeReadDataOfLength:_count]; // TODO return nil; } /* full request */ - (BOOL)isContentLessMethod:(NSString *)_method { static NSMutableSet *methods = nil; if (methods == nil) { methods = [[NSMutableSet alloc] initWithObjects:nil]; } return [methods containsObject:_method]; } - (WORequest *)parseNextRequest { NSString *method, *uri, *v; NSDictionary *headers; NSData *content; WORequest *result; ASSIGN(self->lastException, (id)nil); /* request line */ if ((method = [self parseMethod]) == nil) return nil; if ((uri = [self parseURI]) == nil) return nil; if ((v = [self parseVersion]) == nil) return nil; if (![self readCRLF]) return nil; [self debugWithFormat:@"stage 1: method=%@ uri=%@ version=%@", method, uri, v]; /* headers */ if ((headers = [self parseHeaders]) == nil) return nil; /* body */ if (![self isContentLessMethod:method]) { unsigned int clen; if ((clen = [[headers objectForKey:@"content-length"] intValue])) { content = [self readContentOfLength:clen]; } else { /* Two cases: HTTP/1.0, HTTP/0.9 - read till EOF if no content-length is set HTTP/1.1 and above: if no content-length is set, body is empty */ if ([v hasPrefix:@"HTTP/0"]) content = [self readContentUntilEOF]; else if ([v hasPrefix:@"HTTP/1.0"]) content = [self readContentUntilEOF]; else content = nil; } } else content = nil; /* construct */ result = [[WORequest alloc] initWithMethod:method uri:uri httpVersion:v headers:headers content:content userInfo:nil]; return [result autorelease]; } - (NSException *)lastException { return self->lastException; } /* logging */ - (id)logger { return logger; } - (NSString *)loggingPrefix { return @"[http-parser]"; } - (BOOL)isDebuggingEnabled { static int debugOn = -1; if (debugOn == -1) { debugOn = [[NSUserDefaults standardUserDefaults] boolForKey:@"WORequestParserDebugEnabled"] ? 1 : 0; } return debugOn ? YES : NO; } @end /* WORequestParser */ SOPE/sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m0000644000000000000000000007725115004363604023160 0ustar rootroot/* Copyright (C) 2000-2008 SKYRIX Software AG Copyright (C) 2008 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "WOHttpTransaction.h" #include "WORecordRequestStream.h" #include "WOHttpAdaptor.h" #include "WORequest+Adaptor.h" #include "NGHttp+WO.h" #include "WOSimpleHTTPParser.h" #include #include #include #include #include #include #include #include #include "common.h" #include #include #include @interface WORequest(UsedPrivates) - (NSCalendarDate *)startDate; - (id)startStatistics; @end int WOAsyncResponseStatus = 20001; NSString *WOAsyncResponseTokenKey = @"WOAsyncResponseToken"; NSString *WOAsyncResponseReadyNotificationName = @"WOAsyncResponseReadyNotification"; NSString *WOAsyncResponse = @"WOAsyncResponse"; static BOOL WOHttpAdaptor_LogStream = NO; @interface WOCoreApplication(SimpleParserSelection) - (BOOL)shouldUseSimpleHTTPParserForTransaction:(id)_tx; @end @implementation WOHttpTransaction static NSMutableDictionary *pendingTransactions = nil; // THREAD static BOOL useSimpleParser = YES; static int doCore = -1; static BOOL capitalizeHeaders = YES; static NSString *adLogPath = nil; static NGLogger *debugLogger = nil; static NGLogger *perfLogger = nil; static NGLogger *transActionLogger = nil; static NSDictionary *standardCapitalizedHeaders = nil; + (void)initialize { NSUserDefaults *ud; NGLoggerManager *lm; static BOOL didInit = NO; if (didInit) return; didInit = YES; lm = [NGLoggerManager defaultLoggerManager]; perfLogger = [lm loggerForDefaultKey:@"WOProfileHttpAdaptor"]; debugLogger = [lm loggerForDefaultKey:@"WODebugHttpTransaction"]; transActionLogger = [lm loggerForClass:self]; ud = [NSUserDefaults standardUserDefaults]; useSimpleParser = [ud boolForKey:@"WOHttpTransactionUseSimpleParser"]; doCore = [[ud objectForKey:@"WOCoreOnHTTPAdaptorException"] boolValue]?1:0; capitalizeHeaders = [[ud objectForKey:@"WOHTTPAdaptorCapitalizeHeaders"] boolValue]; WOHttpAdaptor_LogStream = [ud boolForKey:@"WOHttpAdaptor_LogStream"]; adLogPath = [[ud stringForKey:@"WOAdaptorLogPath"] copy]; if (adLogPath == nil) adLogPath = @""; standardCapitalizedHeaders = [NSDictionary dictionaryWithObjectsAndKeys: @"ETag", @"etag", @"MS-Server-ActiveSync", @"ms-server-activesync", @"MS-ASProtocolVersions", @"ms-asprotocolversions", @"MS-ASProtocolCommands", @"ms-asprotocolcommands", nil]; [standardCapitalizedHeaders retain]; } - (BOOL)optionLogStream { return WOHttpAdaptor_LogStream; } - (BOOL)optionLogPerf { return perfLogger ? YES : NO; } - (BOOL)isDebuggingEnabled { return debugLogger ? YES : NO; } - (id)initWithSocket:(id)_socket application:(WOCoreApplication *)_app { NSAssert(_socket, @"missing socket ..."); NSAssert(_app, @"missing application ..."); self->socket = [_socket retain]; self->application = [_app retain]; if ([[_app recordingPath] length] > 0) WOHttpAdaptor_LogStream = YES; return self; } - (void)dealloc { #if 0 [self debugWithFormat:@"dealloc ..."]; #endif [self reset]; [self->socket release]; [self->lastException release]; [self->application release]; [super dealloc]; } /* state management */ - (void)reset { if (self->asyncResponseToken) { [self warnWithFormat: @"resetting while async response pending ... (%@)", self->asyncResponseToken]; abort(); [[self notificationCenter] removeObserver:self]; } [self->asyncResponseToken release]; self->asyncResponseToken = nil; [self->io release]; self->io = nil; [self->log release]; self->log = nil; [self->startDate release]; self->startDate = nil; [self->woRequest release]; self->woRequest = nil; [self->woResponse release]; self->woResponse = nil; } - (BOOL)closeConnectionAfterDelivery { return YES; } - (void)start { self->startDate = [[NSDate alloc] init]; self->t = [self->startDate timeIntervalSince1970]; } - (void)finish { if (self->woResponse == nil) return; [self logResponse:self->woResponse toRequest:self->woRequest connection:self->socket]; if (perfLogger) { struct timeval tv; gettimeofday(&tv, NULL); self->t = (((double)tv.tv_sec) + ((double)tv.tv_usec) / 1000000.0) - self->t; [perfLogger logWithFormat:@"processing of request took %4.3fs.", self->t < 0.0 ? -self->t : self->t]; } } - (BOOL)_setupStreamsForSocket { if ([self optionLogStream]) { self->log = [(WORecordRequestStream *)[WORecordRequestStream alloc] initWithSource:self->socket]; self->io = [(NGBufferedStream *)[NGBufferedStream alloc] initWithSource:self->log]; } else { self->log = nil; self->io = [(NGBufferedStream *)[NGBufferedStream alloc] initWithSource:self->socket]; } return self->io != nil ? YES : NO; } static int logCounter = 0; - (NSString *)currentRecordingPath:(NSString *)_suffix { static NSString *s = nil; NSString *p; if (s == nil) { s = [[self->application recordingPath] copy]; if (s == nil) s = @""; } if ([s length] == 0) return nil; p = [NSString stringWithFormat:@"%04i-%@", logCounter, _suffix]; return [s stringByAppendingPathComponent:p]; } - (void)logRequestData:(NSData *)_data { NSString *logPath = nil; if (![self optionLogStream]) return; logCounter++; if ([adLogPath length] > 0) logPath = adLogPath; else if ([logPath length] == 0) logPath = [self currentRecordingPath:@"request"]; if ([logPath length] == 0) logPath = @"/tmp/woadaptor.log"; [_data writeToFile:logPath atomically:NO]; #if 1 NSLog(@"request is\n"); fflush(stderr); fwrite([_data bytes], 1, [_data length], stderr); fflush(stderr); fprintf(stderr,"\n"); fflush(stderr); #endif } - (void)logResponse:(WOResponse *)_response toRequest:(WORequest *)_request data:(NSData *)_data { NSString *logPath; if (_data == nil) return; if ((int)[_response status] == (int)WOAsyncResponseStatus) return; #if 1 NSLog(@"response is\n"); fflush(stderr); fwrite([_data bytes], 1, [_data length], stderr); fflush(stderr); fprintf(stderr,"\n"); fflush(stderr); #endif if ((logPath = [self currentRecordingPath:@"response"]) == nil) return; [_data writeToFile:logPath atomically:NO]; } - (void)applyAdaptorHeadersWithHttpRequest:(NGHttpRequest *)request { /* apply some adaptor headers in direct-connect mode */ if (woRequest == nil) return; if ([woRequest headerForKey:@"x-webobjects-server-url"] == nil) { NSString *tmp; if ((tmp = [woRequest headerForKey:@"host"])) { if ([tmp hasSuffix:@":0"] && ([tmp length] > 2)) // TODO: bad bad bad tmp = [tmp substringToIndex:([tmp length] - 2)]; tmp = [@"http://" stringByAppendingString:tmp]; [woRequest setHeader:tmp forKey:@"x-webobjects-server-url"]; } } if ([woRequest headerForKey:@"x-webobjects-server-name"] == nil) { NSString *tmp; if ((tmp = [woRequest headerForKey:@"host"])) { NSRange r = [tmp rangeOfString:@":"]; if (r.length > 0) tmp = [tmp substringToIndex:r.location]; [woRequest setHeader:tmp forKey:@"x-webobjects-server-name"]; } } if ([[woRequest headerForKey:@"x-webobjects-server-port"] intValue] < 1) { id tmp; if ((tmp = [woRequest headerForKey:@"host"])) { NSRange r = [tmp rangeOfString:@":"]; if (r.length > 0) tmp = [tmp substringFromIndex:r.location + r.length]; tmp = [NSNumber numberWithInt:[tmp intValue]]; [woRequest setHeader:tmp forKey:@"x-webobjects-server-port"]; } } if ([woRequest headerForKey:@"x-webobjects-remote-host"] == nil) { id remote = nil; NSString *remoteHost = nil; /* Use de facto standard headers if remote-host is not set * before falling back to the remote end of the socket */ if ([woRequest headerForKey:@"x-forward"]) { remoteHost = [woRequest headerForKey:@"x-forward"]; } else if ([woRequest headerForKey:@"x-forwarded-for"]) { remoteHost = [woRequest headerForKey:@"x-forwarded-for"]; } else { remote = [self->socket remoteAddress]; if ([remote isKindOfClass:[NGInternetSocketAddress class]]) remoteHost = [(NGInternetSocketAddress *)remote hostName]; #if !defined(__MINGW32__) else if ([remote isKindOfClass:[NGLocalSocketAddress class]]) remoteHost = @"local"; #endif } if ([remoteHost length] > 0) [woRequest setHeader:remoteHost forKey:@"x-webobjects-remote-host"]; } if ([woRequest headerForKey:@"x-webobjects-remote-user"] == nil) { id auth; auth = [[request valuesOfHeaderFieldWithName:@"authorization"] nextObject]; if (auth) { if (![auth isKindOfClass:[NGHttpCredentials class]]) { auth = [NGHttpCredentials credentialsWithString:[auth stringValue]]; } if ([auth userName]) [woRequest setHeader:[auth userName] forKey:@"x-webobjects-remote-user"]; if ([auth scheme]) [woRequest setHeader:[auth scheme] forKey:@"x-webobjects-auth-type"]; } } } - (WOResponse *)generateMissingResponse { WOResponse *mr; NSString *accept; mr = [WOResponse alloc]; mr = [mr initWithRequest:self->woRequest]; [mr setHTTPVersion:[woRequest httpVersion]]; [mr setStatus:500]; accept = [woRequest headerForKey:@"accept"]; if ([accept rangeOfString:@"text/html"].length > 0) { const char *txt = "could not perform request !
    "; [mr setHeader:@"text/html" forKey:@"content-type"]; [mr setContent:[NSData dataWithBytes:txt length:strlen(txt)]]; } return [mr autorelease]; } - (BOOL)_readRequest { id request = nil; if (self->woRequest) [self warnWithFormat:@"woRequest already set ???"]; if ([self->application shouldUseSimpleHTTPParserForTransaction:self]) { WOSimpleHTTPParser *parser; parser = [[WOSimpleHTTPParser alloc] initWithStream:self->io]; self->woRequest = [[parser parseRequest] retain]; if (self->woRequest == nil) { ASSIGN(self->lastException, [parser lastException]); [self errorWithFormat:@"failed to parse request: %@", self->lastException]; } [parser release]; } else { if ((request = [self parseRequestFromStream:self->io]) == nil) return NO; #if DEBUG NSAssert([request isKindOfClass:[NGHttpRequest class]], @"invalid request class"); #endif self->woRequest = [[request woRequest] retain]; } [self logRequestData:[log readLog]]; [log resetReadLog]; if ([self->woRequest isCodeRedAttack]) { [self logWithFormat: @"WOHttpAdaptor: detected 'Code Red' request: '%@', blocking.", [self->woRequest uri]]; ASSIGN(self->woRequest, (id)nil); return NO; } [self->woRequest takeStartDate:self->startDate]; /* apply some adaptor headers in direct-connect mode */ [self applyAdaptorHeadersWithHttpRequest:request]; if (perfLogger) { NSTimeInterval rt; self->requestFinishTime = [[NSDate date] timeIntervalSince1970]; rt = self->requestFinishTime - self->t; [perfLogger logWithFormat:@"decoding of request took %4.3fs.", rt < 0.0 ? -1.0 : rt]; } return self->woRequest ? YES : NO; } - (BOOL)_sendResponse { if (perfLogger) { NSTimeInterval rt; self->dispatchFinishTime = [[NSDate date] timeIntervalSince1970]; rt = self->dispatchFinishTime - self->requestFinishTime; [perfLogger logWithFormat:@"dispatch of request took %4.3fs.", rt < 0.0 ? -1.0 : rt]; } if (self->woResponse != nil) { [self deliverResponse:self->woResponse toRequest:self->woRequest onStream:self->io]; if (perfLogger) { NSTimeInterval rt; rt = [[NSDate date] timeIntervalSince1970] - dispatchFinishTime; [perfLogger logWithFormat:@"delivery of request took %4.3fs.", rt < 0.0 ? -1.0 : rt]; } } else if (self->woRequest != nil) { [self errorWithFormat:@"got no response for request %@ ..", self->woRequest]; self->woResponse = [[self generateMissingResponse] retain]; [self deliverResponse:self->woResponse toRequest:self->woRequest onStream:self->io]; } if (![self->io flush]) { ASSIGN(self->lastException, [self->io lastException]); return NO; } if ([self closeConnectionAfterDelivery]) { [self debugWithFormat:@"close connection: %@", self->io]; if (![self->io close]) { ASSIGN(self->lastException, [self->io lastException]); [self debugWithFormat:@"close failed: %@", self->lastException]; return NO; } } else [self debugWithFormat:@"not closing connection ..."]; return YES; } - (NSNotificationCenter *)notificationCenter { return [NSNotificationCenter defaultCenter]; } - (void)responseReady:(NSNotification *)_notification { WOResponse *response; if ([self->asyncResponseToken length] == 0) { [self errorWithFormat: @"got response ready notification (%@), " @"but no async HTTP transaction is in progress ...", _notification]; return; } if (![self->asyncResponseToken isEqual:[_notification object]]) { [self errorWithFormat: @"got response ready notification (%@) for a different " @"token (%@ vs %@) !", _notification, self->asyncResponseToken, [_notification object]]; return; } /* OK, everything seems to be correct, so we received a response .. */ [[self retain] autorelease]; [pendingTransactions removeObjectForKey:self->asyncResponseToken]; response = [[_notification userInfo] objectForKey:WOAsyncResponse]; ASSIGN(self->woResponse, response); [[self notificationCenter] removeObserver:self]; [self->asyncResponseToken release]; self->asyncResponseToken = nil; /* send response */ [self debugWithFormat:@"sending async response: %@", self->woResponse]; [self _sendResponse]; [self debugWithFormat:@"logging async response: %@", self->woResponse]; [self logResponse:self->woResponse toRequest:self->woRequest data:[log writeLog]]; [log resetWriteLog]; [self finish]; [self reset]; [self->io release]; self->io = nil; [self->log release]; self->log = nil; } - (BOOL)_enterAsyncMode:(WOResponse *)_response { NSString *token; [self debugWithFormat:@"enter async mode ..."]; if (pendingTransactions == nil) pendingTransactions = [[NSMutableDictionary alloc] initWithCapacity:16]; [self debugWithFormat:@"PENDING: %@", pendingTransactions]; NSAssert1((int)[_response status] == (int)WOAsyncResponseStatus, @"passed in an invalid response %@ ...", _response); token = [[_response userInfo] objectForKey:WOAsyncResponseTokenKey]; if ([token length] == 0) { [self errorWithFormat:@"missing async response token in response %@", _response]; return NO; } [self debugWithFormat:@"using token: %@", token]; ASSIGN(self->asyncResponseToken, token); [pendingTransactions setObject:self forKey:self->asyncResponseToken]; [[self notificationCenter] addObserver:self selector:@selector(responseReady:) name:WOAsyncResponseReadyNotificationName object:self->asyncResponseToken]; return YES; } - (BOOL)_run { if (![self _setupStreamsForSocket]) return NO; if (![self _readRequest]) return NO; /* dispatch request */ if (self->woRequest) self->woResponse = [[self->application dispatchRequest:woRequest] retain]; else self->woResponse = nil; if (self->woResponse) { if ((int)[self->woResponse status] == (int)WOAsyncResponseStatus) { /* switch to async mode ... */ if ([self _enterAsyncMode:self->woResponse]) { [self logResponse:self->woResponse toRequest:self->woRequest data:nil]; return YES; } } } /* send response */ [self _sendResponse]; [self logResponse:self->woResponse toRequest:self->woRequest data:[self->log writeLog]]; [self->log resetWriteLog]; [self->io release]; self->io = nil; [self->log release]; self->log = nil; return YES; } - (NSException *)lastException { return self->lastException; } - (BOOL)_catchedException:(NSException *)localException { if ([localException isKindOfClass:[NGSocketShutdownException class]]) return YES; ASSIGN(self->lastException, localException); #if DEBUG if (doCore) abort(); #endif return NO; } - (BOOL)run { BOOL ok = YES; [self reset]; [self start]; NS_DURING { if (![self _run]) ok = NO; } NS_HANDLER ok = [self _catchedException:localException]; NS_ENDHANDLER; if (self->asyncResponseToken == nil) { [self finish]; [self reset]; } return ok; } - (NGHttpRequest *)parseRequestFromStream:(id)_in { NGHttpMessageParser *parser = nil; volatile id request = nil; NSString *format = @"parsing of request failed with exception: %@"; NS_DURING { *(&parser) = [[NGHttpMessageParser alloc] init]; [parser setDelegate:self]; request = [parser parseRequestFromStream:_in]; [parser release]; parser = nil; } NS_HANDLER { [self errorWithFormat:format, localException]; [parser release]; parser = nil; [localException raise]; } NS_ENDHANDLER; return request; } - (const unsigned char *)_reasonForStatus:(unsigned int)_status { const char *reason; switch (_status) { case 200: reason = "OK"; break; case 201: reason = "Created"; break; case 204: reason = "No Content"; break; case 207: reason = "Multi-Status"; break; case 302: reason = "Found"; break; case 304: reason = "Not Modified"; break; case 401: reason = "Authorization Required"; break; case 402: reason = "Payment Required"; break; case 403: reason = "Forbidden"; break; case 404: reason = "Not Found"; break; case 405: reason = "Method Not Allowed"; break; case 409: reason = "Conflict"; break; case 412: reason = "Precondition Failed"; break; case 415: reason = "Unsupported Media Type"; break; case 424: reason = "Failed Dependency"; break; case 507: reason = "Insufficient Storage"; break; default: if (_status < 300) reason = "Request Was Successful"; else reason = "Request Failed"; break; } return (const unsigned char *) reason; } - (void)_httpValidateResponse:(WOResponse *)_response { /* check HTTP validity */ if ([_response status] == NGHttpStatusCode_Unauthorized) { if ([_response headerForKey:@"www-authenticate"] == nil) { [self warnWithFormat: @"response is %i, but no www-authenticate header is set.", NGHttpStatusCode_Unauthorized]; } } } - (void)deliverResponse:(WOResponse *)_response toRequest:(WORequest *)_request onStream:(id)_out { /* Profiling OSX: - takes 29% of tx -run 12% CTextStream writeString ... to sendto 5.1% (half+ of the performance lost on the way) 4.6% WOMessage headersForKey 4.4% TextStream writeFormat => TODO(perf) reduce usage of writeFormat/writeString */ NGCTextStream *out; static NSString *disconnectError = @"client disconnected during delivery of response for %@ (len=%i): %@"; static NSString *deliveryError = @"delivering of response failed with exception: %@"; *(&out) = nil; [self _httpValidateResponse:_response]; out = [(NGCTextStream *)[NGCTextStream alloc] initWithSource:_out]; NS_DURING { unsigned char buf[1024]; NSString *t1; id body; BOOL doZip; BOOL isok = YES; int length; NSFileHandle *contentFile; doZip = [_response shouldZipResponseToRequest:_request]; /* response line */ if (isok) { unsigned int slen, rlen; const unsigned char *r; int s, size; s = [_response status]; t1 = [_response httpVersion]; r = [self _reasonForStatus:s]; // TBD: replace -cStringLength/-getCString: slen = [t1 cStringLength]; rlen = strlen((const char *)r); size = 8 + rlen; // Size of status (e.g. : 200 OK \r\n) - 1 space, 3 digits for status code, 1 space, X for status, 2 end of line, 1 for zero-byte if ((slen + size) < sizeof(buf)) { [t1 getCString:(char *)buf]; // HTTP status snprintf((char *)&(buf[slen]), size, " %i %s\r\n", s, r); isok = [_out safeWriteBytes:buf count:strlen((char *)buf)]; } else isok = [out writeFormat:@"%@ %i %s\r\n", t, s, r]; } if (isok) isok = [out flush]; contentFile = [_response contentFile]; if (contentFile != nil) { length = [contentFile seekToEndOfFile]; doZip = NO; } else { /* zip */ body = (doZip) ? [_response zipResponse] : [_response content]; /* add content length header */ if ((length = [body length]) == 0 && ![[_response headerForKey: @"content-type"] hasPrefix:@"text/plain"] && ![[_response headerForKey: @"content-type"] hasPrefix:@"application/vnd.ms-sync.wbxml"]) { [_response setHeader:@"text/plain" forKey:@"content-type"]; } } snprintf((char *)buf, sizeof(buf), "%d", length); t1 = [[NSString alloc] initWithCString:(char *)buf]; [_response setHeader:t1 forKey:@"content-length"]; [t1 release]; t1 = nil; /* write headers */ if (isok) { /* collect in string to reduce string IO */ NSEnumerator *fields; NSString *fieldName; NSMutableString *header; BOOL hasConnectionHeader; IMP addStr; #if HEAVY_DEBUG NSLog(@"DELIVER: %@", _response); #endif hasConnectionHeader = NO; header = [[NSMutableString alloc] initWithCapacity:4096]; addStr = [header methodForSelector:@selector(appendString:)]; fields = [[_response headerKeys] objectEnumerator]; while ((fieldName = [fields nextObject]) && isok) { NSEnumerator *values; NSString *value; if (!hasConnectionHeader) { if ([fieldName isEqualToString:@"connection"]) hasConnectionHeader = YES; } #if HEAVY_DEBUG NSLog(@" FIELD: %@", fieldName); #endif values = [[_response headersForKey:fieldName] objectEnumerator]; while ((value = [values nextObject]) && isok) { #if HEAVY_DEBUG NSLog(@" VAL: %@", value); #endif if ([standardCapitalizedHeaders objectForKey: fieldName]) { addStr(header, @selector(appendString:), [standardCapitalizedHeaders objectForKey: fieldName]); } else { addStr(header, @selector(appendString:), capitalizeHeaders ? [fieldName asCapitalizedHeader] : fieldName); } addStr(header, @selector(appendString:), @": "); addStr(header, @selector(appendString:), value); addStr(header, @selector(appendString:), @"\r\n"); } #if HEAVY_DEBUG NSLog(@" END: %@", fieldName); #endif } #if HEAVY_DEBUG NSLog(@" HEADER:\n%@", header); NSLog(@" OUT: %@", out); #endif isok = [out writeString:header]; [header release]; header = nil; #if 0 #warning TODO: experimental, need to check for direct connect if (!hasConnectionHeader && isok) isok = [out writeString:@"connection: close\r\n"]; #endif } #if HEAVY_DEBUG else { NSLog(@"NOT OK TO DELIVER HEADERS ..."); } #endif /* write cookie headers */ if (isok) { NSEnumerator *cookies; WOCookie *cookie; cookies = [[_response cookies] objectEnumerator]; while ((cookie = [cookies nextObject]) && isok) { unsigned clen; t1 = [cookie stringValue]; clen = [t1 cStringLength]; if (isok) isok = [_out safeWriteBytes:"set-cookie: " count:12]; if (isok) { if (clen > 1000) isok = [out writeString:t1]; else { [t1 getCString:(char *)buf]; [_out safeWriteBytes:buf count:clen]; } } if (isok) isok = [_out safeWriteBytes:"\r\n" count:2]; } } if (isok) isok = [_out safeWriteBytes:"\r\n" count:2]; if (isok) isok = [out flush]; /* write body */ if (![[_request method] isEqualToString:@"HEAD"] && isok) { if (contentFile != nil && isok) { char buffer[8192]; int count; int fd = [contentFile fileDescriptor]; lseek(fd, 0, SEEK_SET); while (isok && (count = read(fd, buffer, 8192)) > 0) { isok = [_out safeWriteBytes: buffer count: count]; } isok = isok && (count == 0) && [_out flush]; [contentFile closeFile]; } else if ((body != nil) && isok) { if (![body isKindOfClass:[NSData class]]) { if (![body isKindOfClass:[NSString class]]) body = [body description]; body = [body dataUsingEncoding:[_response contentEncoding] allowLossyConversion:NO]; } isok = [_out safeWriteBytes:[body bytes] count:[body length]]; if (isok) isok = [_out flush]; } } if (!isok) { NSException *e; e = [out lastException]; if ([e isKindOfClass:[NGSocketShutdownException class]]) { [self errorWithFormat:disconnectError, _request, [[_response content] length], [e reason]]; } else [e raise]; } } NS_HANDLER { if ([localException isKindOfClass:[NGSocketShutdownException class]]) { [self errorWithFormat:disconnectError, _request, [[_response content] length], [localException reason]]; } else { [self errorWithFormat:deliveryError, localException]; [out release]; out = nil; // the buffer will be flushed .. [localException raise]; } } NS_ENDHANDLER; [out release]; out = nil; // the buffer will be flushed .. } static __inline__ const char *monthAbbr(int m) { switch (m) { case 1: return "Jan"; case 2: return "Feb"; case 3: return "Mar"; case 4: return "Apr"; case 5: return "May"; case 6: return "Jun"; case 7: return "Jul"; case 8: return "Aug"; case 9: return "Sep"; case 10: return "Oct"; case 11: return "Nov"; case 12: return "Dec"; default: return "UNKNOWN MONTH !"; } } - (void)logResponse:(WOResponse *)_response toRequest:(WORequest *)_request connection:(id)_connection { /* NOTE: *obsoleted profiling information* TODO: update profiling info! (left the old one for comparison) Profiling: this method takes 0.95% of -run if the output is piped to /dev/null on OSX, morphing caldate to string is 0.79% of that. */ static BOOL doExtLog = YES; NSString *remoteHost; NSNumber *zippedLen; NSCalendarDate *now; NSDate *lstartDate; NSDictionary *startStats; NSMutableString *buf; lstartDate = [_request startDate]; startStats = [_request startStatistics]; zippedLen = [[_response userInfo] objectForKey:@"WOResponseZippedLength"]; // host and date if ((remoteHost = [_request headerForKey:@"x-webobjects-remote-host"])) ; else if ((remoteHost = [_request headerForKey:@"x-webobjects-remote-addr"])) ; else { id remote = nil; remote = [_connection remoteAddress]; if ([remote isKindOfClass:[NGInternetSocketAddress class]]) remoteHost = [(NGInternetSocketAddress *)remote hostName]; #if !defined(__MINGW32__) else if ([remote isKindOfClass:[NGLocalSocketAddress class]]) remoteHost = @"local"; #endif } // this is supposed to be in GMT ! TODO: explicitly set GMT now = [NSCalendarDate calendarDate]; buf = [[NSMutableString alloc] initWithCapacity:160]; /* 2 terminal lines */ /* append standard info */ [buf appendString:remoteHost]; [buf appendString: @" \""]; [buf appendString:[_request method]]; [buf appendString:@" "]; [buf appendString:[_request uri]]; [buf appendString:@" "]; [buf appendString:[_request httpVersion]]; [buf appendString:@"\" "]; [buf appendFormat:@"%i %i", [_response status], (int)[[_response content] length]]; if (doExtLog) [buf appendFormat:@"/%i", (int)[[_request content] length]]; /* append duration */ if (lstartDate != nil) [buf appendFormat:@" %.3f", [now timeIntervalSinceDate:lstartDate]]; else [buf appendString:@" -"]; /* append zip level */ if (zippedLen) { double p; double unzippedLen; unzippedLen = [[[_response userInfo] objectForKey:@"WOResponseUnzippedLength"] unsignedIntValue]; [buf appendFormat:@" %d", (unsigned int)unzippedLen]; if ([zippedLen unsignedIntValue] == unzippedLen) { [buf appendString:@" -"]; } else { p = unzippedLen / 100.0; // one percent p = [zippedLen doubleValue] / p; p = 100.0 - p; [buf appendFormat:@" %-2d%%", (unsigned int)p]; } } else { /* content was not zipped */ [buf appendString:@" - -"]; } /* append statistics */ if (startStats) { static NSProcessInfo *pi = nil; NSDictionary *currentStats; if (pi == nil) pi = [[NSProcessInfo processInfo] retain]; if ((currentStats = [pi procStatDictionary])) { int old, new, diff; old = [[startStats objectForKey:@"rss"] intValue]; new = [[currentStats objectForKey:@"rss"] intValue]; diff = new - old; /* number of pages (4KB on ix86 ..) */ diff *= 4; /* in KB */ if (diff == 0) [buf appendString:@" 0"]; else if (diff > 999) [buf appendFormat:@" %iM", diff / 1024]; else [buf appendFormat:@" %iK", diff]; [buf appendFormat:@" - %i", [pi fileDescriptorCount]]; } else [buf appendString:@" ?"]; } else [buf appendString:@" -"]; [transActionLogger logLevel:NGLogLevelInfo message:buf]; [buf release]; } /* NGHttpMessageParserDelegate */ - (BOOL)httpParserWillParseRequest:(NGHttpMessageParser *)_parser { return YES; } - (void)httpParser:(NGHttpMessageParser *)_parser didParseRequest:(NGHttpRequest *)_request { } - (BOOL)parser:(NGMimePartParser *)_parser keepHeaderField:(NSString *)_name value:(id)_value { return YES; } - (void)parser:(NGMimePartParser *)_parser didParseHeader:(NGHashMap *)_header { } - (NGMimeType *)parser:(id)_parser contentTypeOfPart:(id)_part { return [NGMimeType mimeType: @"text/plain; charset=utf-8"]; } @end /* WOHttpAdaptor */ @implementation WOCoreApplication(SimpleParserSelection) - (BOOL)shouldUseSimpleHTTPParserForTransaction:(id)_tx { return useSimpleParser; } @end /* WOCoreApplication(SimpleParserSelection) */ SOPE/sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpAdaptor.h0000644000000000000000000000275415004363604022254 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __WOHttpAdaptor_H__ #define __WOHttpAdaptor_H__ #include #import #import #include @class NSMutableArray; @class NGActiveSocket; @interface WOHttpAdaptor : WOAdaptor { @protected id socket; NGActiveSocket *controlSocket; NSTimeInterval sendTimeout; NSTimeInterval receiveTimeout; unsigned short maxThreadCount; unsigned short activeThreadCount; id lock; BOOL isTerminated; id address; NSMutableArray *delayedResponses; } + (BOOL)optionLogPerf; @end #endif /* __WOHttpAdaptor_H__ */ SOPE/sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.h0000644000000000000000000000561115004363604023142 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __WOHttpTransaction_H__ #define __WOHttpTransaction_H__ #import #import #include #include @class NSException, NSNotificationCenter; @class NGHttpRequest; @class WOCoreApplication, WORequest, WOResponse; @class WORecordRequestStream; /* This object represents a single HTTP transaction (request+response). Note that multiple HTTP transactions can be active at a single point of time, this isn't done by threading, but by using the runloop. Since WOApplications are synchronous by nature, we define a "special" HTTP response with status code "20001" meaning "response not yet ready". If the transaction gets this response, it puts itself into a pending state and waits for a notification targetting the async-object token given in the user-info of the response. (Eg this is used in the skysystemd to be able to fork and process multiple system commands at the same time) */ extern int WOAsyncResponseStatus; extern NSString *WOAsyncResponseTokenKey; extern NSString *WOAsyncResponseReadyNotificationName; @interface WOHttpTransaction : NSObject { @public WOCoreApplication *application; id socket; WORecordRequestStream *log; NGBufferedStream *io; WORequest *woRequest; WOResponse *woResponse; NSTimeInterval t; NSDate *startDate; NSException *lastException; NSTimeInterval requestFinishTime; NSTimeInterval dispatchFinishTime; NSString *asyncResponseToken; } - (id)initWithSocket:(id)_socket application:(WOCoreApplication *)_app; - (void)reset; /* running */ - (NSException *)lastException; - (BOOL)run; - (NSNotificationCenter *)notificationCenter; /* event handler stuff */ - (NGHttpRequest *)parseRequestFromStream:(id)_in; - (void)deliverResponse:(WOResponse *)_response toRequest:(WORequest *)_request onStream:(id)_out; - (void)logResponse:(WOResponse *)_response toRequest:(WORequest *)_request connection:(id)_connection; @end #endif /* __WOHttpTransaction_H__ */ SOPE/sope-appserver/NGObjWeb/WOHttpAdaptor/WORequestParser.h0000644000000000000000000000364415004363604022626 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __WOHttpAdaptor_WORequestParser_H__ #define __WOHttpAdaptor_WORequestParser_H__ #import /* WORequestParser (NOT FINISHED YET) A specialized parser for WO HTTP requests. It has some advanced features like streaming large request bodies to disk and mapping them into memory instead of keeping the whole thing in memory all the time. It also correctly works with HTTP methods that have no content-length specified (the NGHttpParser tries to parse till EOF by default). Note: since the parser keep transient state in the ivars, you need to have at least one parser per thread when running in a multithreaded environment. Note: if parsing fails you *need* to close the socket connection ! */ @class NSException; @class NGBufferedStream; @class WORequest; @interface WORequestParser : NSObject { NGBufferedStream *in; NSException *lastException; int (*readByte)(id,SEL); /* transient */ unsigned char pushBack; } - (id)initWithBufferedStream:(NGBufferedStream *)_in; /* parsing */ - (WORequest *)parseNextRequest; - (NSException *)lastException; @end #endif /* __WOHttpAdaptor_WORequestParser_H__ */ SOPE/sope-appserver/NGObjWeb/WOHttpAdaptor/GNUmakefile.preamble0000644000000000000000000000042215004363604023231 0ustar rootroot# compiler flags ADDITIONAL_CPPFLAGS += -pipe -Wall ADDITIONAL_CPPFLAGS += -DCOMPILING_NGOBJWEB=1 WOHttpAdaptor_INCLUDE_DIRS += \ -I.. -I. -I../.. \ -I../../../sope-core \ -I../../../sope-core/NGStreams \ -I../../../sope-core/NGExtensions \ -I../../../sope-mime SOPE/sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpAdaptor.m0000644000000000000000000003615715004363604022265 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include "common.h" #include "WORunLoop.h" #include "NGHttp+WO.h" //#define USE_POOLS 1 #if USE_POOLS # warning extensive pools are enabled ... #endif #include "WOHttpAdaptor.h" #include "WORecordRequestStream.h" #include "WOHttpTransaction.h" #include #include #include void handle_SIGPIPE(int signum) { NSLog(@"caught SIGPIPE - ignoring!"); } @interface WOHttpAdaptor(Server) /* accessors */ - (id)socket; - (id)serverAddress; - (void)setSendTimeout:(NSTimeInterval)_timeout; - (NSTimeInterval)sendTimeout; - (void)setReceiveTimeout:(NSTimeInterval)_timeout; - (NSTimeInterval)receiveTimeout; @end /* WOHttpAdaptor */ @interface WOCoreApplication(Port) - (NSNumber *)port; @end @implementation WOHttpAdaptor static NGLogger *logger = nil; static NGLogger *perfLogger = nil; static BOOL WOCoreOnHTTPAdaptorException = NO; static int WOHttpAdaptorSendTimeout = 10; static int WOHttpAdaptorReceiveTimeout = 10; static BOOL debugOn = NO; + (BOOL)optionLogPerf { return perfLogger != nil ? YES : NO; } + (void)initialize { NSUserDefaults *ud; NGLoggerManager *lm; static BOOL didInit = NO; if (didInit) return; didInit = YES; ud = [NSUserDefaults standardUserDefaults]; lm = [NGLoggerManager defaultLoggerManager]; logger = [lm loggerForClass:self]; perfLogger = [lm loggerForDefaultKey:@"WOProfileHttpAdaptor"]; WOCoreOnHTTPAdaptorException = [[ud objectForKey:@"WOCoreOnHTTPAdaptorException"] boolValue] ? 1 : 0; WOHttpAdaptorSendTimeout = [ud integerForKey:@"WOHttpAdaptorSendTimeout"]; WOHttpAdaptorReceiveTimeout = [ud integerForKey:@"WOHttpAdaptorReceiveTimeout"]; if (WOCoreOnHTTPAdaptorException) [logger warnWithFormat:@"will dump core on HTTP adaptor exception!"]; } - (id)autoBindAddress { NGInternetSocketAddress *addr; addr = [[NGInternetSocketAddress alloc] initWithPort:0 onHost:@"127.0.0.1"]; return [addr autorelease]; } - (void)_registerForSignals { signal(SIGPIPE, handle_SIGPIPE); } - (id)addressFromDefaultsOfApplication:(WOCoreApplication*)_a{ id woport; id lAddress = nil; const char *cstr; woport = [[NSUserDefaults standardUserDefaults] stringForKey:@"WOPort"]; if ([woport isEqualToString:@"auto"]) { if ((lAddress = [self autoBindAddress]) != nil) return lAddress; } if ((cstr = [woport cString]) != NULL) { if (isdigit(*cstr) && index(cstr, ':') == NULL) { NSNumber *p; p = [(WOCoreApplication *)[_a class] port]; if (p == nil) p = (id)woport; lAddress = [NGInternetSocketAddress wildcardAddressWithPort:[p intValue]]; if (lAddress != nil) return lAddress; } } return NGSocketAddressFromString(woport); } - (id)addressFromArguments:(NSDictionary *)_args { id lAddress = nil; NSString *arg = nil; const char *cstr; if ((arg = [_args objectForKey:@"-p"]) != nil) return [NGInternetSocketAddress wildcardAddressWithPort:[arg intValue]]; if ((arg = [_args objectForKey:@"-WOPort"]) == nil) return nil; lAddress = nil; if ([arg isEqualToString:@"auto"]) lAddress = [self autoBindAddress]; if ((lAddress == nil) && (cstr = [arg cString])) { if (isdigit(*cstr)) { lAddress = [NGInternetSocketAddress wildcardAddressWithPort:[arg intValue]]; } } if (lAddress == nil) lAddress = NGSocketAddressFromString(arg); return lAddress; } - (id)initWithName:(NSString *)_name arguments:(NSDictionary *)_args application:(WOCoreApplication *)_application { if ((self = [super initWithName:_name arguments:_args application:_application])) { id arg = nil; [self _registerForSignals]; if (![_application controlSocket]) { if ([_args count] < 1) self->address = [self addressFromDefaultsOfApplication:_application]; else self->address = [self addressFromArguments:_args]; self->address = [self->address retain]; if (self->address == nil) { [_application errorWithFormat: @"got no address for HTTP server (using arg '%@')", arg]; [self release]; return nil; } [_application logWithFormat:@"%@ listening on address %@", NSStringFromClass([self class]), [(id)self->address stringValue]]; } self->lock = [[NSRecursiveLock alloc] init]; self->maxThreadCount = [[WOCoreApplication workerThreadCount] intValue]; [self setSendTimeout:WOHttpAdaptorSendTimeout]; [self setReceiveTimeout:WOHttpAdaptorReceiveTimeout]; } return self; } - (void)dealloc { signal(SIGPIPE, SIG_DFL); [[NSNotificationCenter defaultCenter] removeObserver:self]; [self->lock release]; [self->socket release]; [self->controlSocket release]; [self->address release]; [super dealloc]; } /* accessors */ - (id)socketAddress { /* used by sns */ return self->address; } /* events */ - (void)registerForEvents { int backlog; WOChildMessage message; controlSocket = [[WOCoreApplication application] controlSocket]; if (controlSocket) { [controlSocket retain]; ASSIGN(self->socket, [[WOCoreApplication application] listeningSocket]); [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(acceptControlMessage:) name:NSFileObjectBecameActiveNotificationName object:nil]; [(WORunLoop *)[WORunLoop currentRunLoop] addFileObject:controlSocket activities:NSPosixReadableActivity forMode:NSDefaultRunLoopMode]; message = WOChildMessageReady; if (![controlSocket safeWriteBytes: &message count: sizeof (WOChildMessage)]) { [self errorWithFormat: @"failure notifying watchdog we are ready during events registration: %@", [controlSocket lastException]]; [[WOCoreApplication application] terminate]; } else [self logWithFormat: @"notified the watchdog that we are ready"]; } else { backlog = [[WOCoreApplication listenQueueSize] intValue]; if (backlog == 0) backlog = 5; [self->socket release]; self->socket = nil; self->socket = [[NGPassiveSocket alloc] initWithDomain:[self->address domain]]; [self->socket bindToAddress:self->address]; if ([[self->address domain] isEqual:[NGInternetSocketDomain domain]]) { if ([(NGInternetSocketAddress *)self->address port] == 0) { /* let the kernel choose an IP address */ [self debugWithFormat:@"bound to wildcard: %@", self->address]; [self debugWithFormat:@"got local: %@", [self->socket localAddress]]; self->address = [[self->socket localAddress] retain]; [self logWithFormat:@"bound to kernel assigned address %@: %@", self->address, self->socket]; } } [self->socket listenWithBacklog:backlog]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(acceptConnection:) name:NSFileObjectBecameActiveNotificationName object:self->socket]; [(WORunLoop *)[WORunLoop currentRunLoop] addFileObject:self->socket activities:NSPosixReadableActivity forMode:NSDefaultRunLoopMode]; } } - (void)unregisterForEvents { [(WORunLoop *)[WORunLoop currentRunLoop] removeFileObject:self->socket forMode:NSDefaultRunLoopMode]; [[NSNotificationCenter defaultCenter] removeObserver:self]; [self->lock release]; self->lock = nil; [self->socket release]; self->socket = nil; } /* debugging */ - (BOOL)isDebuggingEnabled { return debugOn; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"<%@[0x%p]: address=%@>", NSStringFromClass([self class]), self, self->address]; } /* Server */ /* accessors */ - (id)socket { return self->socket; } - (id)serverAddress { return [self->socket localAddress]; } - (void)setSendTimeout:(NSTimeInterval)_timeout { self->sendTimeout = _timeout; } - (NSTimeInterval)sendTimeout { return self->sendTimeout; } - (void)setReceiveTimeout:(NSTimeInterval)_timeout { self->receiveTimeout = _timeout; } - (NSTimeInterval)receiveTimeout { return self->receiveTimeout; } - (void)setMaxThreadCount:(int)_count { self->maxThreadCount = _count; } - (int)maxThreadCount { return self->maxThreadCount; } /* run-loop */ - (void)_serverCatched:(NSException *)_exc { [self errorWithFormat:@"http server caught: %@", _exc]; if (WOCoreOnHTTPAdaptorException) abort(); } - (BOOL)runConnection:(id)_socket { WOHttpTransaction *tx; if (_socket == nil) { [self errorWithFormat:@"got no socket for transaction ??"]; return NO; } tx = [[WOHttpTransaction alloc] initWithSocket:_socket application:self->application]; if (![tx run]) [self _serverCatched:[tx lastException]]; [tx release]; if ([self->application isTerminating]) self->isTerminated = YES; return YES; } - (void)_handleAcceptedConnection:(NGActiveSocket *)_connection { #if USE_POOLS NSAutoreleasePool *pool = nil; #endif NSTimeInterval t; if (perfLogger) t = [[NSDate date] timeIntervalSince1970]; [self->lock lock]; self->activeThreadCount++; [self->lock unlock]; #if USE_POOLS pool = [[NSAutoreleasePool alloc] init]; #endif { [*(&_connection) autorelease]; NS_DURING { [_connection setReceiveTimeout:self->receiveTimeout]; [_connection setSendTimeout:self->sendTimeout]; [self runConnection:_connection]; } NS_HANDLER { [self _serverCatched:localException]; } NS_ENDHANDLER; } #if USE_POOLS [pool release]; pool = nil; #endif [self->lock lock]; self->activeThreadCount--; [self->lock unlock]; if (perfLogger) { t = [[NSDate date] timeIntervalSince1970] - t; [perfLogger logWithFormat:@"handling of request took %4.3fs.", t < 0.0 ? -1.0 : t]; } } - (void)_handleAcceptedConnectionInThread:(NGActiveSocket *)_connection { /* ensure that the top-level pool is properly setup */ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [self _handleAcceptedConnection:_connection]; [pool release]; } - (NGActiveSocket *)_accept { id connection; id remote; NS_DURING { connection = [self->socket accept]; if (!connection) [self _serverCatched:[self->socket lastException]]; else { if ((remote = [connection remoteAddress]) != nil) [self debugWithFormat:@"accepted connection: %@", connection]; else { [self errorWithFormat:@"missing remote address for connection: %@", connection]; connection = nil; } } } NS_HANDLER { connection = nil; [self _serverCatched:localException]; } NS_ENDHANDLER; return (NGActiveSocket*)connection; } - (void)_handleConnection:(NGActiveSocket *)connection { if (connection != nil) { if (self->maxThreadCount <= 1) { NS_DURING [self _handleAcceptedConnection:[connection retain]]; NS_HANDLER [self _serverCatched:localException]; NS_ENDHANDLER; } else { [NSThread detachNewThreadSelector: @selector(_handleAcceptedConnectionInThread:) toTarget:self withObject:[connection retain]]; [self logWithFormat:@"detached new thread for request."]; //[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]]; } connection = nil; } } - (void) acceptControlMessage: (NSNotification *) aNotification { NGActiveSocket *notificationSocket, *connection; WOChildMessage message; NSAutoreleasePool *pool; // NSLog (@"received control message"); notificationSocket = [aNotification object]; if (notificationSocket == controlSocket) { // [self logWithFormat:@"child accepting message from socket: %@", controlSocket]; while (![controlSocket safeReadBytes: &message count: sizeof (WOChildMessage)]) [self errorWithFormat: @"failure reading watchdog message (retrying...): %@", [controlSocket lastException]]; if (message == WOChildMessageAccept) { pool = [NSAutoreleasePool new]; connection = [self _accept]; if (![controlSocket safeWriteBytes: &message count: sizeof (WOChildMessage)]) [self errorWithFormat: @"failure notifying watchdog we are busy: %@", [controlSocket lastException]]; [self _handleConnection: connection]; message = WOChildMessageReady; if (![controlSocket safeWriteBytes: &message count: sizeof (WOChildMessage)]) [self errorWithFormat: @"failure notifying watchdog we are ready: %@", [controlSocket lastException]]; [pool release]; } else if (message == WOChildMessageShutdown) { [controlSocket safeWriteBytes: &message count: sizeof (WOChildMessage)]; [[WOCoreApplication application] terminate]; } } } - (void)acceptConnection:(id)_notification { #if USE_POOLS NSAutoreleasePool *pool; pool = [[NSAutoreleasePool alloc] init]; #endif [self _handleConnection: [self _accept]]; #if USE_POOLS [pool release]; pool = nil; #endif if (self->isTerminated) { if (self->socket) { [[NSNotificationCenter defaultCenter] removeObserver:self name:NSFileObjectBecameActiveNotificationName object:self->socket]; [self->socket close]; [self->socket release]; self->socket = nil; } [self logWithFormat:@"adaptor stops application: %@ ...", self->application]; exit(0); } } @end /* WOHttpAdaptor */ SOPE/sope-appserver/NGObjWeb/WOHttpAdaptor/WORequest+Adaptor.h0000644000000000000000000000211515004363604023027 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __WORequest_Adaptor_H__ #define __WORequest_Adaptor_H__ #include @class NSDate; #define CODE_RED_PREFIX @"/default.ida?XXXXXXXXXXXXX" @interface WORequest(TakeStartDate) - (BOOL)isCodeRedAttack; - (void)takeStartDate:(NSDate *)_startDate; @end #endif /* __WORequest_Adaptor_H__ */ SOPE/sope-appserver/NGObjWeb/WOApplication.m0000644000000000000000000011023515004363604017564 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "WOContext+private.h" #include "WOElement+private.h" #include "WOComponent+private.h" #include #include #include #include #include #include #include #include #include #include #import #include "common.h" #include #if GNU_RUNTIME && !defined(__GNUSTEP_RUNTIME__) && !(__GNU_LIBOBJC__ >= 20110608) # include #endif @interface WOApplication(PrivateMethods) + (id)logger; - (id)_loadComponentDefinitionWithName:(NSString *)_name language:(NSArray *)_langs; - (NSDictionary *)memoryStatistics; @end static NSRecursiveLock *classLock = nil; static NGLogger *perfLogger = nil; static Class NSDateClass = Nil; static Class WOTemplateClass = Nil; static BOOL debugOn = NO; static NSString *rapidTurnAroundPath = nil; @interface WOSessionStore(SnStore) - (void)performExpirationCheck:(NSTimer *)_timer; @end @implementation WOApplication #if 1 // TODO: why is that? why isn't that set by a default? static NSString *defaultCompRqHandlerClassName = @"OWViewRequestHandler"; #else static NSString *defaultCompRqHandlerClassName = @"WOComponentRequestHandler"; #endif /* old license checks */ - (NSCalendarDate *)appExpireDate { // TODO: can we remove that? return nil; } - (BOOL)isLicenseExpired { // TODO: can we remove that? return NO; } /* app path */ - (NSString *)_lookupAppPath { static NSString *suffix = nil; static BOOL appPathMissing = NO; NSUserDefaults *ud; NSFileManager *fm; NSString *cwd; NSString *result; if (appPathMissing) return nil; ud = [NSUserDefaults standardUserDefaults]; // Check if appPath has been forced result = [ud stringForKey:@"WOProjectDirectory"]; if(result != nil) return result; if (suffix == nil) suffix = [ud stringForKey:@"WOApplicationSuffix"]; fm = [NSFileManager defaultManager]; cwd = [fm currentDirectoryPath]; #if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY result = [[NGBundle mainBundle] bundlePath]; //NSLog(@"%s: check path '%@'", __PRETTY_FUNCTION__, result); #else result = cwd; #endif if ([result hasSuffix:suffix]) { /* started app inside of .woa directory */ #if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY result = [[NGBundle mainBundle] bundlePath]; #else result = cwd; #endif } else { NSString *wrapperName; wrapperName = [self->name stringByAppendingString:suffix]; /* take a look whether ./AppName.woa exists */ result = [result stringByAppendingPathComponent:wrapperName]; if (![fm fileExistsAtPath:result]) { /* lookup in process-path */ NSProcessInfo *pi; NSDictionary *env; NSString *ppath; BOOL isFlattened; pi = [NSProcessInfo processInfo]; env = [pi environment]; if ([[env objectForKey:@"GNUSTEP_SYSTEM_ROOT"] isNotNull]) { isFlattened = [[[env objectForKey:@"GNUSTEP_FLATTENED"] lowercaseString] isEqualToString:@"yes"]; } else /* default to flattened if no GNUstep runtime is set */ isFlattened = YES; ppath = [[pi arguments] objectAtIndex:0]; ppath = [ppath stringByDeletingLastPathComponent]; // del exe-name if (!isFlattened) { ppath = [ppath stringByDeletingLastPathComponent]; // lib-combo ppath = [ppath stringByDeletingLastPathComponent]; // os ppath = [ppath stringByDeletingLastPathComponent]; // cpu } if ([ppath hasSuffix:suffix]) result = ppath; } } if (![fm fileExistsAtPath:result]) { [self debugWithFormat:@"%s: missing path '%@'", __PRETTY_FUNCTION__, result]; appPathMissing = YES; result = nil; } return result; } + (NSString *)defaultRequestHandlerClassName { return @"WOComponentRequestHandler"; } - (void)_logDefaults { NSUserDefaults *ud; NSArray *keys; NSEnumerator *e; NSString *key; ud = [NSUserDefaults standardUserDefaults]; keys = [[ud dictionaryRepresentation] allKeys]; keys = [keys sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; e = [keys objectEnumerator]; while((key = [e nextObject]) != nil) { if ([key hasPrefix:@"WO"] || [key isEqualToString:@"NSProjectSearchPath"]) [self logWithFormat:@"[default]: %@ = %@", key, [[ud objectForKey:key] description]]; } } - (id)initWithName:(NSString *)_name { if ((self = [super init]) != nil) { NSUserDefaults *ud; NGLoggerManager *lm; WORequestHandler *rh; NSString *rk; self->name = [_name copy]; ud = [NSUserDefaults standardUserDefaults]; debugOn = [WOApplication isDebuggingEnabled]; if ([WOApplication isDebuggingEnabled]) [[self logger] debugWithFormat:@"WOApplication debugging is enabled."]; if (classLock == nil) classLock = [[NSRecursiveLock alloc] init]; NSDateClass = [NSDate class]; WOTemplateClass = [WOTemplate class]; rapidTurnAroundPath = [[ud stringForKey:@"WOProjectDirectory"] copy]; lm = [NGLoggerManager defaultLoggerManager]; perfLogger = [lm loggerForDefaultKey:@"WOProfileApplication"]; [self setPageCacheSize:[ud integerForKey:@"WOPageCacheSize"]]; [self setPermanentPageCacheSize: [ud integerForKey:@"WOPermanentPageCacheSize"]]; [self setPageRefreshOnBacktrackEnabled: [[ud objectForKey:@"WOPageRefreshOnBacktrack"] boolValue]]; [self setCachingEnabled:[WOApplication isCachingEnabled]]; /* setup request handlers */ self->defaultRequestHandler = [[NSClassFromString([[self class] defaultRequestHandlerClassName]) alloc] init]; self->requestHandlerRegistry = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 8); if ((rk = [WOApplication componentRequestHandlerKey]) == nil) { [self logWithFormat: @"WARNING: no component request handler key is specified, " @"this probably means that share/ngobjweb/Defaults.plist " @"could not get loaded (permissions?)"]; } rh = [[NSClassFromString(defaultCompRqHandlerClassName) alloc] init]; if ([rk isNotEmpty] && [rh isNotNull]) [self registerRequestHandler:rh forKey:rk]; [rh release]; rh = nil; rk = [WOApplication directActionRequestHandlerKey]; rh = [[NSClassFromString(@"WODirectActionRequestHandler") alloc] init]; if ([rk isNotEmpty] && [rh isNotNull]) [self registerRequestHandler:rh forKey:rk]; [rh release]; rh = nil; if ((rh = [[NSClassFromString(@"WOResourceRequestHandler") alloc] init])) { rk = [WOApplication resourceRequestHandlerKey]; if ([rk isNotEmpty]) [self registerRequestHandler:rh forKey:rk]; [self registerRequestHandler:rh forKey:@"WebServerResources"]; #ifdef __APPLE__ [self registerRequestHandler:rh forKey:@"Resources"]; #endif [rh release]; rh = nil; } /* setup session store */ self->iSessionStore = [[NSClassFromString([self sessionStoreClassName]) alloc] init]; /* setup statistics store */ self->iStatisticsStore = [[WOStatisticsStore alloc] init]; /* register timers */ self->expirationTimer = [[NSTimer scheduledTimerWithTimeInterval: [[ud objectForKey:@"WOExpirationTimeInterval"] intValue] target:self selector:@selector(performExpirationCheck:) userInfo:nil repeats:YES] retain]; if ([ud boolForKey:@"WOLogDefaultsOnStartup"]) [self _logDefaults]; [[NSNotificationCenter defaultCenter] postNotificationName: WOApplicationWillFinishLaunchingNotification object:self]; } return self; } - (id)init { return [self initWithName:[[[NSProcessInfo processInfo] processName] stringByDeletingPathExtension]]; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [self->expirationTimer invalidate]; if (self->requestHandlerRegistry) NSFreeMapTable(self->requestHandlerRegistry); [self->expirationTimer release]; [self->resourceManager release]; [self->iSessionStore release]; [self->defaultRequestHandler release]; [self->path release]; [self->name release]; [self->instanceNumber release]; [super dealloc]; } - (void)processHupSignal:(int)_signal { /* this isn't called immediatly */ [self logWithFormat:@"terminating on SIGHUP ..."]; [self terminate]; } /* accessors */ - (NSString *)name { return self->name; } - (BOOL)monitoringEnabled { return NO; } - (NSString *)path { static BOOL missingPath = NO; if (missingPath) return nil; if (self->path == nil) { if ((self->path = [[self _lookupAppPath] copy]) == nil) { [self debugWithFormat:@"could not find wrapper of application !"]; missingPath = YES; return nil; } } return self->path; } - (NSString *)number { if (self->instanceNumber == nil) { id num; if ((num = [[NSUserDefaults standardUserDefaults] objectForKey:@"n"])) { self->instanceNumber = [[num stringValue] copy]; } else { unsigned pid; #if defined(__MINGW32__) pid = (unsigned)GetCurrentProcessId(); #else pid = (unsigned)getpid(); #endif self->instanceNumber = [[NSString alloc] initWithFormat:@"%d", pid]; } } return self->instanceNumber; } - (void)_setCurrentContext:(WOContext *)_ctx { NSMutableDictionary *info; info = [[NSThread currentThread] threadDictionary]; if (_ctx != nil) [info setObject:_ctx forKey:@"WOContext"]; else [info removeObjectForKey:@"WOContext"]; } - (WOContext *)context { // deprecated in WO4 NSThread *t; NSDictionary *td; if ((t = [NSThread currentThread]) == nil) { [self errorWithFormat:@"missing current thread !!!"]; return nil; } if ((td = [t threadDictionary]) == nil) { [self errorWithFormat: @"missing current thread's dictionary (thread=%@) !!!", t]; return nil; } return [td objectForKey:@"WOContext"]; } /* request handlers */ - (void)registerRequestHandler:(WORequestHandler *)_hdl forKey:(NSString *)_key { [self lock]; NSMapInsert(self->requestHandlerRegistry, _key, _hdl); [self unlock]; } - (void)removeRequestHandlerForKey:(NSString *)_key { if (_key == nil) return; [self lock]; NSMapRemove(self->requestHandlerRegistry, _key); [self unlock]; } - (void)setDefaultRequestHandler:(WORequestHandler *)_hdl { [self lock]; ASSIGN(self->defaultRequestHandler, _hdl); [self unlock]; } - (WORequestHandler *)defaultRequestHandler { return self->defaultRequestHandler; } - (WORequestHandler *)requestHandlerForKey:(NSString *)_key { WORequestHandler *handler; [self lock]; handler = [(id)NSMapGet(self->requestHandlerRegistry, _key) retain]; if (handler == nil) handler = [[self defaultRequestHandler] retain]; [self unlock]; return [handler autorelease]; } - (NSArray *)registeredRequestHandlerKeys { NSMutableArray *array = [NSMutableArray arrayWithCapacity:16]; NSMapEnumerator e; NSString *key; WORequestHandler *handler; [self lock]; e = NSEnumerateMapTable(self->requestHandlerRegistry); while (NSNextMapEnumeratorPair(&e, (void**)&key, (void**)&handler)) [array addObject:key]; [self unlock]; return [[array copy] autorelease]; } - (WORequestHandler *)handlerForRequest:(WORequest *)_request { WORequestHandler *handler; NSString *key; if ((key = [_request requestHandlerKey]) == nil) return [self defaultRequestHandler]; handler = NSMapGet(self->requestHandlerRegistry, key); return (handler != nil) ? handler : [self defaultRequestHandler]; } /* sessions */ - (WOSession *)_initializeSessionInContext:(WOContext *)_ctx { WOSession *sn; sn = [self createSessionForRequest:[_ctx request]]; [_ctx setNewSession:sn]; if ([sn respondsToSelector:@selector(prepare)]) { #if DEBUG [self debugWithFormat:@"calling -prepare on session .."]; #endif [sn performSelector:@selector(prepare)]; } [sn _awakeWithContext:_ctx]; [[NSNotificationCenter defaultCenter] postNotificationName:WOSessionDidCreateNotification object:sn]; return [sn autorelease]; } - (NSString *)sessionIDFromRequest:(WORequest *)_request { NSString *sessionId; if (_request == nil) return nil; /* first look into form values */ if ((sessionId = [_request formValueForKey:WORequestValueSessionID])!=nil) { if ([sessionId isNotEmpty]) return sessionId; } /* now look into the cookies */ if ((sessionId = [_request cookieValueForKey:[self name]]) != nil) { if ([sessionId respondsToSelector:@selector(objectEnumerator)]) { NSEnumerator *e; e = [(id)sessionId objectEnumerator]; while ((sessionId = [e nextObject]) != nil) { if ([sessionId isNotEmpty] && ![sessionId isEqual:@"nil"]) return sessionId; } } else { if ([sessionId isNotEmpty] && ![sessionId isEqual:@"nil"]) return sessionId; } } return nil; } - (NSString *)createSessionIDForSession:(WOSession *)_session { /* session id must be 18 chars long for snsd to work ! */ static unsigned int sessionCount = 0; NSString *wosid; unsigned char buf[20]; sessionCount++; sprintf((char *)buf, "%04X%04X%02X%08X", [[self number] intValue], getpid(), sessionCount, (unsigned int)time(NULL)); wosid = [NSString stringWithCString:(char *)buf]; return wosid; } - (id)createSessionForRequest:(WORequest *)_request { if ([self respondsToSelector:@selector(createSession)]) { /* call deprecated method */ [self warnWithFormat:@"calling deprecated -createSession .."]; return [self createSession]; } else { Class snClass = Nil; if ((snClass = NSClassFromString(@"Session")) == Nil) snClass = [WOSession class]; return [[snClass alloc] init]; } } - (id)restoreSessionWithID:(NSString *)_sid inContext:(WOContext *)_ctx { WOSession *session; *(&session) = nil; if ([self respondsToSelector:@selector(restoreSession)]) { /* call deprecated method */ [self warnWithFormat:@"calling deprecated -restoreSession .."]; return [self restoreSession]; } SYNCHRONIZED(self) { WOSessionStore *store; if ((store = [self sessionStore]) == nil) { [self errorWithFormat:@"missing session store ..."]; } else { session = [store restoreSessionWithID:_sid request:[_ctx request]]; if ([session isNotNull]) { [_ctx setSession:session]; [session _awakeWithContext:_ctx]; } else { [self debugWithFormat:@"did not find a session for sid '%@'", _sid]; } } } END_SYNCHRONIZED; if (session) { [[NSNotificationCenter defaultCenter] postNotificationName:WOSessionDidRestoreNotification object:session]; } else { if ([_sid hasPrefix:@"("]) { id sid; sid = [_sid propertyList]; if ([sid respondsToSelector:@selector(objectEnumerator)]) { NSEnumerator *e; [self errorWithFormat:@"got multiple session IDs !"]; e = [sid objectEnumerator]; while ((_sid = [e nextObject])) { if ([_sid isEqualToString:@"nil"]) continue; if ((session = [self restoreSessionWithID:_sid inContext:_ctx])) return session; //[self warnWithFormat:@"did not find session for sid %@", _sid); } } } } return session; } - (void)saveSessionForContext:(WOContext *)_ctx { NSTimeInterval startSave = 0.0; if (perfLogger) startSave = [[NSDateClass date] timeIntervalSince1970]; if ([self respondsToSelector:@selector(saveSession:)]) { /* call deprecated method */ [self warnWithFormat:@"calling deprecated -saveSession: .."]; [self saveSession:[_ctx session]]; return; } SYNCHRONIZED(self) { WOSession *sn; NSTimeInterval startSnSleep = 0.0, startStore = 0.0; sn = [_ctx session]; if (perfLogger) startSnSleep = [[NSDateClass date] timeIntervalSince1970]; /* put session to sleep */ [sn _sleepWithContext:_ctx]; if (perfLogger) { NSTimeInterval rt; rt = [[NSDateClass date] timeIntervalSince1970] - startSnSleep; [perfLogger logWithFormat:@"[woapp]: session -sleep took %4.3fs.", rt < 0.0 ? -1.0 : rt]; } if ([sn isTerminating]) { [[NSNotificationCenter defaultCenter] postNotificationName: WOSessionDidTerminateNotification object:sn]; } if (perfLogger) startStore = [[NSDateClass date] timeIntervalSince1970]; [[self sessionStore] saveSessionForContext:_ctx]; if (perfLogger) { NSTimeInterval rt; rt = [[NSDateClass date] timeIntervalSince1970] - startStore; [perfLogger logWithFormat:@"[woapp]: storing sn in store took %4.3fs.", rt < 0.0 ? -1.0 : rt]; } } END_SYNCHRONIZED; if (perfLogger) { NSTimeInterval rt; rt = [[NSDateClass date] timeIntervalSince1970] - startSave; [perfLogger logWithFormat:@"[woapp]: saveSessionForContext took %4.3fs.", rt < 0.0 ? -1.0 : rt]; } } - (void)refuseNewSessions:(BOOL)_flag { self->appFlags.doesRefuseNewSessions = _flag ? 1 : 0; } - (BOOL)isRefusingNewSessions { return self->appFlags.doesRefuseNewSessions; } - (int)activeSessionsCount { return [[self sessionStore] activeSessionsCount]; } - (void)setSessionStore:(WOSessionStore *)_store { ASSIGN(self->iSessionStore, _store); } - (NSString *)sessionStoreClassName { return [[NSUserDefaults standardUserDefaults] stringForKey:@"WOSessionStore"]; } - (WOSessionStore *)sessionStore { return self->iSessionStore; } - (void)setMinimumActiveSessionsCount:(int)_minimum { self->minimumActiveSessionsCount = _minimum; } - (int)minimumActiveSessionsCount { return self->minimumActiveSessionsCount; } - (void)performExpirationCheck:(NSTimer *)_timer { WOSessionStore *ss; /* let session store check for expiration ... */ ss = [self sessionStore]; if ([ss respondsToSelector:@selector(performExpirationCheck:)]) [ss performExpirationCheck:_timer]; /* check whether application should terminate ... */ if ([self isRefusingNewSessions] && ([self activeSessionsCount] < [self minimumActiveSessionsCount])) { /* check whether the application instance is still valid .. */ [self debugWithFormat: @"application terminates because it refuses new sessions and " @"the active session count (%i) is below the minimum (%i).", [self activeSessionsCount], [self minimumActiveSessionsCount]]; [self terminate]; } } - (id)session { return [[self context] session]; } - (WOResponse *)handleSessionCreationErrorInContext:(WOContext *)_ctx { WOResponse *response = [_ctx response]; unsigned pid; #ifdef __MINGW32__ pid = GetCurrentProcessId(); #else pid = getpid(); #endif if ([self respondsToSelector:@selector(handleSessionCreationError)]) { [self warnWithFormat:@"called deprecated -handleSessionCreationError method"]; return [self handleSessionCreationError]; } [self errorWithFormat:@"could not create session for context %@", _ctx]; [response setStatus:200]; [response appendContentString:@"

    Session Creation Error

    \n
    "];
      [response appendContentString:
                  @"Application Instance failed to create session."];
      [response appendContentHTMLString:
                  [NSString stringWithFormat:
                              @"   application: %@\n"
                              @"   adaptor:     %@\n"
                              @"   baseURL:     %@\n"
                              @"   contextID:   %@\n"
                              @"   instance:    %i\n"
                              @"   request:     %@\n",
                              [self name],
                              [[_ctx request] adaptorPrefix],
                              [self baseURL],
                              [_ctx contextID],
                              pid,
                              [[_ctx request] description]]];
      [response appendContentString:@"
    "]; return response; } - (WOResponse *)handleSessionRestorationErrorInContext:(WOContext *)_ctx { if ([self respondsToSelector:@selector(handleSessionRestorationError)]) { [self warnWithFormat:@"calling deprecated " @"-handleSessionRestorationError method"]; return [self handleSessionRestorationError]; } // TODO: is it correct to return nil? // TODO: we should return a page saying sorry with a cookie + redirect [self errorWithFormat:@"could not restore session for context %@", _ctx]; return nil; } /* statistics */ - (void)setStatisticsStore:(WOStatisticsStore *)_statStore { ASSIGN(self->iStatisticsStore, _statStore); } - (WOStatisticsStore *)statisticsStore { return self->iStatisticsStore; } - (bycopy NSDictionary *)statistics { return [[self statisticsStore] statistics]; } /* resources */ - (void)_setupDefaultResourceManager { NSUserDefaults *ud; Class rmClass; NSString *p; ud = [NSUserDefaults standardUserDefaults]; p = [ud stringForKey:@"WODefaultResourceManager"]; rmClass = [p isNotEmpty] ? NSClassFromString(p) : [WOResourceManager class]; if (rmClass == Nil) { [self errorWithFormat: @"failed to locate class of resource manager: '%@'", p]; return; } if ([rmClass instancesRespondToSelector:@selector(initWithPath:)]) self->resourceManager = [[rmClass alloc] init]; else { self->resourceManager = [(WOResourceManager *)[rmClass alloc] initWithPath:[self path]]; } } - (void)setResourceManager:(WOResourceManager *)_manager { ASSIGN(self->resourceManager, _manager); } - (WOResourceManager *)resourceManager { if (self->resourceManager == nil) [self _setupDefaultResourceManager]; return self->resourceManager; } - (NSURL *)baseURL { NSString *n; WOContext *ctx = [self context]; n = [[ctx request] applicationName]; n = [@"/" stringByAppendingString:n ? n : [self name]]; return [NSURL URLWithString:n relativeToURL:[ctx baseURL]]; } - (NSString *)pathForResourceNamed:(NSString *)_name ofType:(NSString *)_type { IS_DEPRECATED; return [[self resourceManager] pathForResourceNamed:_name ofType:_type]; } - (NSString *)stringForKey:(NSString *)_key inTableNamed:(NSString *)_tableName withDefaultValue:(NSString *)_default { IS_DEPRECATED; return [[self resourceManager] stringForKey:_key inTableNamed:_tableName withDefaultValue:_default languages: [(WOSession *)[self session] languages]]; } /* notifications */ - (void)awake { } - (void)sleep { #if DEBUG && PRINT_NSSTRING_STATISTICS if ([NSString respondsToSelector:@selector(printStatistics)]) [NSString printStatistics]; #endif #if DEBUG && PRINT_OBJC_STATISTICS extern int __objc_selector_max_index; printf("nbuckets=%i, nindices=%i, narrays=%i, idxsize=%i\n", nbuckets, nindices, narrays, idxsize); printf("maxsel=%i\n", __objc_selector_max_index); #endif } /* responder */ - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx { if ([_ctx hasSession]) [[_ctx session] takeValuesFromRequest:_req inContext:_ctx]; else { WOComponent *page; if ((page = [_ctx page]) != nil) { WOContext_enterComponent(_ctx, page, nil); [page takeValuesFromRequest:_req inContext:_ctx]; WOContext_leaveComponent(_ctx, page); } } } - (id)invokeActionForRequest:(WORequest *)_rq inContext:(WOContext *)_ctx { id result; if ([_ctx hasSession]) result = [[_ctx session] invokeActionForRequest:_rq inContext:_ctx]; else { WOComponent *page; if ((page = [_ctx page])) { WOContext_enterComponent(_ctx, page, nil); result = [[_ctx page] invokeActionForRequest:_rq inContext:_ctx]; WOContext_leaveComponent(_ctx, page); } else result = nil; } return result; } - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { if ([_ctx hasSession]) [[_ctx session] appendToResponse:_response inContext:_ctx]; else { WOComponent *page; if ((page = [_ctx page])) { WOContext_enterComponent(_ctx, page, nil); [page appendToResponse:_response inContext:_ctx]; WOContext_leaveComponent(_ctx, page); } } if(rapidTurnAroundPath != nil) { WOComponent *page; if((page = [_ctx page])) { WOElement *template; template = [page _woComponentTemplate]; if([template isKindOfClass:WOTemplateClass]) { NSString *_path; _path = [[(WOTemplate *)template url] path]; [_response setHeader:_path forKey:@"x-sope-template-path"]; } } } } // dynamic elements - (WOElement *)dynamicElementWithName:(NSString *)_name associations:(NSDictionary *)_associations template:(WOElement *)_template languages:(NSArray *)_languages { WOElement *element = nil; Class dynamicElementClass = NSClassFromString(_name); if (dynamicElementClass == Nil) { [self warnWithFormat:@"did not find dynamic element class %@ !", _name]; return nil; } if (![dynamicElementClass isDynamicElement]) { [self warnWithFormat:@"class %@ is not a dynamic element class !", _name]; return nil; } element = [[dynamicElementClass allocWithZone:[_template zone]] initWithName:_name associations:_associations template:_template]; return element; } - (WOElement *)dynamicElementWithName:(NSString *)_name associations:(NSDictionary *)_associations template:(WOElement *)_template { return [self dynamicElementWithName:_name associations:_associations template:_template languages:[(WOSession *)[self session] languages]]; } // pages - (void)setPageRefreshOnBacktrackEnabled:(BOOL)_flag { self->appFlags.isPageRefreshOnBacktrackEnabled = _flag ? 1 : 0; } - (BOOL)isPageRefreshOnBacktrackEnabled { return self->appFlags.isPageRefreshOnBacktrackEnabled ? YES : NO; } - (void)setCachingEnabled:(BOOL)_flag { self->appFlags.isCachingEnabled = _flag ? 1 : 0; } - (BOOL)isCachingEnabled { // component definition caching return self->appFlags.isCachingEnabled ? YES : NO; } - (void)setPageCacheSize:(int)_size { self->pageCacheSize = _size; } - (int)pageCacheSize { return self->pageCacheSize; } - (void)setPermanentPageCacheSize:(int)_size { self->permanentPageCacheSize = _size; } - (int)permanentPageCacheSize { return self->permanentPageCacheSize; } - (id)pageWithName:(NSString *)_name { // deprecated in WO4 return [self pageWithName:_name inContext:[self context]]; } - (WOComponent *)_pageWithName:(NSString *)_name inContext:(WOContext *)_ctx { /* OSX profiling: 3.4% of dispatchRequest? 3.0% rm -pageWithName.. 1.5% def instantiate 1.3% initWithName:... 0.76% initWithContent:.. (0.43 addobserver) 0.76% rm defForComp (0.43% touch) 0.54% pool 0.11% ctx -component 0.11% pool */ NSArray *languages; WOComponent *page; NSAutoreleasePool *pool; WOResourceManager *rm; #if MEM_DEBUG NSDictionary *start, *stop; start = [self memoryStatistics]; #endif pool = [[NSAutoreleasePool alloc] init]; languages = [_ctx resourceLookupLanguages]; if ((rm = [[_ctx component] resourceManager]) == nil) rm = [self resourceManager]; /* TODO: * the following ignores the fact that the passed context may be different * from that of WOApplication. During the course of template instantiation * WOApplication's current context gets attached to page which is definitely * wrong. We workaround this problem by using the private API of WOComponent * to explicitly set it. However all accompanied methods should be * extended to pass the correct context where needed. */ page = [rm pageWithName:(_name != nil ? _name : (NSString *)@"Main") languages:languages]; [page _setContext:_ctx]; [page ensureAwakeInContext:_ctx]; page = [page retain]; [pool release]; #if MEM_DEBUG { int rss, vmsize, lib; stop = [self memoryStatistics]; rss = [[stop objectForKey:@"VmRSS"] intValue] - [[start objectForKey:@"VmRSS"] intValue]; vmsize = [[stop objectForKey:@"VmSize"] intValue] - [[start objectForKey:@"VmSize"] intValue]; lib = [[stop objectForKey:@"VmLib"] intValue] - [[start objectForKey:@"VmLib"] intValue]; [self debugWithFormat:@"loaded component %@; rss=%i vm=%i lib=%i.", _name, rss,vmsize,lib]; } #endif return [page autorelease]; } - (id)pageWithName:(NSString *)_name inContext:(WOContext *)_ctx { return [self _pageWithName:_name inContext:_ctx]; } - (id)pageWithName:(NSString *)_name forRequest:(WORequest *)_req { WOResourceManager *rm; if ((rm = [self resourceManager]) == nil) return nil; return [rm pageWithName:(_name != nil) ? _name : (NSString *)@"Main" languages:[_req browserLanguages]]; } - (void)savePage:(WOComponent *)_page { IS_DEPRECATED; [[[self context] session] savePage:_page]; } - (id)restorePageForContextID:(NSString *)_ctxId { IS_DEPRECATED; return [[[self context] session] restorePageForContextID:_ctxId]; } - (WOResponse *)handlePageRestorationErrorInContext:(WOContext *)_ctx { [self errorWithFormat: @"could not restore page for context-id %@\n in context %@", [_ctx currentElementID], _ctx]; /* return main page ... */ return [[self pageWithName:nil inContext:_ctx] generateResponse]; } - (WOResponse *)handlePageRestorationError { IS_DEPRECATED; return [self handlePageRestorationErrorInContext:[self context]]; } /* exceptions */ - (WOResponse *)handleException:(NSException *)_exc inContext:(WOContext *)_ctx { WORequest *rq = [_ctx request]; WOResponse *r = nil; if ([self respondsToSelector:@selector(handleException:)]) { [self warnWithFormat:@"calling deprecated -handleException method !"]; return [self handleException:_exc]; } #if DEBUG { static int doCore = -1; if (doCore == -1) { doCore = [[NSUserDefaults standardUserDefaults] boolForKey:@"WOCoreOnApplicationException"] ? 1 : 0; } if (doCore) { [self fatalWithFormat:@"%@: caught (ctx=%@):\n %@.", self, _ctx, _exc]; abort(); } } #endif if (_ctx == nil) { [self fatalWithFormat:@"%@: caught (without context):\n %@.", self, _exc]; [self terminate]; } else if (rq == nil) { [self fatalWithFormat:@"%@: caught (without request):\n %@.", self, _exc]; [self terminate]; } else { static NSString *pageFormat = @"Application Server caught exception:\n\n" @" session: %@\n" @" element: %@\n" @" context: %@\n" @" request: %@\n\n" @" class: %@\n" @" name: %@\n" @" reason: %@\n" @" info:\n %@\n" @" backtrace:\n%@\n"; NSString *str = nil; NSString *bt = nil; [self errorWithFormat:@"%@: caught:\n %@\nin context:\n %@.", self, _exc, _ctx]; #if LIB_FOUNDATION_LIBRARY if ([NSException respondsToSelector:@selector(backtrace)]) bt = [NSException backtrace]; #endif if ((r = [WOResponse responseWithRequest:rq]) == nil) [self errorWithFormat:@"could not create response !"]; [r setHeader:@"text/html" forKey:@"content-type"]; [r setHeader:@"no-cache" forKey:@"cache-control"]; if (rapidTurnAroundPath != nil) { NSURL *templateURL; templateURL = [[_exc userInfo] objectForKey:@"templateURL"]; if(templateURL != nil) [r setHeader:[templateURL path] forKey:@"x-sope-template-path"]; } str = [NSString stringWithFormat:pageFormat, [_ctx hasSession] ? [[_ctx session] sessionID] : (NSString *)@"[no session]", [_ctx elementID], [_ctx description], [rq description], NSStringFromClass([_exc class]), [_exc name], [_exc reason], [[_exc userInfo] description], bt]; [r appendContentString:@"Caught exception
    \n"];
        [r appendContentHTMLString:str];
        [r appendContentString:@"
    \n"]; } return r; } /* runloop */ - (BOOL)shouldTerminate { if (![self isRefusingNewSessions]) return NO; if ([self activeSessionsCount] >= [self minimumActiveSessionsCount]) return NO; /* check whether the application instance is still valid .. */ [self debugWithFormat: @"application terminates because it refuses new sessions and " @"the active session count (%i) is below the minimum (%i).", [self activeSessionsCount], [self minimumActiveSessionsCount]]; return YES; } - (void)terminate { [self debugWithFormat: @"application terminates:\n" @" %i active sessions\n" @" %i minimum active sessions\n" @" refuses new session: %s", [self activeSessionsCount], [self minimumActiveSessionsCount], [self isRefusingNewSessions] ? "yes" : "no"]; [super terminate]; } /* logging */ - (BOOL)isDebuggingEnabled { return debugOn; } - (NSString *)loggingPrefix { return [NSString stringWithFormat:@"|%@%@|", [self name], [self isTerminating] ? @" terminating" : @""]; } /* KVC */ #if !LIB_FOUNDATION_LIBRARY - (id)valueForUndefinedKey:(NSString *)_key { [self warnWithFormat:@"tried to access undefined KVC key: '%@'", _key]; return nil; } #endif /* configuration */ + (Class)eoEditingContextClass { static Class eoEditingContextClass = Nil; static BOOL lookedUpForEOEditingContextClass = NO; if (!lookedUpForEOEditingContextClass) { if ((eoEditingContextClass = NSClassFromString(@"EOEditingContext")) ==nil) eoEditingContextClass = NSClassFromString(@"NSManagedObjectContext"); lookedUpForEOEditingContextClass = YES; } return eoEditingContextClass; } + (BOOL)implementsEditingContexts { return [self eoEditingContextClass] != NULL ? YES : NO; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"<%@[0x%p]: name=%@%@>", NSStringFromClass([self class]), self, [self name], [self isTerminating] ? @" terminating" : @"" ]; } @end /* WOApplication */ SOPE/sope-appserver/NGObjWeb/Templates/0000755000000000000000000000000015004363604016631 5ustar rootrootSOPE/sope-appserver/NGObjWeb/Templates/WOxComponentElemBuilder.m0000644000000000000000000002022015004363604023515 0ustar rootroot/* Copyright (C) 2002-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include /* This builder builds references to subcomponents. The subcomponent name is derived from the tagname. NOTE: this builder is a "final destination" for all bind(var) namespace tags ! Sample: Supported tags: .... maps to a component script part ... maps to WOSwitchComponent */ @interface WOxComponentElemBuilder : WOxElemBuilder { } @end #include #include #include #include #include #include "WOChildComponentReference.h" #include "common.h" @interface NSObject(LineInfo) - (unsigned)line; @end @implementation WOxComponentElemBuilder static NGLogger *debugLogger = nil; + (void)initialize { NGLoggerManager *lm; static BOOL didInit = NO; if (didInit) return; didInit = YES; lm = [NGLoggerManager defaultLoggerManager]; debugLogger = [lm loggerForDefaultKey:@"WOxComponentElemBuilderDebugEnabled"]; } /* extracting associations */ - (NSMutableDictionary *)associationsForAttributes:(id)_attrs templateBuilder:(id)_b { NSMutableDictionary *assocs; if ((assocs = [_b associationsForAttributes:_attrs]) == nil) return nil; // should we check the tag or do we always remove className ? if ([assocs objectForKey:@"className"]) [assocs removeObjectForKey:@"className"]; else if ([assocs objectForKey:@"value"]) [assocs removeObjectForKey:@"value"]; return assocs; } /* building elements */ - (WOElement *)buildComponentReferenceElement:(id)_element templateBuilder:(id)_b { /* TODO: I don't think that this already works - it uses the 'value' binding but WOComponentReference expects 'component' */ static Class LiveChildRefClass = Nil; NSMutableDictionary *assocs; NSArray *children; NSString *value; WOElement *de; if (LiveChildRefClass == Nil) LiveChildRefClass = NSClassFromString(@"WOComponentReference"); if (debugLogger) [debugLogger debugWithFormat:@"build component-reference: %@", _element]; value = [_element attribute:@"value" namespaceURI:XMLNS_OD_BIND]; if ([value length] == 0) return nil; /* construct child elements */ children = [_element hasChildNodes] ? [_b buildNodes:[_element childNodes] templateBuilder:_b] : (NSArray *)nil; [children autorelease]; /* build associations */ assocs = [self associationsForAttributes:[_element attributes] templateBuilder:_b]; [assocs setObject:[WOAssociation associationWithKeyPath:value] forKey:@"component"]; /* build element */ if (debugLogger) { [debugLogger debugWithFormat: @"create reference for keypath: '%@': children=%@, " @"assocs=%@", value, children, assocs]; } de = [[LiveChildRefClass alloc] initWithName:[_b uniqueIDForNode:_element] associations:assocs contentElements:children]; if (debugLogger) [debugLogger debugWithFormat:@"built: %@", de]; return de; } - (WOElement *)processScriptElement:(id)_e templateBuilder:(id)_b { /* process a component related script */ NSString *src; [self debugWithFormat:@"processing script element: %@", _e]; /* first process src attribute ... */ if ((src = [_e attribute:@"src" namespaceURI:XMLNS_OD_BIND])) { /* create script part for src ... */ [self logWithFormat:@"create script part for src '%@', not implemented", src]; } /* create script part for content ... */ if ([_e hasChildNodes]) { WOComponentScriptPart *lscript; NSEnumerator *e; id subnode; NSMutableString *content; unsigned line; NSURL *url; content = [[NSMutableString alloc] initWithCapacity:256]; line = ([(NSObject *)_e respondsToSelector:@selector(line)]) ? [(id)_e line] : 0; url = nil; e = [(NSArray *)[_e childNodes] objectEnumerator]; while ((subnode = [e nextObject])) { [content appendString:[subnode textValue]]; } lscript = [WOComponentScriptPart alloc]; lscript = [lscript initWithURL:url startLine:line script:content]; [content release]; [_b addComponentScriptPart:lscript]; [lscript release]; } return nil; } - (WOElement *)buildElement:(id)_element templateBuilder:(id)_b { static Class ChildRefClass = Nil; NSMutableDictionary *bindings; NSArray *children; NSString *cid; NSString *tagName; NSString *compName; if (![[_element namespaceURI] isEqualToString:XMLNS_OD_BIND]) { if (debugLogger) { [self debugWithFormat: @"do not process element, not in bind namespace: %@", _element]; } return nil; } tagName = [_element tagName]; compName = nil; if ([tagName isEqualToString:@"script"]) return [self processScriptElement:_element templateBuilder:_b]; if ([tagName isEqualToString:@"component"]) { compName = [_element attribute:@"className" namespaceURI:XMLNS_OD_BIND]; if ([compName length] == 0) { compName = [_element attribute:@"classname" namespaceURI:XMLNS_OD_BIND]; } if ([compName length] == 0) compName = [_element attribute:@"name" namespaceURI:XMLNS_OD_BIND]; /* check whether we should use a "live" reference to a component object */ if ([compName length] == 0) { NSString *value; value = [_element attribute:@"value" namespaceURI:XMLNS_OD_BIND]; if ([value length] > 0) { return [self buildComponentReferenceElement:_element templateBuilder:_b]; } } if ([compName length] == 0) { [self logWithFormat: @"missing 'name' or 'value' attribute in var:component: %@", [_element attributes]]; return nil; } } else { [self logWithFormat:@"Creating component %@ using tag. " @" is preferred !", _element, _element]; } if (debugLogger) [debugLogger debugWithFormat:@"creating static component reference: %@", _element]; if (ChildRefClass == Nil) ChildRefClass = NSClassFromString(@"WOChildComponentReference"); cid = [_b uniqueIDForNode:_element]; if (debugLogger) [debugLogger debugWithFormat:@"BUILD Component(%@): %@", cid, _element]; /* construct child elements */ children = [_element hasChildNodes] ? [_b buildNodes:[_element childNodes] templateBuilder:_b] : (NSArray *)nil; [children autorelease]; if (compName == nil) compName = [_element tagName]; bindings = [self associationsForAttributes:[_element attributes] templateBuilder:_b]; if (debugLogger) [debugLogger debugWithFormat:@"using bindings: %@", bindings]; [_b registerSubComponentWithId:cid componentName:compName bindings:bindings]; return [[ChildRefClass alloc] initWithName:cid associations:nil contentElements:children]; } /* debugging */ - (BOOL)isDebuggingEnabled { return debugLogger != nil; } @end /* WOxComponentElemBuilder */ SOPE/sope-appserver/NGObjWeb/Templates/README-Templates.txt0000644000000000000000000001100015004363604022253 0ustar rootrootHow Templates Work ... ====================== In general we have two kinds of templates, XML based ones and "hash" based ones. The 'hash' templates are simple scanners for strings which start and end with "<#" and "">blah Since unlike the XML parser the hash parser only scans for "<#", this is OK. - hash templates use "wod" files for declarations which may or may not improve the visual clutter in the template itself - XML templates do not need to have a 1:1 mapping from tag to WODynamicElement and the mapping between tag and element is completely controlled by the builder while for hash templates you always use the actuall WODynamicElement subclass name in the .wod file Class Overview ============== WOTemplate (WOElement) - an WOElement subclass - this represents the 'real' root element of the template and contains some additional information like the URL it was loaded from and the subcomponents declared in the template - an WOTemplate object will be bound to a WOComponent once instantiated WOSubcomponentInfo - used in WOTemplate to track information on the subcomponents declared in the template (like bindings and component name) - if a WOComponent is instantiated this will be used to construct the subcomponents WODParser - a parser for the .wod file format - works someone like a SAX parser and requires a delegate to collect the actual information out of the parsed objects WOHTMLParser - the parser for the "hash" template format - requires a callback for instantiation of dynamic elements WOComponentScript / WOComponentScriptPart - this is used to collect server side template scripts declared in an XML file or or in a name-associated file (eg Main.js). sample: - a WOComponentScriptPart is one entry while WOComponentScript is the set of all entries (which usually will be joined into one script for evaluation) WOTemplateBuilder - the common superclass for the XML and hash based builder classes - also acts as the build "registry" + (WOTemplateBuilder *)templateBuilderForURL:(NSURL *)_url this currently returns the WOxTemplateBuilder for .wox extensions and the hash builder for all other templates - one API method: - (WOTemplate *)buildTemplateAtURL:(NSURL *)_url WOWrapperTemplateBuilder (WOTemplateBuilder) - subclass of WOTemplateBuilder for "hash" templates - uses WOHTMLParser and WODParser for processing .wo wrappers - supports language projects inside wrappers (eg a.wo/English.lproj/a.html) - looks for JavaScript component scripts (Name.js files) _WODFileEntry - used in WOWrapperTemplateBuilder - somewhat like WOSubcomponentInfo, contains information on a parsed WOD entry (will be stored in a name=>entry map) WOxTemplateBuilder (WOTemplateBuilder) - subclass of WOTemplateBuilder for XML templates (also called 'wox' templates) - defaults: WOxBuilderClasses - also scans for "WOxElemBuilder" resources using NGBundleManager - this one parses a DOM tree from the "build-URL" and then delegates the actual building to so called "element builders" (subclasses of WOxElemBuilder) WOxElemBuilder - superclass for all other element builders - has a 'nextBuilder' for passing on unsupported tags WOxElemBuilderComponentInfo - somewhat like _WODFileEntry, - used in WOxElemBuilder for tracking subcomponent references - some API: - (WOElement *)buildTemplateFromDocument:(id)_document; - (WOElement *)buildNode:(id)_node templateBuilder:(id)_bld; - (NSArray *)buildNodes:(id)_node templateBuilder:(id)_bld; - also manages WOAssociation to namespace mappings, binds a WOAssociation subclass to a certain namespace, eg: "var" => "WOKeyValueAssociation" "" WOxComponentElemBuilder (WOxElemBuilder) - build subcomponent references: - WOChildComponentReference - WOComponentReference (but currently no WOSwitchComponent?) - processes: ""); } /* description */ - (NSString *)associationDescription { NSMutableString *str = [[NSMutableString alloc] init]; str = [NSMutableString stringWithCapacity:64]; if (self->scriptFile) [str appendFormat:@" file=%@", self->scriptFile]; if (self->scriptString) [str appendFormat:@" string=%@", self->scriptString]; if (self->scriptSource) [str appendFormat:@" source=%@", self->scriptSource]; if (self->hideInComment) [str appendFormat:@" hide=%@", self->hideInComment]; return str; } @end /* WOJavaScript */ SOPE/sope-appserver/NGObjWeb/DynamicElements/WOImage.m0000644000000000000000000002547615004363604021440 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "WOImage.h" @interface _WOTemporaryImage : NSObject @end @interface _WODynamicImage : WOImage /* new in WO4 */ { WOAssociation *data; WOAssociation *mimeType; WOAssociation *key; } @end @interface _WOElementImage : WOImage { WOAssociation *value; // image data (eg from a database) } @end @interface _WOExternalImage : WOImage { WOAssociation *src; // absolute URL } @end @interface WOImage(PrivateMethods) - (NSString *)associationDescription; @end #include "WOElement+private.h" #include #include #include "decommon.h" #if NeXT_Foundation_LIBRARY || APPLE_FOUNDATION_LIBRARY @interface NSObject(Miss) - (void)subclassResponsibility:(SEL)cmd; @end #endif @implementation WOImage + (id)allocWithZone:(NSZone *)zone { static Class WOImageClass = Nil; static _WOTemporaryImage *temporaryImage = nil; if (WOImageClass == Nil) WOImageClass = [WOImage class]; if (temporaryImage == nil) temporaryImage = [_WOTemporaryImage allocWithZone:zone]; return (self == WOImageClass) ? (id)temporaryImage : (id)NSAllocateObject(self, 0, zone); } /* request handling */ - (id)invokeActionForRequest:(WORequest *)_rq inContext:(WOContext *)_ctx { NSLog(@"no value configured for WOImage %@", self); return nil; } - (void)_appendSrcToResponse:(WOResponse *)_resp inContext:(WOContext *)_ctx { [self subclassResponsibility:_cmd]; } - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { if ([_ctx isRenderingDisabled] || [[_ctx request] isFromClientComponent]) return; WOResponse_AddBytesLen(_response, "otherTagString) { WOResponse_AddBytesLen(_response, " ", 1); WOResponse_AddString(_response, [self->otherTagString stringValueInComponent: [_ctx component]]); } WOResponse_AddEmptyCloseParens(_response, _ctx); } @end /* WOImage */ @implementation _WODynamicImage - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_t { if ((self = [super initWithName:_name associations:_config template:_t])) { self->data = OWGetProperty(_config, @"data"); self->mimeType = OWGetProperty(_config, @"mimeType"); self->key = OWGetProperty(_config, @"key"); #if DEBUG if ([_config objectForKey:@"value"] || [_config objectForKey:@"filename"] || [_config objectForKey:@"framework"] || [_config objectForKey:@"src"]) { NSLog(@"WARNING: inconsistent association settings in WOImage !" @" (assign only one of value, src, data or filename)"); } #endif } return self; } - (void)dealloc { [self->key release]; [self->data release]; [self->mimeType release]; [super dealloc]; } /* dynamic delivery */ - (id)invokeActionForRequest:(WORequest *)_rq inContext:(WOContext *)_ctx { WOComponent *sComponent = [_ctx component]; NSData *adata; NSString *atype; WOResponse *response; adata = [self->data valueInComponent:sComponent]; atype = [self->mimeType stringValueInComponent:sComponent]; response = [_ctx response]; [response setContent:adata]; [response setHeader: (atype != nil ? atype : (NSString *)@"application/octet-stream") forKey:@"content-type"]; return response; } /* HTML generation */ - (void)_appendSrcToResponse:(WOResponse *)_resp inContext:(WOContext *)_ctx { WOResourceManager *rm; WOComponent *sComponent; NSString *kk, *url; sComponent = [_ctx component]; if ((kk = [self->key stringValueInComponent:sComponent]) == nil) { WOResponse_AddString(_resp, [_ctx componentActionURL]); return; } if ((rm = [[_ctx component] resourceManager]) == nil) rm = [[_ctx application] resourceManager]; [rm setData:[self->data valueInComponent:sComponent] forKey:kk mimeType:[self->mimeType stringValueInComponent:sComponent] session:[_ctx hasSession] ? [_ctx session] : nil]; url = [_ctx urlWithRequestHandlerKey: [WOApplication resourceRequestHandlerKey] path:[@"/" stringByAppendingString:kk] queryString:nil]; WOResponse_AddString(_resp, url); } /* description */ - (NSString *)associationDescription { NSMutableString *str = [NSMutableString stringWithCapacity:64]; if (self->data) [str appendFormat:@" data=%@", self->data]; if (self->mimeType) [str appendFormat:@" mimeType=%@", self->mimeType]; if (self->key) [str appendFormat:@" key=%@", self->key]; [str appendString:[super associationDescription]]; return str; } @end /* _WODynamicImage */ @implementation _WOElementImage - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_t { if ((self = [super initWithName:_name associations:_config template:_t])) { self->value = OWGetProperty(_config, @"value"); #if DEBUG if ([_config objectForKey:@"data"] || [_config objectForKey:@"mimeType"] || [_config objectForKey:@"key"] || [_config objectForKey:@"filename"] || [_config objectForKey:@"framework"] || [_config objectForKey:@"src"]) { NSLog(@"WARNING: inconsistent association settings in WOImage !" @" (assign only one of value, src, data or filename)"); } #endif } return self; } - (void)dealloc { RELEASE(self->value); [super dealloc]; } /* dynamic delivery */ - (id)invokeActionForRequest:(WORequest *)_rq inContext:(WOContext *)_ctx { WOElement *element; if ((element = [self->value valueInComponent:[_ctx component]]) == nil) { NSLog(@"WARNING: missing element value for WOImage %@", self); return nil; } [element appendToResponse:[_ctx response] inContext:_ctx]; return [_ctx response]; } /* HTML generation */ - (void)_appendSrcToResponse:(WOResponse *)_resp inContext:(WOContext *)_ctx { WOResponse_AddString(_resp, [_ctx componentActionURL]); } /* description */ - (NSString *)associationDescription { NSMutableString *str = [NSMutableString stringWithCapacity:64]; [str appendFormat:@" value=%@", self->value]; [str appendString:[super associationDescription]]; return str; } @end /* _WOElementImage */ @implementation _WOExternalImage - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_t { if ((self = [super initWithName:_name associations:_config template:_t])) { self->src = OWGetProperty(_config, @"src"); #if DEBUG if ([_config objectForKey:@"data"] || [_config objectForKey:@"mimeType"] || [_config objectForKey:@"key"] || [_config objectForKey:@"filename"] || [_config objectForKey:@"framework"] || [_config objectForKey:@"value"]) { NSLog(@"WARNING: inconsistent association settings in WOImage !" @" (assign only one of value, src, data or filename)"); } #endif } return self; } - (void)dealloc { [self->src release]; [super dealloc]; } /* HTML generation */ - (void)_appendSrcToResponse:(WOResponse *)_resp inContext:(WOContext *)_ctx { NSString *s; s = [self->src stringValueInComponent:[_ctx component]]; if (s != nil) [_resp appendContentHTMLAttributeValue:s]; } /* description */ - (NSString *)associationDescription { NSMutableString *str; str = [NSMutableString stringWithCapacity:64]; [str appendFormat:@" src=%@", self->src]; [str appendString:[super associationDescription]]; return str; } @end /* _WOExternalImage */ @implementation _WOTemporaryImage - (id)initWithName:(NSString *)_n associations:(NSDictionary *)_config template:(WOElement *)_t { // TODO: cache class objects? Class imageClass = Nil; WOAssociation *a; if ((a = [_config objectForKey:@"filename"])) { if ([a isValueConstant] && [_config objectForKey:@"framework"] == nil) imageClass = NSClassFromString(@"_WOConstResourceImage"); else imageClass = NSClassFromString(@"_WOResourceImage"); } else if ([_config objectForKey:@"src"]) imageClass = [_WOExternalImage class]; else if ([_config objectForKey:@"value"]) imageClass = [_WOElementImage class]; else if ([_config objectForKey:@"data"]) imageClass = [_WODynamicImage class]; else { NSLog(@"WARNING: missing data source association for WOImage !"); } return [[imageClass alloc] initWithName:_n associations:_config template:_t]; } - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_associations contentElements:(NSArray *)_contents { WOAssociation *a; Class imageClass = Nil; if ((a = [_associations objectForKey:@"filename"])) { if ([a isValueConstant] && [_associations objectForKey:@"framework"]==nil) imageClass = NSClassFromString(@"_WOConstResourceImage"); else imageClass = NSClassFromString(@"_WOResourceImage"); } else if ([_associations objectForKey:@"src"]) imageClass = [_WOExternalImage class]; else if ([_associations objectForKey:@"value"]) imageClass = [_WOElementImage class]; else if ([_associations objectForKey:@"data"]) imageClass = [_WODynamicImage class]; else { NSLog(@"WARNING: missing data source association for WOImage !"); } return [[imageClass alloc] initWithName:_name associations:_associations contentElements:_contents]; } - (void)dealloc { [self errorWithFormat:@"called dealloc on %@", self]; #if DEBUG abort(); #endif return; // same issue with gcc 4.1 on Linux ..., make Tiger GCC happy if (0) [super dealloc]; } @end /* _WOTemporaryImage */ SOPE/sope-appserver/NGObjWeb/DynamicElements/WOComponentReference.m0000644000000000000000000001344315004363604024166 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "WOComponentReference.h" #include "WOElement+private.h" #include "WOContext+private.h" #include "WOComponent+private.h" #include "decommon.h" @interface WOContext(ComponentStackCount) - (unsigned)componentStackCount; @end @implementation WOComponentReference static int profileComponents = -1; static BOOL coreOnRecursion = NO; static BOOL debugOn = NO; static Class NSDateClass = Nil; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; profileComponents = [[ud objectForKey:@"WOProfileComponents"] boolValue] ? 1 : 0; coreOnRecursion = [ud boolForKey:@"WOCoreOnRecursiveSubcomponents"]; NSDateClass = [NSDate class]; } - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_c { if ((self = [super initWithName:_name associations:_config template:_c])) { self->containsForm = YES; self->activeComponent = OWGetProperty(_config, @"component"); self->bindings = [_config copyWithZone:[self zone]]; [(NSMutableDictionary *)_config removeAllObjects]; self->template = [_c retain]; } return self; } - (void)dealloc { [self->template release]; [self->bindings release]; [self->activeComponent release]; [self->child release]; [super dealloc]; } /* accessors */ - (WOComponent *)childComponent { return self->child; // THREAD } static inline void _updateComponent(WOComponentReference *self, WOContext *_ctx) { /* Note: this is rather dangerous. We keep a processing state - the 'child' ivar containing the component - inside the dynamic element. Yet elements are supposed to be stateless. As long as we are single-threaded this should not be a problem, but keep in mind that this element is NOT reentrant. */ // THREAD WOComponent *newChild; if (self->activeComponent == nil) return; newChild = [self->activeComponent valueInComponent:[_ctx component]]; #if 0 if (newChild == nil) { [[_ctx component] logWithFormat: @"missing child (got nil) " @"(element=%@, association=%@, component=%@).", self, self->activeComponent, [[_ctx component] name]]; } #endif if (newChild != self->child) { // THREAD #if 0 NSLog(@"switched component %@ => %@ ...", [self->child name], [newChild name]); #endif ASSIGN(self->child, newChild); [newChild setParent:[_ctx component]]; [newChild setBindings:self->bindings]; } } /* handling requests */ - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx { _updateComponent(self, _ctx); if (self->child != nil) { [_ctx enterComponent:self->child content:self->template]; [self->child takeValuesFromRequest:_req inContext:_ctx]; [_ctx leaveComponent:self->child]; } } - (id)invokeActionForRequest:(WORequest *)_req inContext:(WOContext *)_ctx { id result = nil; _updateComponent(self, _ctx); if (self->child != nil) { [_ctx enterComponent:self->child content:self->template]; result = [self->child invokeActionForRequest:_req inContext:_ctx]; [_ctx leaveComponent:self->child]; } return result; } /* generate response */ - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { WOComponent *parent; parent = [_ctx component]; _updateComponent(self, _ctx); if (self->child == parent) { [self warnWithFormat:@"recursive call of component: %@", parent]; if (coreOnRecursion) abort(); } if (self->child != nil) { NSTimeInterval st = 0.0; if (profileComponents) st = [[NSDateClass date] timeIntervalSince1970]; [_ctx enterComponent:self->child content:self->template]; [self->child appendToResponse:_response inContext:_ctx]; [_ctx leaveComponent:self->child]; if (profileComponents) { NSTimeInterval diff; int i; diff = [[NSDateClass date] timeIntervalSince1970] - st; for (i = [_ctx componentStackCount]; i >= 0; i--) printf(" "); printf("[%s %s]: %0.3fs\n", [[child name] cString], sel_getName(_cmd), diff); } } else if (debugOn) { [self debugWithFormat:@"missing component for reference: %@", self->activeComponent]; if (![_ctx isRenderingDisabled]) { [_response appendContentHTMLString:@"[missing component for reference: "]; [_response appendContentHTMLString:[self->activeComponent description]]; [_response appendContentHTMLString:@"]"]; } } } /* description */ - (NSString *)description { NSMutableString *desc; desc = [NSMutableString stringWithCapacity:64]; [desc appendFormat:@"<%@[0x%p]:", NSStringFromClass([self class]), self]; if (self->child != nil) { [desc appendFormat:@" child=%@[0x%p] childName=%@", NSStringFromClass([self->child class]), self->child, [self->child name]]; } [desc appendString:@">"]; return desc; } @end /* WOComponentReference */ SOPE/sope-appserver/NGObjWeb/DynamicElements/WOGenericElement.m0000644000000000000000000001607715004363604023301 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "WOGenericElement.h" #include "WOElement+private.h" #include "decommon.h" #include #include // TODO: we should be able to store the key as ASCII ? // TODO: does it make sense to resolve constant associations ? // all constant assocs could be joined at init time ? #define TagNameType_Assoc 0 #define TagNameType_String 1 #define TagNameType_ASCII 2 typedef struct { NSString *key; WOAssociation *value; } OWAttribute; @implementation WOGenericElement - (id)initWithElement:(id)_element templateBuilder:(WOxElemBuilder *)_builder { NSString *name; NSMutableDictionary *assocs; NSArray *children; id attrs; unsigned lcount; name = [_element tagName]; /* construct associations */ assocs = nil; attrs = [_element attributes]; if ((lcount = [attrs length]) > 0) assocs = [_builder associationsForAttributes:attrs]; if (assocs == nil) { assocs = [NSMutableDictionary dictionaryWithObject: [_builder associationForValue:[_element tagName]] forKey:@"elementName"]; } else { [assocs setObject:[_builder associationForValue:[_element tagName]] forKey:@"elementName"]; } /* construct child elements */ children = [_element hasChildNodes] ? [_builder buildNodes:[_element childNodes] templateBuilder:_builder] : (NSArray *)nil; [children autorelease]; /* construct self ... */ return (WOGenericElement*)[(WODynamicElement *)self initWithName:name associations:assocs contentElements:children]; } - (BOOL)_isASCIIString:(NSString *)_s { /* TODO: not a very fast check for an ASCII string ... */ return [_s dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:NO] != nil ? YES : NO; } - (void)_setupAssociations:(NSMutableDictionary *)_associations { NSEnumerator *keys; NSString *key = nil; OWAttribute *mapping = NULL; if (self->count == 0) return; keys = [_associations keyEnumerator]; self->mappings = calloc(self->count, sizeof(OWAttribute)); for (mapping = self->mappings; (key = [keys nextObject]); mapping++) { WOAssociation *value; value = [_associations objectForKey:key]; mapping->key = [key copy]; mapping->value = [value retain]; } [_associations removeAllObjects]; } - (void)_configureForConstantElementName:(NSString *)s { if ([self _isASCIIString:s]) { unsigned char *cs; unsigned len; len = [s cStringLength]; cs = malloc(len + 2); [s getCString:(char *)cs]; cs[len] = '\0'; self->tagName = cs; self->tagNameType = TagNameType_ASCII; } else { /* a tagname which is not ASCII ?? */ self->tagName = [s copy]; self->tagNameType = TagNameType_String; } } - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_associations template:(WOElement *)_template { self = [super initWithName:_name associations:_associations template:_template]; if (self) { WOAssociation *a; self->tagName = a = OWGetProperty(_associations, @"elementName"); self->tagNameType = TagNameType_Assoc; self->count = [_associations count]; if ([a isValueConstant]) { [self _configureForConstantElementName:[a stringValueInComponent:nil]]; [a release]; a = nil; } if (self->count > 0) [self _setupAssociations:(NSMutableDictionary *)_associations]; } return self; } - (void)dealloc { if (self->mappings) { OWAttribute *map; unsigned cnt; for (cnt = 0, map = self->mappings; cnt < self->count; cnt++, map++) { [map->key release]; map->key = nil; [map->value release]; map->value = nil; } if (self->mappings) free(self->mappings); self->mappings = NULL; } switch (self->tagNameType) { case TagNameType_Assoc: [(id)self->tagName release]; break; case TagNameType_String: [(id)self->tagName release]; break; case TagNameType_ASCII: if (self->tagName) free(self->tagName); break; default: [self errorWithFormat:@"unknown tag-name-type %i !", self->tagNameType]; break; } [super dealloc]; } /* response generation */ - (void)_appendAttributesToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { // TODO: this seems to take some time during profiling, maybe we can // optimize that (ASCII keys, constant assocs) WOComponent *sComponent = [_ctx component]; OWAttribute *map; unsigned cnt; static Class WOBoolAssociationKlass = Nil; if (!WOBoolAssociationKlass) WOBoolAssociationKlass = NSClassFromString(@"WOBoolAssociation"); for (cnt = 0, map = self->mappings; cnt < self->count; cnt++, map++) { register id value; if ((value = [map->value valueInComponent:sComponent]) == nil) continue; WOResponse_AddChar(_response, ' '); WOResponse_AddString(_response, map->key); if (![map->value isKindOfClass: WOBoolAssociationKlass]) { WOResponse_AddCString(_response, "=\""); WOResponse_AddHtmlString(_response, [value stringValue]); WOResponse_AddChar(_response, '"'); } } } - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { WOComponent *sComponent; NSString *tag; if ([_ctx isRenderingDisabled] || [[_ctx request] isFromClientComponent]) return; sComponent = [_ctx component]; WOResponse_AddChar(_response, '<'); switch (self->tagNameType) { case TagNameType_Assoc: tag = [(id)self->tagName stringValueInComponent:sComponent]; WOResponse_AddString(_response, tag); break; case TagNameType_String: WOResponse_AddString(_response, self->tagName); break; case TagNameType_ASCII: WOResponse_AddCString(_response, self->tagName); break; } [self _appendAttributesToResponse:_response inContext:_ctx]; if (self->otherTagString) { WOResponse_AddChar(_response, ' '); WOResponse_AddString(_response, [self->otherTagString stringValueInComponent: sComponent]); } WOResponse_AddEmptyCloseParens(_response, _ctx); } @end /* WOGenericElement */ SOPE/sope-appserver/NGObjWeb/DynamicElements/WOInput.m0000644000000000000000000000767215004363604021513 0ustar rootroot/* Copyright (C) 2000-2006 SKYRIX Software AG Copyright (C) 2006 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "WOInput.h" #include "WOElement+private.h" #include "decommon.h" @implementation WOInput static BOOL takeValueDebugOn = YES; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; if ((takeValueDebugOn = [ud boolForKey:@"WODebugTakeValues"])) NSLog(@"WOInput: WODebugTakeValues on."); } - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_associations template:(WOElement *)_rootChild { self = [super initWithName:_name associations:_associations template:_rootChild]; if (self) { self->containsForm = YES; self->name = OWGetProperty(_associations, @"name"); self->type = OWGetProperty(_associations, @"type"); self->value = OWGetProperty(_associations, @"value"); self->disabled = OWGetProperty(_associations, @"disabled"); if ([_associations objectForKey:@"NAME"]) { [self warnWithFormat:@"found 'NAME' association in element %@, " @"'name' is probably the right thing.", _name]; } } return self; } - (void)dealloc { [self->name release]; [self->type release]; [self->value release]; [self->disabled release]; [super dealloc]; } /* form support */ NSString *OWFormElementName(WOInput *self, WOContext *_ctx) { NSString *name; if (self->name == nil) return [_ctx elementID]; if ((name = [self->name stringValueInComponent:[_ctx component]]) != nil) return name; [[_ctx component] warnWithFormat: @"in element %@, 'name' attribute configured (%@)," @"but no name assigned (using elementID as name) !", self, self->name]; return [_ctx elementID]; } /* taking form values */ - (id)parseFormValue:(id)_value inContext:(WOContext *)_ctx { /* redefined in subclasses */ return _value; } - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx { NSString *formName; id formValue = nil; if ([self->disabled boolValueInComponent:[_ctx component]]) return; formName = OWFormElementName(self, _ctx); if ((formValue = [_req formValueForKey:formName]) == nil) // TODO: is this correct? return; if (takeValueDebugOn) { [self logWithFormat: @"%s(%@): form=%@ ctx=%@ value=%@ ..", __PRETTY_FUNCTION__, [_ctx elementID], formName, [_ctx contextID], formValue]; } if ([self->value isValueSettable]) { formValue = [self parseFormValue:formValue inContext:_ctx]; [self->value setStringValue:formValue inComponent:[_ctx component]]; } else if (self->value != nil) { [self logWithFormat: @"%s: form value is not settable: %@", __PRETTY_FUNCTION__, self->value]; } } /* description */ - (NSString *)associationDescription { NSMutableString *str; str = [NSMutableString stringWithCapacity:128]; if (self->value != nil) [str appendFormat:@" value=%@", self->value]; if (self->name != nil) [str appendFormat:@" name=%@", self->name]; if (self->type != nil) [str appendFormat:@" type=%@", self->value]; if (self->disabled) [str appendFormat:@" disabled=%@", self->disabled]; return str; } @end /* WOInput */ SOPE/sope-appserver/NGObjWeb/DynamicElements/WORadioButtonList.api0000644000000000000000000000125215004363604024003 0ustar rootroot SOPE/sope-appserver/NGObjWeb/DynamicElements/WOSetCursor.api0000644000000000000000000000027215004363604022647 0ustar rootroot SOPE/sope-appserver/NGObjWeb/DynamicElements/WOForm.m0000644000000000000000000003176415004363604021316 0ustar rootroot/* Copyright (C) 2000-2006 SKYRIX Software AG Copyright (C) 2006 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "WOForm.h" #include "WOElement+private.h" #include "WOInput.h" #include "WOContext+private.h" #include #include "decommon.h" @implementation WOForm static int debugTakeValues = -1; - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_c { if (debugTakeValues == -1) { debugTakeValues = [[NSUserDefaults standardUserDefaults] boolForKey:@"WODebugTakeValues"] ? 1 : 0; if (debugTakeValues) NSLog(@"WOForm: WODebugTakeValues on."); } if ((self = [super initWithName:_name associations:_config template:_c])) { WOAssociation *sidInUrlAssoc; id tmp; self->containsForm = YES; sidInUrlAssoc = OWGetProperty(_config, @"?wosid"); self->action = OWGetProperty(_config, @"action"); self->href = OWGetProperty(_config, @"href"); self->pageName = OWGetProperty(_config, @"pageName"); self->queryDictionary = OWGetProperty(_config, @"queryDictionary"); self->queryParameters = OWExtractQueryParameters(_config); self->actionClass = OWGetProperty(_config, @"actionClass"); self->directActionName = OWGetProperty(_config, @"directActionName"); self->method = OWGetProperty(_config, @"method"); self->fragmentIdentifier = OWGetProperty(_config, @"fragmentIdentifier"); self->sidInUrl = (sidInUrlAssoc != nil) ? [sidInUrlAssoc boolValueInComponent:nil] : YES; if ((tmp = OWGetProperty(_config, @"multipleSubmit")) != nil) { /* not required with SOPE, for WO compatibility */ [tmp release]; } self->template = [_c retain]; } return self; } - (void)dealloc { [self->fragmentIdentifier release]; [self->method release]; [self->template release]; [self->actionClass release]; [self->directActionName release]; [self->queryDictionary release]; [self->queryParameters release]; [self->action release]; [self->pageName release]; [self->href release]; [super dealloc]; } /* handle active form elements */ - (id)template { return self->template; } /* handling requests */ - (void)takeValuesFromRequest:(WORequest *)_rq inContext:(WOContext *)_ctx { static int alwaysPassIn = -1; if (alwaysPassIn == -1) { alwaysPassIn = [[[NSUserDefaults standardUserDefaults] objectForKey:@"WOFormAlwaysPassDown"] boolValue] ? 1 : 0; } if ([_ctx isInForm]) { [self errorWithFormat:@"(%s): another form is already active in context !", __PRETTY_FUNCTION__]; } [_ctx setInForm:YES]; { WOComponent *sComponent = [_ctx component]; BOOL doTakeValues = NO; if (self->queryParameters != nil) { /* apply values to ?style parameters */ NSEnumerator *keys; NSString *key; keys = [self->queryParameters keyEnumerator]; while ((key = [keys nextObject])) { WOAssociation *assoc; id value; assoc = [self->queryParameters objectForKey:key]; value = [_rq formValueForKey:key]; [assoc setValue:value inComponent:sComponent]; } } // TODO: explain this href comparison if ([[self->href stringValueInComponent:sComponent] isEqualToString:[_rq uri]]) { if (debugTakeValues) { NSArray *formValues = [_rq formValueKeys]; NSLog(@"%s: we are uri active (uri=%@): %@ ..", __PRETTY_FUNCTION__, [_rq uri], formValues); } doTakeValues = YES; } else if ([[_ctx elementID] isEqualToString:[_ctx senderID]]) { if (debugTakeValues) { NSArray *formValues = [_rq formValueKeys]; NSLog(@"%s: we are elem active (eid=%@): %@ ..", __PRETTY_FUNCTION__, [_ctx elementID], formValues); } doTakeValues = YES; } else if (alwaysPassIn) { // Note: this does not call the component! Bug? (see 'else' below) if (debugTakeValues) NSLog(@"%s: taking values from foreign request ",__PRETTY_FUNCTION__); doTakeValues = YES; } else { /* finally, let the component decide */ doTakeValues = [sComponent shouldTakeValuesFromRequest:_rq inContext:_ctx]; if (debugTakeValues) { NSLog(@"%s: component should take values: %s ", __PRETTY_FUNCTION__, doTakeValues ? "yes" : "no"); } } if (doTakeValues) { if (debugTakeValues) NSLog(@"%s: taking values ...", __PRETTY_FUNCTION__); [self->template takeValuesFromRequest:_rq inContext:_ctx]; if (debugTakeValues) NSLog(@"%s: did take values.", __PRETTY_FUNCTION__); } else if (debugTakeValues) { [sComponent debugWithFormat: @"WOForm: *not* taking values from foreign request " @"(id='%@' vs sid='%@') ...", [_ctx elementID], [_ctx senderID]]; } } if (![_ctx isInForm]) { [[_ctx component] errorWithFormat:@"(%s:%d): -isInForm is NO !!!", __PRETTY_FUNCTION__, __LINE__]; } else [_ctx setInForm:NO]; } - (id)invokeActionForRequest:(WORequest *)_rq inContext:(WOContext *)_ctx { id result = nil; [_ctx setInForm:YES]; if ([_ctx currentElementID] == nil) { WOElement *element; if ((element = [_ctx activeFormElement])) { #if 1 result = [self->template invokeActionForRequest:_rq inContext:_ctx]; RETAIN(result); #else /* wrong - need to setup correct component stack */ result = [[element invokeActionForRequest:_rq inContext:_ctx] retain]; #endif } else if (self->action) { result = [self executeAction:self->action inContext:_ctx]; } else if (self->pageName) { NSString *pname = nil; WOComponent *page = nil; pname = [self->pageName stringValueInComponent:[_ctx component]]; page = [[_ctx application] pageWithName:pname inContext:_ctx]; if (page == nil) { [[_ctx session] logWithFormat: @"%@[0x%p]: did not find page with name %@ !", NSStringFromClass([self class]), self, pname]; } NSLog(@"showing page %@", page); result = page; } } else result = [self->template invokeActionForRequest:_rq inContext:_ctx]; [_ctx setInForm:NO]; return result; } /* generate response */ - (NSString *)_addHrefToResponse:(WOResponse *)_r inContext:(WOContext *)_ctx { /* post to a fixed hyperlink */ WOComponent *sComponent = [_ctx component]; NSString *s; NSDictionary *d; s = [self->href stringValueInComponent:sComponent]; d = [self->queryDictionary valueInComponent:sComponent]; WOResponse_AddString(_r, s); return [self queryStringForQueryDictionary:d andQueryParameters:self->queryParameters inContext:_ctx]; } - (NSString *)_addActionToResponse:(WOResponse *)_r inContext:(WOContext *)_c { /* post to a component action */ NSDictionary *d; WOResponse_AddString(_r, [_c componentActionURL]); d = [self->queryDictionary valueInComponent:[_c component]]; return [self queryStringForQueryDictionary:d andQueryParameters:self->queryParameters inContext:_c]; } - (void)_addDirectActionToResponse:(WOResponse *)_r inContext:(WOContext *)_c { /* a direct action link */ WOComponent *sComponent; NSString *daClass = nil; NSString *daName = nil; NSMutableDictionary *qd; NSDictionary *tmp; NSString *uri; sComponent = [_c component]; daClass = [self->actionClass stringValueInComponent:sComponent]; daName = [self->directActionName stringValueInComponent:sComponent]; if (daClass != nil) { if (daName != nil) { if (![daClass isEqualToString:@"DirectAction"]) daName = [NSString stringWithFormat:@"%@/%@", daClass, daName]; } else daName = daClass; } qd = [NSMutableDictionary dictionaryWithCapacity:16]; /* add query dictionary */ if (self->queryDictionary) { if ((tmp = [self->queryDictionary valueInComponent:sComponent])) [qd addEntriesFromDictionary:tmp]; } /* add ?style parameters */ if (self->queryParameters) { NSEnumerator *keys; NSString *key; keys = [self->queryParameters keyEnumerator]; while ((key = [keys nextObject])) { id assoc, value; assoc = [self->queryParameters objectForKey:key]; value = [assoc stringValueInComponent:sComponent]; [qd setObject:(value != nil ? value : (id)@"") forKey:key]; } } /* add session ID */ if (self->sidInUrl && [_c hasSession]) { WOSession *sn; sn = [_c session]; [qd setObject:[sn sessionID] forKey:WORequestValueSessionID]; if (![sn isDistributionEnabled]) { [qd setObject:[[WOApplication application] number] forKey:WORequestValueInstance]; } } else if (self->sidInUrl) { /* Note: this is not a problem! Eg this occurs on the OGo Main component */ [self debugWithFormat: @"Note: session-id is requested, but no session is active?"]; } uri = [_c directActionURLForActionNamed:daName queryDictionary:qd]; WOResponse_AddString(_r, uri); } - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { WOComponent *sComponent; NSString *queryString = nil; if ([_ctx isRenderingDisabled] || [[_ctx request] isFromClientComponent]) { [self->template appendToResponse:_response inContext:_ctx]; return; } sComponent = [_ctx component]; if ([_ctx isInForm]) [self warnWithFormat:@"detected nested WOForm, component: %@", sComponent]; else [_ctx setInForm:YES]; WOResponse_AddCString(_response, "href != nil || self->directActionName != nil || self->actionClass != nil) { WOResponse_AddCString(_response, " action=\""); if (self->href != nil) queryString = [self _addHrefToResponse:_response inContext:_ctx]; else if (self->directActionName != nil || self->actionClass != nil) [self _addDirectActionToResponse:_response inContext:_ctx]; else queryString = [self _addActionToResponse:_response inContext:_ctx]; if (self->fragmentIdentifier != nil) { NSString *f = [self->fragmentIdentifier stringValueInComponent:sComponent]; if ([f isNotEmpty]) { [_response appendContentCharacter:'#']; WOResponse_AddString(_response, f); } } /* append the query string */ if (queryString != nil) { [_response appendContentCharacter:'?']; WOResponse_AddString(_response, queryString); } WOResponse_AddCString(_response, "\""); } if (self->method != nil) { WOResponse_AddCString(_response, " method=\""); WOResponse_AddString(_response, [self->method stringValueInComponent:sComponent]); WOResponse_AddCString(_response, "\""); } else WOResponse_AddCString(_response, " method=\"post\""); [self appendExtraAttributesToResponse:_response inContext:_ctx]; if (self->otherTagString != nil) { WOResponse_AddChar(_response, ' '); WOResponse_AddString(_response, [self->otherTagString stringValueInComponent: sComponent]); } WOResponse_AddChar(_response, '>'); /* render form content */ [self->template appendToResponse:_response inContext:_ctx]; /* close form */ WOResponse_AddCString(_response, ""); [_ctx setInForm:NO]; } /* description */ - (NSString *)associationDescription { NSMutableString *str = [NSMutableString stringWithCapacity:64]; //[str appendString:[super associationDescription]]; if (self->action) [str appendFormat:@" action=%@", self->action]; if (self->href) [str appendFormat:@" href=%@", self->href]; if (self->pageName) [str appendFormat:@" page=%@", self->pageName]; if (self->actionClass) [str appendFormat:@" actionClass=%@", self->actionClass]; if (self->directActionName) [str appendFormat:@" directAction=%@", self->directActionName]; if (self->template) [str appendFormat:@" template=%@", self->template]; return str; } @end /* WOForm */ SOPE/sope-appserver/NGObjWeb/DynamicElements/WOHiddenField.m0000644000000000000000000000441615004363604022544 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "WOInput.h" @interface WOHiddenField : WOInput { // WODynamicElement: extraAttributes // WODynamicElement: otherTagString // WOInput: name // WOInput: value // WOInput: disabled } @end /* WOHiddenField */ #include "decommon.h" @implementation WOHiddenField /* generate response */ - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { NSString *v; BOOL isDisabled; if ([_ctx isRenderingDisabled] || [[_ctx request] isFromClientComponent]) return; isDisabled = [self->disabled boolValueInComponent:[_ctx component]]; if (isDisabled) { // TODO: this is correct for a _hidden_? v = [self->value stringValueInComponent:[_ctx component]]; [_response appendContentHTMLString:v]; return; } v = [self->value stringValueInComponent:[_ctx component]]; WOResponse_AddCString(_response, "otherTagString != nil) { WOResponse_AddChar(_response, ' '); WOResponse_AddString(_response, [self->otherTagString stringValueInComponent: [_ctx component]]); } WOResponse_AddEmptyCloseParens(_response, _ctx); } @end /* WOHiddenField */ SOPE/sope-appserver/NGObjWeb/DynamicElements/WOSwitchComponent.api0000644000000000000000000000030715004363604024041 0ustar rootroot SOPE/sope-appserver/NGObjWeb/DynamicElements/WOHyperlink.h0000644000000000000000000000241115004363604022336 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGObjWeb_WOHyperlink_H__ #define __NGObjWeb_WOHyperlink_H__ #include @class NSString; @class WOHyperlinkInfo; @interface WOHyperlink : WOHTMLDynamicElement { // WODynamicElement: extraAttributes // WODynamicElement: otherTagString } - (id)initWithName:(NSString *)_name hyperlinkInfo:(WOHyperlinkInfo *)_info template:(WOElement *)_t; @end /* WOHyperlink */ @interface _WOTemporaryHyperlink : NSObject @end #endif /* __NGObjWeb_WOHyperlink_H__ */ SOPE/sope-appserver/NGObjWeb/DynamicElements/WOVBScript.m0000644000000000000000000001010215004363604022066 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "WOElement+private.h" #include #include #include "decommon.h" @interface WOVBScript : WOHTMLDynamicElement { // WODynamicElement: extraAttributes // WODynamicElement: otherTagString @protected WOAssociation *scriptFile; WOAssociation *scriptString; WOAssociation *scriptSource; WOAssociation *hideInComment; } @end /* WOVBScript */ @implementation WOVBScript - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_tmpl { if ((self = [super initWithName:_name associations:_config template:_tmpl])) { self->scriptFile = OWGetProperty(_config, @"scriptFile"); self->scriptString = OWGetProperty(_config, @"scriptString"); self->scriptSource = OWGetProperty(_config, @"scriptSource"); self->hideInComment = OWGetProperty(_config, @"hideInComment"); } return self; } #if !LIB_FOUNDATION_BOEHM_GC - (void)dealloc { RELEASE(self->scriptFile); RELEASE(self->scriptString); RELEASE(self->scriptSource); RELEASE(self->hideInComment); [super dealloc]; } #endif // ******************** responder ******************** #define StrVal(__x__) [self->__x__ stringValueInComponent:sComponent] - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { WOComponent *sComponent; BOOL hide; if ([_ctx isRenderingDisabled] || [[_ctx request] isFromClientComponent]) return; sComponent = [_ctx component]; hide = [self->hideInComment boolValueInComponent:sComponent]; WOResponse_AddCString(_response, ""); } // description - (NSString *)associationDescription { NSMutableString *str = [[NSMutableString alloc] init]; if (self->scriptFile) [str appendFormat:@" file=%@", self->scriptFile]; if (self->scriptString) [str appendFormat:@" string=%@", self->scriptString]; if (self->scriptSource) [str appendFormat:@" source=%@", self->scriptSource]; if (self->hideInComment) [str appendFormat:@" hide=%@", self->hideInComment]; return AUTORELEASE(str); } @end /* WOVBScript */ SOPE/sope-appserver/NGObjWeb/DynamicElements/WOPasswordField.api0000644000000000000000000000051715004363604023466 0ustar rootroot SOPE/sope-appserver/NGObjWeb/DynamicElements/_WOTemporaryHyperlink.m0000644000000000000000000001067715004363604024422 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "WOHyperlink.h" #include "WOHyperlinkInfo.h" #include "WOCompoundElement.h" #include #include "decommon.h" @implementation _WOTemporaryHyperlink static Class _WOSimpleActionHyperlinkClass = Nil; static Class _WOSimpleStringActionHyperlinkClass = Nil; static Class _WOActionHyperlinkClass = Nil; static Class _WOPageHyperlinkClass = Nil; static Class _WOHrefHyperlinkClass = Nil; static Class _WOCommonStaticDAHyperlinkClass = Nil; static Class _WODirectActionHyperlinkClass = Nil; + (void)initialize { static BOOL didInit = NO; if (didInit) return; didInit = YES; _WOSimpleActionHyperlinkClass = NSClassFromString(@"_WOSimpleActionHyperlink"); _WOSimpleStringActionHyperlinkClass = NSClassFromString(@"_WOSimpleStringActionHyperlink"); _WOActionHyperlinkClass = NSClassFromString(@"_WOActionHyperlink"); _WOPageHyperlinkClass = NSClassFromString(@"_WOPageHyperlink"); _WOHrefHyperlinkClass = NSClassFromString(@"_WOHrefHyperlink"); _WOCommonStaticDAHyperlinkClass = NSClassFromString(@"_WOCommonStaticDAHyperlink"); _WODirectActionHyperlinkClass = NSClassFromString(@"_WODirectActionHyperlink"); } - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_t { WOHyperlinkInfo *info; Class linkClass = Nil; if ((info = [(WOHyperlinkInfo *)[WOHyperlinkInfo alloc] initWithConfig:(id)_config]) == nil) { return nil; } if (info->action) { if (info->assocCount == 0) linkClass = [_WOSimpleActionHyperlinkClass class]; else if ((info->assocCount == 1) && (info->string != nil)) linkClass = [_WOSimpleStringActionHyperlinkClass class]; else linkClass = [_WOActionHyperlinkClass class]; } else if (info->pageName) { linkClass = [_WOPageHyperlinkClass class]; } else if (info->href) { linkClass = [_WOHrefHyperlinkClass class]; } else if (info->directActionName) { linkClass = Nil; if (info->assocCount < 3) { if ([info->directActionName isValueConstant]) { if (info->actionClass == nil || ([info->actionClass isValueConstant])) { if (info->assocCount == 1) { if (info->queryParameters != nil || info->string != nil) linkClass = [_WOCommonStaticDAHyperlinkClass class]; } else if (info->assocCount == 2 && (info->queryParameters != nil) && (info->string != nil)) { linkClass = [_WOCommonStaticDAHyperlinkClass class]; } } } } } if (linkClass == Nil) linkClass = [_WODirectActionHyperlinkClass class]; self = [[linkClass alloc] initWithName:_name hyperlinkInfo:info template:_t]; [info release]; info = nil; return self; } - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_associations contentElements:(NSArray *)_contents { WOCompoundElement *template; int count; count = [_contents count]; if (count == 0) { template = nil; } else if (count == 1) { template = [_contents objectAtIndex:0]; } else { template = [[WOCompoundElement allocForCount:[_contents count] zone:[self zone]] initWithContentElements:_contents]; [template autorelease]; } return [self initWithName:_name associations:_associations template:template]; } - (void)dealloc { [self errorWithFormat:@"called dealloc on %@", self]; #if DEBUG abort(); #endif return; // make Tiger GCC / gcc 4.1 happy if (0) [super dealloc]; } @end /* _WOTemporaryHyperlink */ SOPE/sope-appserver/NGObjWeb/DynamicElements/WOGenericContainer.m0000644000000000000000000000676515004363604023635 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "WOGenericElement.h" @interface WOGenericContainer : WOGenericElement { // WODynamicElement: extraAttributes // WODynamicElement: otherTagString // WOGenericContainer: tagName @protected WOElement *template; } @end #include "WOElement+private.h" #include "decommon.h" // TODO(perf): ASCII Tags (appendContentCString) // TODO(perf): constant tags #define TagNameType_Assoc 0 #define TagNameType_String 1 #define TagNameType_ASCII 2 @implementation WOGenericContainer - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_c { if ((self = [super initWithName:_name associations:_config template:_c])) { self->template = [_c retain]; } return self; } - (void)dealloc { [self->template release]; [super dealloc]; } /* accessors */ - (id)template { return self->template; } /* handling requests */ - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx { [self->template takeValuesFromRequest:_req inContext:_ctx]; } - (id)invokeActionForRequest:(WORequest *)_req inContext:(WOContext *)_ctx { return [self->template invokeActionForRequest:_req inContext:_ctx]; } /* generate response */ - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { WOComponent *sComponent; NSString *tag; if ([_ctx isRenderingDisabled] || [[_ctx request] isFromClientComponent]) { [self->template appendToResponse:_response inContext:_ctx]; return; } sComponent = [_ctx component]; switch (self->tagNameType) { case TagNameType_Assoc: if ((tag = [(id)self->tagName stringValueInComponent:sComponent]) == nil) tag = @"p"; break; case TagNameType_String: if ((tag = self->tagName) == nil) tag = @"p"; break; case TagNameType_ASCII: default: tag = nil; break; } WOResponse_AddBytesLen(_response, "<", 1); if (tag) { WOResponse_AddString(_response, tag); } else if (self->tagNameType == TagNameType_ASCII) { WOResponse_AddCString(_response, self->tagName); } [self _appendAttributesToResponse:_response inContext:_ctx]; if (self->otherTagString) { WOResponse_AddBytesLen(_response, " ", 1); WOResponse_AddString(_response, [self->otherTagString stringValueInComponent: sComponent]); } WOResponse_AddBytesLen(_response, ">", 1); [self->template appendToResponse:_response inContext:_ctx]; WOResponse_AddBytesLen(_response, "tagNameType == TagNameType_ASCII) { WOResponse_AddCString(_response, self->tagName); } WOResponse_AddBytesLen(_response, ">", 1); } @end /* WOGenericContainer */ SOPE/sope-appserver/NGObjWeb/DynamicElements/WOBody.api0000644000000000000000000000103315004363604021607 0ustar rootroot SOPE/sope-appserver/NGObjWeb/DynamicElements/WOEntity.api0000644000000000000000000000022315004363604022166 0ustar rootroot SOPE/sope-appserver/NGObjWeb/DynamicElements/WOHtml.m0000644000000000000000000000472015004363604021307 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include @class WOAssociation; @interface WOHtml : WOHTMLDynamicElement { // WODynamicElement: extraAttributes // WODynamicElement: otherTagString @protected WOElement *template; } @end #include "WOElement+private.h" #include #include #include "decommon.h" @implementation WOHtml - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_c { if ((self = [super initWithName:_name associations:_config template:_c])) { self->template = [_c retain]; } return self; } - (void)dealloc { [self->template release]; [super dealloc]; } /* accessors */ - (id)template { return self->template; } /* handling requests */ - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx { [self->template takeValuesFromRequest:_req inContext:_ctx]; } - (id)invokeActionForRequest:(WORequest *)_req inContext:(WOContext *)_ctx { return [self->template invokeActionForRequest:_req inContext:_ctx]; } /* generating response */ - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { BOOL doRender = !([_ctx isRenderingDisabled] || [[_ctx request] isFromClientComponent]); if (doRender) WOResponse_AddCString(_response, ""); [self->template appendToResponse:_response inContext:_ctx]; if (doRender) WOResponse_AddCString(_response, ""); } /* description */ - (NSString *)associationDescription { NSMutableString *str; str = [NSMutableString stringWithCapacity:128]; if (self->template) [str appendFormat:@" template=%@", self->template]; return str; } @end /* WOHtml */ SOPE/sope-appserver/NGObjWeb/DynamicElements/WOImage.h0000644000000000000000000000275515004363604021426 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGObjWeb_DynElems_WOImage_H__ #define __NGObjWeb_DynElems_WOImage_H__ #include /* WOImage is a class cluster with separate subclasses for the different image types (dynamic, element, external and resource - image). Note: WOImage is a class cluster! WOImage associations: otherTagString filename framework src value data mimeType key TODO: add support for "?" parameters? */ @interface WOImage : WOHTMLDynamicElement { // WODynamicElement: extraAttributes // WODynamicElement: otherTagString } @end /* WOImage */ @interface WOImage(Privates) - (NSString *)associationDescription; @end #endif /* __NGObjWeb_DynElems_WOImage_H__ */ SOPE/sope-appserver/NGObjWeb/DynamicElements/_WOComplexHyperlink.m0000644000000000000000000004665615004363604024055 0ustar rootroot/* Copyright (C) 2000-2008 SKYRIX Software AG Copyright (C) 2008 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "WOHyperlink.h" /* Class Hierachy [WOHTMLDynamicElement] [WOHyperlink] _WOComplexHyperlink _WOHrefHyperlink _WOActionHyperlink _WOPageHyperlink _WODirectActionHyperlink */ @interface _WOComplexHyperlink : WOHyperlink { /* superclass of most hyperlink classes */ @protected WOAssociation *fragmentIdentifier; WOAssociation *string; WOAssociation *target; WOAssociation *disabled; WOAssociation *isAbsolute; WOElement *template; /* new in WO4: */ WOAssociation *queryDictionary; NSDictionary *queryParameters; /* associations beginning with ? */ /* non WO, image stuff */ WOAssociation *filename; /* path relative to WebServerResources */ WOAssociation *framework; WOAssociation *src; /* absolute URL */ WOAssociation *disabledFilename; /* icon for 'disabled' state */ } - (NSString *)associationDescription; @end @interface _WOHrefHyperlink : _WOComplexHyperlink { WOAssociation *href; } @end @interface _WOActionHyperlink : _WOComplexHyperlink { WOAssociation *action; } @end @interface _WOPageHyperlink : _WOComplexHyperlink { WOAssociation *pageName; } @end @interface _WODirectActionHyperlink : _WOComplexHyperlink { WOAssociation *actionClass; WOAssociation *directActionName; BOOL sidInUrl; /* include session-id in wa URL ? */ } @end #include "WOElement+private.h" #include "WOHyperlinkInfo.h" #include "WOCompoundElement.h" #include #include #include #include "decommon.h" static Class NSURLClass = Nil; @implementation _WOComplexHyperlink + (void)initialize { if (NSURLClass == Nil) NSURLClass = [NSURL class]; } - (id)initWithName:(NSString *)_name hyperlinkInfo:(WOHyperlinkInfo *)_info template:(WOElement *)_t { if ((self = [super initWithName:_name hyperlinkInfo:_info template:_t])) { self->template = [_t retain]; self->fragmentIdentifier = _info->fragmentIdentifier; self->string = _info->string; self->target = _info->target; self->disabled = _info->disabled; self->queryDictionary = _info->queryDictionary; self->queryParameters = _info->queryParameters; /* image */ self->filename = _info->filename; self->framework = _info->framework; self->src = _info->src; self->disabledFilename = _info->disabledFilename; self->containsForm = self->queryParameters ? YES : NO; } return self; } - (void)dealloc { [self->template release]; [self->queryDictionary release]; [self->queryParameters release]; [self->disabledFilename release]; [self->filename release]; [self->framework release]; [self->src release]; [self->fragmentIdentifier release]; [self->string release]; [self->target release]; [self->disabled release]; [super dealloc]; } /* accessors */ - (id)template { return self->template; } /* handle requests */ - (void)takeValuesFromRequest:(WORequest *)_rq inContext:(WOContext *)_ctx { /* links can take form values !!!! (for query-parameters) */ if (self->queryParameters != nil) { /* apply values to ?style parameters */ WOComponent *sComponent = [_ctx component]; NSEnumerator *keys; NSString *key; keys = [self->queryParameters keyEnumerator]; while ((key = [keys nextObject]) != nil) { id assoc, value; assoc = [self->queryParameters objectForKey:key]; if ([assoc isValueSettable]) { value = [_rq formValueForKey:key]; [assoc setValue:value inComponent:sComponent]; } } } [self->template takeValuesFromRequest:_rq inContext:_ctx]; } - (id)invokeActionForRequest:(WORequest *)_rq inContext:(WOContext *)_ctx { if (self->disabled != nil) { if ([self->disabled boolValueInComponent:[_ctx component]]) return nil; } if (![[_ctx elementID] isEqualToString:[_ctx senderID]]) /* link is not the active element */ return [self->template invokeActionForRequest:_rq inContext:_ctx]; /* link is active */ [[_ctx session] logWithFormat:@"%@[0x%p]: no action/page set !", NSStringFromClass([self class]), self]; return nil; } - (BOOL)_appendHrefToResponse:(WOResponse *)_resp inContext:(WOContext *)_ctx { [self subclassResponsibility:_cmd]; return NO; } - (void)_addImageToResponse:(WOResponse *)_resp inContext:(WOContext *)_ctx { WOComponent *sComponent = [_ctx component]; NSString *uUri; NSString *uFi = nil; NSArray *languages; uUri = [[self->src valueInContext:_ctx] stringValue]; if ([self->disabled boolValueInComponent:sComponent]) { uFi = [self->disabledFilename stringValueInComponent:sComponent]; if (uFi == nil) uFi = [self->filename stringValueInComponent:sComponent]; } else uFi = [self->filename stringValueInComponent:sComponent]; if (!((uFi != nil) || (uUri != nil))) return; languages = [_ctx resourceLookupLanguages]; WOResponse_AddCString(_resp, "framework stringValueInComponent:sComponent] languages:languages request:[_ctx request]]; if (uFi == nil) { NSLog(@"%@: did not find resource %@", sComponent, [self->filename stringValueInComponent:sComponent]); uFi = uUri; } [_resp appendContentHTMLAttributeValue:uFi]; } else { [_resp appendContentHTMLAttributeValue:uUri]; } WOResponse_AddChar(_resp, '"'); [self appendExtraAttributesToResponse:_resp inContext:_ctx]; WOResponse_AddEmptyCloseParens(_resp, _ctx); } - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { WOComponent *sComponent = [_ctx component]; NSString *content; BOOL doNotDisplay; if ([_ctx isRenderingDisabled] || [[_ctx request] isFromClientComponent]) { [self->template appendToResponse:_response inContext:_ctx]; return; } content = [self->string valueInContext:_ctx]; doNotDisplay = [self->disabled boolValueInComponent:sComponent]; if (!doNotDisplay) { NSString *targetView; NSString *queryString = nil; targetView = [self->target stringValueInComponent:sComponent]; WOResponse_AddCString(_response, "queryDictionary valueInComponent:sComponent] andQueryParameters:self->queryParameters inContext:_ctx]; if (self->fragmentIdentifier) { [_response appendContentCharacter:'#']; WOResponse_AddString(_response, [self->fragmentIdentifier stringValueInComponent:sComponent]); } if (queryString) { [_response appendContentCharacter:'?']; WOResponse_AddString(_response, queryString); } [_response appendContentCharacter:'"']; } if (targetView) { WOResponse_AddCString(_response, " target=\""); WOResponse_AddString(_response, targetView); [_response appendContentCharacter:'"']; } [self appendExtraAttributesToResponse:_response inContext:_ctx]; if (self->otherTagString) { WOResponse_AddChar(_response, ' '); WOResponse_AddString(_response, [self->otherTagString stringValueInComponent: [_ctx component]]); } [_response appendContentCharacter:'>']; } /* content */ [self->template appendToResponse:_response inContext:_ctx]; if (content) [_response appendContentHTMLString:content]; /* image content */ if ((self->src != nil) || (self->filename != nil)) [self _addImageToResponse:_response inContext:_ctx]; if (!doNotDisplay) { /* closing tag */ WOResponse_AddCString(_response, ""); } } /* description */ - (NSString *)associationDescription { NSMutableString *str = [NSMutableString stringWithCapacity:256]; if (self->fragmentIdentifier) [str appendFormat:@" fragment=%@", self->fragmentIdentifier]; if (self->string) [str appendFormat:@" string=%@", self->string]; if (self->target) [str appendFormat:@" target=%@", self->target]; if (self->disabled) [str appendFormat:@" disabled=%@", self->disabled]; /* image .. */ if (self->filename) [str appendFormat:@" filename=%@", self->filename]; if (self->framework) [str appendFormat:@" framework=%@", self->framework]; if (self->src) [str appendFormat:@" src=%@", self->src]; return str; } @end /* _WOComplexHyperlink */ @implementation _WOHrefHyperlink static BOOL debugStaticLinks = NO; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; debugStaticLinks = [ud boolForKey:@"WODebugStaticLinkProcessing"]; } - (id)initWithName:(NSString *)_name hyperlinkInfo:(WOHyperlinkInfo *)_info template:(WOElement *)_t { if ((self = [super initWithName:_name hyperlinkInfo:_info template:_t])) { self->href = _info->href; self->isAbsolute = _info->isAbsolute; } return self; } - (void)dealloc { [self->href release]; [super dealloc]; } /* URI generation */ - (BOOL)shouldRewriteURLString:(NSString *)_s inContext:(WOContext *)_ctx { // TODO: we need a binding to disable rewriting! NSRange r; if ([[self->isAbsolute valueInContext:_ctx] boolValue] == YES) return NO; r.length = [_s length]; /* do not rewrite pure fragment URLs */ if (r.length > 0 && [_s characterAtIndex:0] == '#') return NO; /* rewrite all URLs w/o a protocol */ r = [_s rangeOfString:@":"]; if (r.length == 0) return YES; /* only rewrite HTTP URLs */ return [_s hasPrefix:@"http"]; } - (BOOL)_appendHrefToResponse:(WOResponse *)_r inContext:(WOContext *)_ctx { NSString *s; id hrefValue; NSURL *url, *base; base = [_ctx baseURL]; hrefValue = [self->href valueInContext:_ctx]; url = nil; if (hrefValue == nil) return NO; if ([hrefValue isMemberOfClass:NSURLClass] || [hrefValue isKindOfClass:NSURLClass]) { s = [hrefValue stringValueRelativeToURL:base]; } else { /* given HREF is a string */ s = [hrefValue stringValue]; /* we do not want to rewrite stuff like mailto: or javascript: URLs */ if ([self shouldRewriteURLString:s inContext:_ctx]) { if ([s isAbsoluteURL]) { // TODO: why are we doing this? we could just pass through the string? // => probably to generate relative links url = [NSURLClass URLWithString:s]; } else if (base != nil) { /* avoid creating a new URL for ".", just return the base */ url = [s isEqualToString:@"."] ? base : (NSURL *)[NSURLClass URLWithString:s relativeToURL:base]; } else { [self warnWithFormat:@"missing base URL in context ..."]; WOResponse_AddString(_r, s); return YES; } if (url == nil) { [self logWithFormat: @"could not construct URL from 'href' string '%@' (base=%@)", s, base]; return NO; } s = [url stringValueRelativeToURL:base]; } } /* generate URL */ if (debugStaticLinks) { [self logWithFormat:@"static links based on 'href': '%@'", hrefValue]; [self logWithFormat:@" base %@", base]; [self logWithFormat:@" base-abs %@", [base absoluteString]]; [self logWithFormat:@" url %@", url]; if (url != nil) [self logWithFormat:@" url-abs %@", [url absoluteString]]; else [self logWithFormat:@" href %@", hrefValue]; [self logWithFormat:@" string %@", s]; } s = [NSString stringWithFormat: @" href=\"%@", s]; WOResponse_AddString(_r, s); return YES; } /* description */ - (NSString *)associationDescription { NSMutableString *str = [NSMutableString stringWithCapacity:256]; [str appendFormat:@" href=%@", self->href]; [str appendString:[super associationDescription]]; return str; } @end /* _WOHrefHyperlink */ @implementation _WOActionHyperlink - (id)initWithName:(NSString *)_name hyperlinkInfo:(WOHyperlinkInfo *)_info template:(WOElement *)_t { if ((self = [super initWithName:_name hyperlinkInfo:_info template:_t])) { self->action = _info->action; } return self; } - (void)dealloc { [self->action release]; [super dealloc]; } /* dynamic invocation */ - (id)invokeActionForRequest:(WORequest *)_rq inContext:(WOContext *)_ctx { if (self->disabled) { if ([self->disabled boolValueInComponent:[_ctx component]]) return nil; } if (![[_ctx elementID] isEqualToString:[_ctx senderID]]) /* link is not the active element */ return [self->template invokeActionForRequest:_rq inContext:_ctx]; /* link is active */ return [self executeAction:self->action inContext:_ctx]; } - (BOOL)_appendHrefToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { NSString *s; s = [NSString stringWithFormat: @" href=\"%@", [_ctx componentActionURL]]; WOResponse_AddString(_response, s); return YES; } /* description */ - (NSString *)associationDescription { NSMutableString *str = [NSMutableString stringWithCapacity:256]; [str appendFormat:@" action=%@", self->action]; [str appendString:[super associationDescription]]; return str; } @end /* _WOActionHyperlink */ @implementation _WOPageHyperlink - (id)initWithName:(NSString *)_name hyperlinkInfo:(WOHyperlinkInfo *)_info template:(WOElement *)_t { if ((self = [super initWithName:_name hyperlinkInfo:_info template:_t])) { self->pageName = _info->pageName; } return self; } - (void)dealloc { [self->pageName release]; [super dealloc]; } /* handle request */ - (id)invokeActionForRequest:(WORequest *)_rq inContext:(WOContext *)_ctx { WOComponent *page; NSString *name; if (self->disabled) { if ([self->disabled boolValueInComponent:[_ctx component]]) return nil; } if (![[_ctx elementID] isEqualToString:[_ctx senderID]]) /* link is not the active element */ return [self->template invokeActionForRequest:_rq inContext:_ctx]; /* link is the active element */ name = [self->pageName stringValueInComponent:[_ctx component]]; page = [[_ctx application] pageWithName:name inContext:_ctx]; if (page == nil) { [[_ctx session] logWithFormat: @"%@[0x%p]: did not find page with name %@ !", NSStringFromClass([self class]), self, name]; } return page; } /* generate response */ - (BOOL)_appendHrefToResponse:(WOResponse *)_r inContext:(WOContext *)_ctx { /* Profiling: 87% -componentActionURL 13% NSString dataUsingEncoding(appendContentString!) TODO(prof): use addcstring */ NSString *s; s = [NSString stringWithFormat: @" href=\"%@", [_ctx componentActionURL]]; WOResponse_AddString(_r, s); return YES; } /* description */ - (NSString *)associationDescription { NSMutableString *str = [NSMutableString stringWithCapacity:256]; [str appendFormat:@" pageName=%@", self->pageName]; [str appendString:[super associationDescription]]; return str; } @end /* _WOPageHyperlink */ @implementation _WODirectActionHyperlink - (id)initWithName:(NSString *)_name hyperlinkInfo:(WOHyperlinkInfo *)_info template:(WOElement *)_t { if ((self = [super initWithName:_name hyperlinkInfo:_info template:_t])) { self->actionClass = _info->actionClass; self->directActionName = _info->directActionName; self->sidInUrl = _info->sidInUrl; self->containsForm = NO; /* direct actions are never form stuff ... */ } return self; } - (void)dealloc { [self->actionClass release]; [self->directActionName release]; [super dealloc]; } /* handle requests */ - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx { /* DA links can *never* take form values !!!! */ [self->template takeValuesFromRequest:_req inContext:_ctx]; } - (id)invokeActionForRequest:(WORequest *)_rq inContext:(WOContext *)_ctx { /* DA links can *never* invoke an action !!!! */ return [self->template invokeActionForRequest:_rq inContext:_ctx]; } /* generate response */ - (BOOL)_appendHrefToResponse:(WOResponse *)_r inContext:(WOContext *)_ctx { WOComponent *sComponent; NSString *daClass; NSString *daName, *s; NSMutableDictionary *qd; NSDictionary *tmp; sComponent = [_ctx component]; daClass = [self->actionClass stringValueInComponent:sComponent]; daName = [self->directActionName stringValueInComponent:sComponent]; if (daClass) { if (daName) { if (![daClass isEqualToString:@"DirectAction"]) daName = [NSString stringWithFormat:@"%@/%@", daClass, daName]; } else daName = daClass; } qd = [NSMutableDictionary dictionaryWithCapacity:16]; /* add query dictionary */ if (self->queryDictionary) { if ((tmp = [self->queryDictionary valueInComponent:sComponent])) [qd addEntriesFromDictionary:tmp]; } /* add ?style parameters */ if (self->queryParameters != nil) { NSEnumerator *keys; NSString *key; keys = [self->queryParameters keyEnumerator]; while ((key = [keys nextObject])) { id assoc, value; assoc = [self->queryParameters objectForKey:key]; value = [assoc stringValueInComponent:sComponent]; [qd setObject:(value != nil ? value : (id)@"") forKey:key]; } } /* add session ID */ if (self->sidInUrl) { if ([_ctx hasSession]) { WOSession *sn; sn = [_ctx session]; [qd setObject:[sn sessionID] forKey:WORequestValueSessionID]; if (![sn isDistributionEnabled]) { [qd setObject:[[WOApplication application] number] forKey:WORequestValueInstance]; } } } if (daName) { s = [NSString stringWithFormat: @" href=\"%@\"", [_ctx directActionURLForActionNamed:daName queryDictionary:qd]]; WOResponse_AddString(_r, s); } return NO; } /* description */ - (NSString *)associationDescription { NSMutableString *str = [NSMutableString stringWithCapacity:256]; if (self->actionClass) [str appendFormat:@" actionClass=%@", self->actionClass]; if (self->directActionName) [str appendFormat:@" directAction=%@", self->directActionName]; [str appendString:[super associationDescription]]; return str; } @end /* _WODirectActionHyperlink */ SOPE/sope-appserver/NGObjWeb/DynamicElements/WOIFrame.api0000644000000000000000000000222215004363604022056 0ustar rootroot SOPE/sope-appserver/NGObjWeb/DynamicElements/WOQuickTime.m0000644000000000000000000001120415004363604022271 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "WOElement+private.h" #include #include #include "decommon.h" /* A QuickTime movie, picture, ... The HTML tag attributes are described at: http://www.apple.com/quicktime/authoring/embed2.html */ @interface WOQuickTime : WOHTMLDynamicElement { // WODynamicElement: extraAttributes // WODynamicElement: otherTagString @protected WOElement *template; WOAssociation *filename; WOAssociation *framework; WOAssociation *src; WOAssociation *action; WOAssociation *href; WOAssociation *pageName; WOAssociation *prefixHost; WOAssociation *width; WOAssociation *height; WOAssociation *pluginsPage; WOAssociation *hotspotList; WOAssociation *selection; WOAssociation *bgcolor; WOAssociation *target; WOAssociation *volume; WOAssociation *pan; WOAssociation *tilt; WOAssociation *fov; WOAssociation *node; WOAssociation *correction; WOAssociation *cache; WOAssociation *autoplay; WOAssociation *hidden; WOAssociation *playEveryFrame; WOAssociation *controller; } @end /* WOQuickTime */ @interface WODynamicElement(UsedPrivates) - (id)_initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_t; @end @implementation WOQuickTime - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_t { if ((self = [super _initWithName:_name associations:_config template:_t])) { self->template = [_t retain]; self->filename = OWGetProperty(_config, @"filename"); self->framework = OWGetProperty(_config, @"framework"); self->src = OWGetProperty(_config, @"src"); self->action = OWGetProperty(_config, @"action"); self->href = OWGetProperty(_config, @"href"); self->pageName = OWGetProperty(_config, @"pageName"); self->prefixHost = OWGetProperty(_config, @"prefixHost"); self->width = OWGetProperty(_config, @"width"); self->height = OWGetProperty(_config, @"height"); self->pluginsPage = OWGetProperty(_config, @"pluginsPage"); self->hotspotList = OWGetProperty(_config, @"hotspotList"); self->selection = OWGetProperty(_config, @"selection"); self->bgcolor = OWGetProperty(_config, @"bgcolor"); self->target = OWGetProperty(_config, @"target"); self->volume = OWGetProperty(_config, @"volume"); self->pan = OWGetProperty(_config, @"pan"); self->tilt = OWGetProperty(_config, @"tilt"); self->fov = OWGetProperty(_config, @"fov"); self->node = OWGetProperty(_config, @"node"); self->correction = OWGetProperty(_config, @"correction"); self->cache = OWGetProperty(_config, @"cache"); self->autoplay = OWGetProperty(_config, @"autoplay"); self->hidden = OWGetProperty(_config, @"hidden"); self->playEveryFrame = OWGetProperty(_config, @"playEveryFrame"); self->controller = OWGetProperty(_config, @"controller"); } return self; } - (void)dealloc { RELEASE(self->template); RELEASE(self->filename); RELEASE(self->framework); RELEASE(self->src); RELEASE(self->action); RELEASE(self->href); RELEASE(self->pageName); RELEASE(self->prefixHost); RELEASE(self->width); RELEASE(self->height); RELEASE(self->pluginsPage); RELEASE(self->hotspotList); RELEASE(self->selection); RELEASE(self->bgcolor); RELEASE(self->target); RELEASE(self->volume); RELEASE(self->pan); RELEASE(self->tilt); RELEASE(self->fov); RELEASE(self->node); RELEASE(self->correction); RELEASE(self->cache); RELEASE(self->autoplay); RELEASE(self->hidden); RELEASE(self->playEveryFrame); RELEASE(self->controller); [super dealloc]; } /* event handling */ /* HTML generation */ /* description */ @end SOPE/sope-appserver/NGObjWeb/DynamicElements/GNUmakefile.preamble0000644000000000000000000000061215004363604023613 0ustar rootroot# compilation flags ADDITIONAL_CPPFLAGS += -pipe # -DHTML_DEBUG=1 # -DPROFILE_CLUSTERS=1 ADDITIONAL_CPPFLAGS += -pipe -Wall -funsigned-char -O2 ADDITIONAL_CPPFLAGS += -DCOMPILING_NGOBJWEB=1 DynamicElements_INCLUDE_DIRS += \ -I.. -I. -I../.. \ -I../../../sope-core \ -I../../../sope-core/NGStreams \ -I../../../sope-core/NGExtensions \ -I../../../sope-mime \ -I../../../sope-xml SOPE/sope-appserver/NGObjWeb/DynamicElements/WORepetition.api0000644000000000000000000000170115004363604023036 0ustar rootroot SOPE/sope-appserver/NGObjWeb/DynamicElements/WOBrowser.api0000644000000000000000000000217215004363604022342 0ustar rootroot SOPE/sope-appserver/NGObjWeb/DynamicElements/WOImageButton.api0000644000000000000000000000331315004363604023133 0ustar rootroot SOPE/sope-appserver/NGObjWeb/DynamicElements/WOxXULElemBuilder.m0000644000000000000000000000401115004363604023346 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import /* This builder builds all standard elements which are defined in the XUL namespace. Supported tags: - all other tags are represented using either WOGenericElement or WOGenericContainer, so this builder is "final destination" for all XUL related tags. \n"]; /* the language mappings */ [self appendEpozScript:@"epoz_lang_en.js" toResponse:_r inContext:_ctx]; /* the processing JavaScripts */ [self appendEpozScript:@"epoz_script_widget.js" toResponse:_r inContext:_ctx]; [self appendEpozScript:@"epoz_script_detect.js" toResponse:_r inContext:_ctx]; [self appendEpozScript:@"epoz_script_main.js" toResponse:_r inContext:_ctx]; /* Start Epoz """ Create an Epoz-Wysiwyg-Editor. name : the name of the form-element which submits the data data : the data to edit toolbox : a link to a HTML-Page which delivers additional tools lang: a code for the language-file (en,de,...) path : path to Epoz-Javascript. Needed mainly for Plone (portal_url). widget: You can specify a path to an alternative JavaScript for epoz_script_widget.js style : style-definition for the editor-area button : style-definiton for buttons If Epoz can't create a Rich-Text-Editor, a simple textarea is created. """ */ [_r appendContentString: @""]; /* fallback if scripting is disabled */ [_r appendContentString:@""]; } - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { if ([_ctx isRenderingDisabled]) return; if ([self isEpozBrowserInContext:_ctx]) [self appendEpozToResponse:_response inContext:_ctx]; else [self appendTextAreaToResponse:_response inContext:_ctx]; } /* description */ - (NSString *)associationDescription { NSMutableString *str = nil; str = [NSMutableString stringWithCapacity:64]; if (self->value) [str appendFormat:@" value=%@", self->value]; if (self->name) [str appendFormat:@" name=%@", self->name]; if (self->disabled) [str appendFormat:@" disabled=%@", self->disabled]; if (self->rows) [str appendFormat:@" rows=%@", self->rows]; if (self->cols) [str appendFormat:@" cols=%@", self->cols]; return str; } @end /* WEEpozEditor */ SOPE/sope-appserver/WEExtensions/WEPageView.api0000644000000000000000000000125015004363604020325 0ustar rootroot SOPE/sope-appserver/WEExtensions/WEPageView.m0000644000000000000000000005732115004363604020022 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include /* WEPageView TODO: describe what it does */ @interface WEPageView : WODynamicElement { WOAssociation *selection; /* config: */ WOAssociation *titleColor; WOAssociation *contentColor; WOAssociation *fontColor; WOAssociation *fontFace; WOAssociation *fontSize; WOAssociation *firstIcon; WOAssociation *firstBlind; // firstBlindIcon WOAssociation *previousIcon; WOAssociation *previousBlind; // previousBlindIcon WOAssociation *nextIcon; WOAssociation *nextBlind; // nextBlindIcon WOAssociation *lastIcon; WOAssociation *lastBlind; // lastBlindIcon WOAssociation *firstLabel; WOAssociation *previousLabel; WOAssociation *nextLabel; WOAssociation *lastLabel; id template; } @end @interface WEPageItem : WODynamicElement { WOAssociation *key; WOAssociation *title; WOAssociation *action; id template; } @end @interface WEPageItemInfo : NSObject { @public NSString *title; NSString *key; NSString *uri; } @end #include #include "common.h" // #define DEBUG_TAKEVALUES 1 /* context keys */ static NSString *WEPageView_HEAD = @"WEPageView_head"; static NSString *WEPageView_BODY = @"WEPageView_body"; static NSString *WEPageView_KEYS = @"WEPageView_keys"; static NSString *WEPageView_ACTIVEKEY = @"WEPageView_activekey"; static NSString *WEPageView_COLLECT = @"~tv~"; // navigation icons static NSString *WEPageView_first = @"WEPageView_first"; static NSString *WEPageView_first_blind = @"WEPageView_first_blind"; static NSString *WEPageView_previous = @"WEPageView_previous"; static NSString *WEPageView_previous_blind = @"WEPageView_previous_blind"; static NSString *WEPageView_next = @"WEPageView_next"; static NSString *WEPageView_next_blind = @"WEPageView_next_blind"; static NSString *WEPageView_last = @"WEPageView_last"; static NSString *WEPageView_last_blind = @"WEPageView_last_blind"; // labels static NSString *WEPageView_firstLabel = @"WEPageView_firstLabel"; static NSString *WEPageView_previousLabel = @"WEPageView_previousLabel"; static NSString *WEPageView_nextLabel = @"WEPageView_nextLabel"; static NSString *WEPageView_lastLabel = @"WEPageView_lastLabel"; static NSString *WEPageView_ = @"WEPageView_"; @implementation WEPageView static NSNumber *YesNumber = nil; + (void)initialize { if (YesNumber == nil) YesNumber = [[NSNumber numberWithBool:YES] retain]; } - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_subs { if ((self = [super initWithName:_name associations:_config template:_subs])) { self->selection = WOExtGetProperty(_config, @"selection"); self->contentColor = WOExtGetProperty(_config, @"contentColor"); self->titleColor = WOExtGetProperty(_config, @"titleColor"); self->firstIcon = WOExtGetProperty(_config, @"firstIcon"); self->firstBlind = WOExtGetProperty(_config, @"firstBlindIcon"); self->previousIcon = WOExtGetProperty(_config, @"previousIcon"); self->previousBlind = WOExtGetProperty(_config, @"previousBlindIcon"); self->nextIcon = WOExtGetProperty(_config, @"nextIcon"); self->nextBlind = WOExtGetProperty(_config, @"nextBlindIcon"); self->lastIcon = WOExtGetProperty(_config, @"lastIcon"); self->lastBlind = WOExtGetProperty(_config, @"lastBlindIcon"); self->firstLabel = WOExtGetProperty(_config, @"firstLabel"); self->previousLabel = WOExtGetProperty(_config, @"previousLabel"); self->nextLabel = WOExtGetProperty(_config, @"nextLabel"); self->lastLabel = WOExtGetProperty(_config, @"lastLabel"); self->fontColor = WOExtGetProperty(_config, @"fontColor"); self->fontFace = WOExtGetProperty(_config, @"fontFace"); self->fontSize = WOExtGetProperty(_config, @"fontSize"); #define SetAssociationValue(_a_, _value_) \ if (_a_ == nil) \ _a_ = [[WOAssociation associationWithValue:_value_] retain]; SetAssociationValue(self->firstLabel, @"<<"); SetAssociationValue(self->previousLabel, @"<"); SetAssociationValue(self->nextLabel, @">"); SetAssociationValue(self->lastLabel, @">>"); #undef SetAssociationValue self->template = [_subs retain]; } return self; } - (void)dealloc { RELEASE(self->selection); RELEASE(self->contentColor); RELEASE(self->titleColor); RELEASE(self->firstIcon); RELEASE(self->firstBlind); RELEASE(self->previousIcon); RELEASE(self->previousBlind); RELEASE(self->nextIcon); RELEASE(self->nextBlind); RELEASE(self->lastIcon); RELEASE(self->lastBlind); RELEASE(self->firstLabel); RELEASE(self->previousLabel); RELEASE(self->nextLabel); RELEASE(self->lastLabel); RELEASE(self->fontColor); RELEASE(self->fontFace); RELEASE(self->fontSize); RELEASE(self->template); [super dealloc]; } - (void)updateConfigInContext:(WOContext *)_ctx { WOComponent *cmp; NSString *tmp; cmp = [_ctx component]; #define SetConfigInContext(_a_, _key_) \ if (_a_ && (tmp = [_a_ valueInComponent:cmp])) \ [_ctx setObject:tmp forKey:_key_]; \ SetConfigInContext(self->firstIcon, WEPageView_first); SetConfigInContext(self->firstBlind, WEPageView_first_blind); SetConfigInContext(self->previousIcon, WEPageView_previous); SetConfigInContext(self->previousBlind, WEPageView_previous_blind); SetConfigInContext(self->nextIcon, WEPageView_next); SetConfigInContext(self->nextBlind, WEPageView_next_blind); SetConfigInContext(self->lastIcon, WEPageView_last); SetConfigInContext(self->lastBlind, WEPageView_last_blind); SetConfigInContext(self->firstLabel, WEPageView_firstLabel); SetConfigInContext(self->previousLabel, WEPageView_previousLabel); SetConfigInContext(self->nextLabel, WEPageView_nextLabel); SetConfigInContext(self->lastLabel, WEPageView_lastLabel); #undef SetConfigInContext } - (void)removeConfigInContext:(WOContext *)_ctx { [_ctx removeObjectForKey:WEPageView_first]; [_ctx removeObjectForKey:WEPageView_first_blind]; [_ctx removeObjectForKey:WEPageView_previous]; [_ctx removeObjectForKey:WEPageView_previous_blind]; [_ctx removeObjectForKey:WEPageView_next]; [_ctx removeObjectForKey:WEPageView_next_blind]; [_ctx removeObjectForKey:WEPageView_last]; [_ctx removeObjectForKey:WEPageView_last_blind]; [_ctx removeObjectForKey:WEPageView_firstLabel]; [_ctx removeObjectForKey:WEPageView_previousLabel]; [_ctx removeObjectForKey:WEPageView_nextLabel]; [_ctx removeObjectForKey:WEPageView_lastLabel]; } static inline NSString *WEPageLabelForKey(NSString *_key, WOContext *_ctx) { NSString *key; key = [NSString stringWithFormat:@"WEPageView_%@Label", _key]; return [_ctx objectForKey:key]; } /* nesting */ - (id)saveNestedStateInContext:(WOContext *)_ctx { return nil; } - (void)restoreNestedState:(id)_state inContext:(WOContext *)_ctx { if (_state == nil) return; } - (NSArray *)collectKeysInContext:(WOContext *)_ctx { /* collect mode, collects all keys */ [_ctx setObject:WEPageView_COLLECT forKey:WEPageView_HEAD]; [self->template appendToResponse:nil inContext:_ctx]; [_ctx removeObjectForKey:WEPageView_HEAD]; return [_ctx objectForKey:WEPageView_KEYS]; } /* responder */ - (void)takeValuesFromRequest:(WORequest *)_request inContext:(WOContext *)_ctx { id nestedState; nestedState = [self saveNestedStateInContext:_ctx]; [_ctx appendElementIDComponent:@"h"]; [self->template takeValuesFromRequest:_request inContext:_ctx]; [_ctx deleteLastElementIDComponent]; [_ctx appendElementIDComponent:@"b"]; [_ctx setObject:self->selection forKey:WEPageView_BODY]; #if DEBUG_TAKEVALUES [[_ctx component] debugWithFormat:@"WEPageView: body takes values, eid='%@'", [_ctx elementID]]; #endif [self->template takeValuesFromRequest:_request inContext:_ctx]; [_ctx removeObjectForKey:WEPageView_BODY]; [_ctx deleteLastElementIDComponent]; /* 'b' */ [self restoreNestedState:nestedState inContext:_ctx]; } - (id)invokeActionForRequest:(WORequest *)_request inContext:(WOContext *)_ctx { NSString *key; id result; result = nil; if ((key = [_ctx currentElementID])) { id nestedState; nestedState = [self saveNestedStateInContext:_ctx]; if ([key isEqualToString:@"h"]) { /* header action */ [_ctx consumeElementID]; [_ctx appendElementIDComponent:key]; [_ctx setObject:self->selection forKey:WEPageView_HEAD]; result = [self->template invokeActionForRequest:_request inContext:_ctx]; [_ctx removeObjectForKey:WEPageView_HEAD]; [_ctx deleteLastElementIDComponent]; } else if ([key isEqualToString:@"b"]) { /* body action */ [_ctx consumeElementID]; [_ctx appendElementIDComponent:key]; [_ctx setObject:self->selection forKey:WEPageView_BODY]; result = [self->template invokeActionForRequest:_request inContext:_ctx]; [_ctx removeObjectForKey:WEPageView_BODY]; [_ctx deleteLastElementIDComponent]; } else { [[_ctx application] debugWithFormat:@"unknown page container key '%@'", key]; } [self restoreNestedState:nestedState inContext:_ctx]; } return result; } - (void)_appendNav:(NSString *)_nav isBlind:(BOOL)_isBlind toResponse:(WOResponse *)_response inContext:(WOContext *)_ctx info:(WEPageItemInfo *)_info { NSString *img; NSString *label; BOOL doForm; doForm = [_ctx isInForm]; img = [WEPageView_ stringByAppendingString:_nav]; img = [img stringByAppendingString:(_isBlind) ? @"_blind" : @""]; img = [_ctx objectForKey:img]; img = WEUriOfResource(img,_ctx); label = WEPageLabelForKey(_nav, _ctx); // append as submit button if (doForm && !_isBlind && img && _info) { NSString *uri; uri = [[_info->uri componentsSeparatedByString:@"/"] lastObject]; [_ctx appendElementIDComponent:_nav]; [_response appendContentString:@"wcFlags.xmlStyleEmptyElements) [_response appendContentString:@"\" />"]; else [_response appendContentString:@"\">"]; [_ctx deleteLastElementIDComponent]; return; } /* open anker */ if (!_isBlind && _info) { [_ctx appendElementIDComponent:_nav]; [_response appendContentString:@"uri]; [_response appendContentString:@"\">"]; } if (!img) { [_response appendContentCharacter:'[']; [_response appendContentString:label]; [_response appendContentCharacter:']']; } else { [_response appendContentString:@"\""];wcFlags.xmlStyleEmptyElements) [_response appendContentString:@"\" />"]; else [_response appendContentString:@"\">"]; } /* close anker */ if (!_isBlind && _info) { [_response appendContentString:@""]; [_ctx deleteLastElementIDComponent]; } } - (void)appendNavToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx isLeft:(BOOL)_isLeft activeKey:(WEPageItemInfo *)_activeKey keys:(NSArray *)_keys { WEPageItemInfo *info; int idx, cnt; idx = [_keys indexOfObject:_activeKey]; cnt = [_keys count]; if (idx > cnt) { NSLog(@"Warning! WEPageView: idx is out of range!"); return; } if (_isLeft) { info = (cnt > 0) ? [_keys objectAtIndex:0] : nil; [self _appendNav:@"first" isBlind:(idx < 1) ? YES : NO toResponse:_response inContext:_ctx info:info]; info = (cnt > 0 && idx > 0) ? [_keys objectAtIndex:idx-1] : nil; [self _appendNav:@"previous" isBlind:(idx < 1) ? YES : NO toResponse:_response inContext:_ctx info:info]; } else { info = (cnt > idx+1) ? [_keys objectAtIndex:idx+1] : nil; [self _appendNav:@"next" isBlind:(cnt <= idx+1) ? YES : NO toResponse:_response inContext:_ctx info:info]; info = (cnt > 0) ? [_keys objectAtIndex:cnt-1] : nil; [self _appendNav:@"last" isBlind:(cnt <= idx+1) ? YES : NO toResponse:_response inContext:_ctx info:info]; } } - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { WOComponent *cmp; BOOL indentContent; NSString *bgcolor; id nestedState; NSString *activeKey; WEPageItemInfo *activeInfo = nil; NSArray *keys; unsigned i, count; if ([_ctx isRenderingDisabled]) { [self->template appendToResponse:_response inContext:_ctx]; return; } [self updateConfigInContext:_ctx]; indentContent = YES; /* put additional padding table into content */ cmp = [_ctx component]; /* check for browser */ { WEClientCapabilities *ccaps; ccaps = [[_ctx request] clientCapabilities]; if ([ccaps isFastTableBrowser] && ![ccaps isTextModeBrowser]) indentContent = YES; } /* save state */ nestedState = [self saveNestedStateInContext:_ctx]; /* collect & process keys (= available tabs) */ [_ctx appendElementIDComponent:@"h"]; activeKey = [self->selection stringValueInComponent:cmp]; keys = [self collectKeysInContext:_ctx]; if (![[keys valueForKey:@"key"] containsObject:activeKey]) /* selection is not available in keys */ activeKey = nil; if ((activeKey == nil) && ([keys count] > 0)) { /* no or invalid selection, use first key */ activeKey = [[keys objectAtIndex:0] key]; if ([self->selection isValueSettable]) [self->selection setValue:activeKey inComponent:[_ctx component]]; } for (i = 0, count = [keys count]; i < count; i++) { WEPageItemInfo *info; info = [keys objectAtIndex:i]; if ([info->key isEqualToString:activeKey]) { activeInfo = info; break; } } /* start appending */ [_response appendContentString: @""]; /* generate header row */ bgcolor = [self->titleColor stringValueInComponent:cmp]; [_response appendContentString:@""]; /* left navigation */ WEAppendTD(_response, @"left", nil, bgcolor); [self appendNavToResponse:_response inContext:_ctx isLeft:YES activeKey:activeInfo keys:keys]; [_response appendContentString:@""]; /* title */ WEAppendTD(_response, @"center", nil, bgcolor); { unsigned char buf[256]; NSString *tC, *tF, *tS; // text font attrtibutes BOOL hasFont; cmp = [_ctx component]; // TODO: use CSS tC = [self->fontColor stringValueInComponent:cmp]; tF = [self->fontFace stringValueInComponent:cmp]; tS = [self->fontSize stringValueInComponent:cmp]; hasFont = (tC || tF || tS) ? YES : NO; if (hasFont) WEAppendFont(_response, tC, tF, tS); for (i = 0, count = [keys count]; i < count; i++) { WEPageItemInfo *info; info = [keys objectAtIndex:i]; // TODO: use CSS if ([info->key isEqualToString:activeKey]) { [_response appendContentString:@""]; [_response appendContentString:info->title]; [_response appendContentString:@""]; break; } } // TODO: use CSS sprintf((char *)buf, " (%d/%d)", (i + 1), count); [_response appendContentCString:buf]; if (hasFont) [_response appendContentString:@""]; } [_response appendContentString:@""]; /* right navigation */ WEAppendTD(_response, @"right", nil, bgcolor); [self appendNavToResponse:_response inContext:_ctx isLeft:NO activeKey:activeInfo keys:keys]; [_response appendContentString:@""]; [_response appendContentString:@""]; [_ctx deleteLastElementIDComponent]; // delete "h" [_ctx removeObjectForKey:WEPageView_HEAD]; /* body row */ bgcolor = [self->contentColor stringValueInComponent:cmp]; { [_response appendContentString:@""]; } [_response appendContentString:@"
    "]; if (indentContent) { /* start padding table */ [_response appendContentString: @""]; [_response appendContentString:@"
    "]; } [_ctx appendElementIDComponent:@"b"]; /* generate currently active page */ { [_ctx setObject:activeKey forKey:WEPageView_BODY]; [self->template appendToResponse:_response inContext:_ctx]; [_ctx removeObjectForKey:WEPageView_BODY]; } [_ctx deleteLastElementIDComponent]; if (indentContent) /* close padding table */ [_response appendContentString:@"
    "]; [_response appendContentString:@"
    "]; [_ctx removeObjectForKey:WEPageView_ACTIVEKEY]; [_ctx removeObjectForKey:WEPageView_KEYS]; [self restoreNestedState:nestedState inContext:_ctx]; [self removeConfigInContext:_ctx]; } @end /* WEPageView */ @implementation WEPageItem - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_subs { if ((self = [super initWithName:_name associations:_config template:_subs])) { self->key = WOExtGetProperty(_config, @"key"); self->title = WOExtGetProperty(_config, @"title"); self->action = WOExtGetProperty(_config, @"action"); self->template = RETAIN(_subs); } return self; } - (void)dealloc { [self->action release]; [self->title release]; [self->key release]; [self->template release]; [super dealloc]; } /* responder */ - (void)takeValuesFromRequest:(WORequest *)_request inContext:(WOContext *)_ctx { WOAssociation *tmp; if ((tmp = [_ctx objectForKey:WEPageView_BODY])) { NSString *activeTabKey; NSString *myTabKey; activeTabKey = [tmp stringValueInComponent:[_ctx component]]; myTabKey = [self->key stringValueInComponent:[_ctx component]]; if ([activeTabKey isEqualToString:myTabKey]) { [_ctx appendElementIDComponent:activeTabKey]; #if DEBUG_TAKEVALUES [[_ctx component] debugWithFormat: @"WEPageItem: body takes values, eid='%@'", [_ctx elementID]]; #endif [self->template takeValuesFromRequest:_request inContext:_ctx]; [_ctx deleteLastElementIDComponent]; } #if DEBUG_TAKEVALUES else { [[_ctx component] debugWithFormat: @"WEPageItem: body takes no values, eid='%@'", [_ctx elementID]]; } #endif } else { NSString *k; NSString *eid; k = [self->key stringValueInComponent:[_ctx component]]; eid = [[_ctx elementID] stringByAppendingString:@"."]; eid = [eid stringByAppendingString:k]; if (k && [_request formValueForKey:[eid stringByAppendingString:@".x"]]) { [_ctx addActiveFormElement:self]; [_ctx setRequestSenderID:eid]; } } } - (id)invokeActionForRequest:(WORequest *)_rq inContext:(WOContext *)_ctx { NSString *tabkey; id result; WOAssociation *tmp; tabkey = [_ctx currentElementID]; [_ctx consumeElementID]; [_ctx appendElementIDComponent:tabkey]; if ((tmp = [_ctx objectForKey:WEPageView_HEAD])) { /* click on tab icon */ if ([tmp isValueSettable]) [tmp setValue:tabkey inComponent:[_ctx component]]; result = [self->action valueInComponent:[_ctx component]]; } else if ((tmp = [_ctx objectForKey:WEPageView_BODY])) { /* clicked somewhere in the body */ if ([tmp isValueSettable]) [tmp setValue:tabkey inComponent:[_ctx component]]; result = [self->template invokeActionForRequest:_rq inContext:_ctx]; } else { [[_ctx component] debugWithFormat:@"WEPageItem: invalid invoke state"]; result = [self->template invokeActionForRequest:_rq inContext:_ctx]; } [_ctx deleteLastElementIDComponent]; return result; } - (void)appendHead:(NSString *)tmp toResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { NSMutableArray *keys; WEPageItemInfo *info; WOComponent *cmp; NSString *k; if (![tmp isEqual:WEPageView_COLLECT]) return; /* collect keys */ cmp = [_ctx component]; keys = [_ctx objectForKey:WEPageView_KEYS]; if (keys == nil) { keys = [NSMutableArray arrayWithCapacity:8]; [_ctx setObject:keys forKey:WEPageView_KEYS]; } if ((k = [self->key stringValueInComponent:[_ctx component]]) == nil) { /* auto-assign a key */ char kb[16]; #if GS_64BIT_OLD sprintf(kb, "%d", [keys count]); #else sprintf(kb, "%ld", [keys count]); #endif k = [NSString stringWithCString:kb]; } [_ctx appendElementIDComponent:k]; info = [[WEPageItemInfo alloc] init]; info->key = [k copy]; info->title = [[self->title stringValueInComponent:cmp] copy]; info->uri = [[_ctx componentActionURL] copy]; [keys addObject:info]; [info release]; [_ctx deleteLastElementIDComponent]; } - (void)appendBody:(NSString *)tmp toResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { NSString *k; k = [self->key stringValueInComponent:[_ctx component]]; if (![tmp isEqualToString:k]) return; /* content is active or used as layer*/ [_ctx appendElementIDComponent:k]; #if DEBUG [self debugWithFormat:@"PAGE: %@", k]; #endif [self->template appendToResponse:_response inContext:_ctx]; [_ctx deleteLastElementIDComponent]; } - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { NSString *tmp; if ([_ctx isRenderingDisabled]) { [self->template appendToResponse:_response inContext:_ctx]; return; } if ((tmp = [_ctx objectForKey:WEPageView_HEAD])) [self appendHead:tmp toResponse:_response inContext:_ctx]; else if ((tmp = [_ctx objectForKey:WEPageView_BODY])) [self appendBody:tmp toResponse:_response inContext:_ctx]; else [_response appendContentString:@"[invalid pageview state]"]; } @end /* WEPageItem */ @implementation WEPageItemInfo - (void)dealloc { [self->uri release]; [self->title release]; [self->key release]; [super dealloc]; } - (NSString *)key { return self->key; } - (NSString *)title { return self->title; } - (NSString *)uri { return self->uri; } @end /* WEPageItemInfo */ SOPE/sope-appserver/COPYRIGHT0000644000000000000000000000010515004363604014565 0ustar rootrootCopyright (C) 2000-2005 SKYRIX Software AG Contact: info@skyrix.com SOPE/sope-appserver/README-OSX.txt0000644000000000000000000000122415004363604015442 0ustar rootrootPlease refer to ../README-OSX.txt for compilation directives. Building Notes ============== Prerequisites: - sope-xml - sope-core Prebinding Notes (DEPRECATED, for reference only) ================================================= sope-appserver: 0xC3000000 - 0xC5FFFFFF 0xC3000000 NGScripting [REMOVED] 0xC3200000 NGJavaScript [REMOVED] 0xC3400000 NGHttp [not available in gstep-make] 0xC3700000 WebDAV [not available in gstep-make] 0xC3A00000 SoOFS 0xC3D00000 NGXmlRpc 0xC4000000 WEExtensions 0xC4300000 WOExtensions 0xC4600000 NGObjDOM [REMOVED] 0xC4900000 NGObjWeb 0xC5AF0000 SoObjects [NEW] 0xC5B00000 WOXML 0xC5E00000 WEPrototype 0xC5FF0000 SOPE SOPE/sope-appserver/common.make0000644000000000000000000000124315004363604015425 0ustar rootroot# GNUstep makefile include $(GNUSTEP_MAKEFILES)/common.make include ../Version -include ./Version ADDITIONAL_CPPFLAGS += -pipe -Wall -Wno-protocol ADDITIONAL_INCLUDE_DIRS += \ -I.. \ -I../../sope-core/ \ -I../../sope-core/NGExtensions \ -I../../sope-core/NGStreams \ -I../../sope-xml ADDITIONAL_LIB_DIRS += \ -L./$(GNUSTEP_OBJ_DIR) \ -L../../sope-core/EOControl/$(GNUSTEP_OBJ_DIR) \ -L../../sope-core/NGExtensions/$(GNUSTEP_OBJ_DIR) \ -L../../sope-core/NGStreams/$(GNUSTEP_OBJ_DIR) \ -L../../sope-xml/SaxObjC/$(GNUSTEP_OBJ_DIR) \ -L../../sope-xml/DOM/$(GNUSTEP_OBJ_DIR) \ ifeq ($(FOUNDATION_LIB),nx) ADDITIONAL_LDFLAGS += -framework Foundation endif SOPE/general.make0000644000000000000000000000163215004363604012601 0ustar rootroot# Macros that allow testing for GCC flag existence try-run = $(shell set -e; \ TMP="/tmp/SOPE-gcc-flags-check.$$$$.tmp"; \ TMPO="/tmp/SOPE-gcc-flags-check.$$$$.o"; \ if ($(1)) >/dev/null 2>&1; \ then echo "$(2)"; \ else echo "$(3)"; \ fi; \ rm -f "$$TMP" "$$TMPO") cc-option = $(call try-run,\ $(CC) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2)) # Use GCC level 2 optimization by default # Might be overridden below ADDITIONAL_OBJCFLAGS=-O2 ifeq ($(debug),yes) ADDITIONAL_OBJCFLAGS=-O0 else ADDITIONAL_OBJCFLAGS=-Wuninitialized endif # Ensure we store in the ELF files minimal debugging # information plus the compiler flags used; that can # be afterwards read with: # readelf -p .GCC.command.line /path/to/elf_file ADDITIONAL_OBJCFLAGS += -g $(call cc-option,-frecord-gcc-switches) SOPE/Version0000644000000000000000000000046715004363604011702 0ustar rootroot# # This file is included by library makefiles to set the version information # of the executable. # Note: # These versions do not say anything about the SOPE "release" # version. It's just the "compatibility" version used for shared libraries. MAJOR_VERSION=4 MINOR_VERSION=9 # next: SUBMINOR_VERSION=2 SOPE/COPYRIGHT0000644000000000000000000000010515004363604011612 0ustar rootrootCopyright (C) 2000-2005 SKYRIX Software AG Contact: info@skyrix.com SOPE/sope-mime/0000755000000000000000000000000015004363604012216 5ustar rootrootSOPE/sope-mime/NGMail/0000755000000000000000000000000015004363604013325 5ustar rootrootSOPE/sope-mime/NGMail/NGMimeMessage.m0000644000000000000000000001324715004363604016133 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeMessage.h" #include "common.h" @implementation NGMimeMessage static NGMimeType *defaultTextType = nil; static NGMimeType *defaultDataType = nil; + (void)initialize { static BOOL isInitialized = NO; if (!isInitialized) { isInitialized = YES; defaultTextType = [[NGMimeType mimeType:@"text/plain; charset=us-ascii"] retain]; defaultDataType = [[NGMimeType mimeType:@"application/octet-stream"] retain]; } } + (id)messageWithHeader:(NGHashMap *)_header { return [[[self alloc] initWithHeader:_header] autorelease]; } - (id)init { return [self initWithHeader:nil]; } - (id)initWithHeader:(NGHashMap *)_header { if ((self = [super init])) { if (_header) self->header = [NGMutableHashMap hashMapWithHashMap: _header]; else self->header = [NGMutableHashMap hashMap]; [self->header retain]; } return self; } - (void)dealloc { [self->header release]; [self->body release]; [self->mimeType release]; [super dealloc]; } /* NGPart */ - (NSEnumerator *)valuesOfHeaderFieldWithName:(NSString *)_name { if ([_name isEqualToString:@"content-type"]) return [[NSArray arrayWithObject:[self contentType]] objectEnumerator]; return [self->header objectEnumeratorForKey:_name]; } - (NSEnumerator *)headerFieldNames { return [self->header keyEnumerator]; } - (void)setBody:(id)_body { ASSIGN(self->body, _body); ASSIGN(self->mimeType, (id)nil); } - (id)body { return self->body; } /* NGMimePart */ - (NGMimeType *)autodetectContentType { const char *bytes; unsigned length; if (!((self->body != nil) && [self->body isKindOfClass:[NSData class]])) return defaultTextType; bytes = [self->body bytes]; length = [self->body length]; while (length > 0) { if ((unsigned char)*bytes > 127) break; bytes++; length--; } return (length > 0) ? defaultDataType : defaultTextType; } - (NGMimeType *)contentType { if (self->mimeType == nil) { NGMimeType *type = nil; if ((type = [self->header objectForKey:@"content-type"]) == nil) type = [self autodetectContentType]; if (![type isKindOfClass:[NGMimeType class]]) type = [NGMimeType mimeType:[type stringValue]]; ASSIGNCOPY(self->mimeType, type); } return self->mimeType; } - (NSString *)contentId { return [[self->header objectForKey:@"content-id"] stringValue]; } - (NSArray *)contentLanguage { return [self->header objectForKey:@"content-language"]; } - (NSString *)contentMd5 { return [[self->header objectForKey:@"content-md5"] stringValue]; } - (NSString *)encoding { return [[self->header objectForKey:@"content-transfer-encoding"] stringValue]; } - (NSString *)contentDescription { return [self->header objectForKey:@"content-description"]; } /* convenience */ - (NSString *)headerForKey:(NSString *)_key { return [[self->header objectEnumeratorForKey:_key] nextObject]; } - (NSArray *)headersForKey:(NSString *)_key { NSEnumerator *values; NSMutableArray *array; id value; if ((values = [self->header objectEnumeratorForKey:_key]) == nil) return nil; array = [NSMutableArray arrayWithCapacity:4]; while ((value = [values nextObject]) != nil) [array addObject:value]; return array; } - (NSArray *)headerKeys { NSEnumerator *values; NSMutableArray *array = nil; id name = nil; if ((values = [self->header keyEnumerator]) == nil) return nil; array = [[NSMutableArray alloc] init]; while ((name = [values nextObject]) != nil) [array addObject:name]; name = [array copy]; [array release]; return [name autorelease]; } - (NSDictionary *)headers { return [self->header asDictionary]; } - (NSString *)headersAsString { // TODO: not correct for MIME NSMutableString *ms; NSEnumerator *keys; NSString *key; ms = [NSMutableString stringWithCapacity:1024]; /* headers */ keys = [[self headerKeys] objectEnumerator]; while ((key = [keys nextObject]) != nil) { NSEnumerator *vals; id val; vals = [[self headersForKey:key] objectEnumerator]; while ((val = [vals nextObject])) { [ms appendString:key]; [ms appendString:@": "]; [ms appendString:[val stringValue]]; [ms appendString:@"\r\n"]; } } return ms; } - (void) setHeader: (id) _header forKey: (NSString *)_key { [self->header setObject: _header forKey: _key]; } /* description */ - (NSString *)description { NSMutableString *d; id b; d = [NSMutableString stringWithCapacity:64]; [d appendFormat:@"<%@[0x%p]: header=%@", NSStringFromClass([self class]), self, self->header]; b = [self body]; if ([b isKindOfClass:[NSString class]] || [b isKindOfClass:[NSData class]]) { if ([b length] < 512) [d appendFormat:@" body=%@", b]; else [d appendFormat:@" body[len=%i]", (int)[b length]]; } else [d appendFormat:@" body=%@", b]; [d appendString:@">"]; return d; } @end /* NGMimeMessage */ SOPE/sope-mime/NGMail/NGMailAddressParser.m0000644000000000000000000007445315004363604017312 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #import #include "NGMailAddressParser.h" #include "NGMailAddress.h" #include "NGMailAddressList.h" #include "common.h" #include @interface NGMailAddressParser(PrivateMethods) - (id)parseQuotedString:(BOOL)_guestMode; - (id)parseWord:(BOOL)_guestMode; - (id)parsePhrase:(BOOL)_guestMode; - (id)parseLocalPart:(BOOL)_guestMode; - (id)parseDomain:(BOOL)_guestMode; - (id)parseAddrSpec:(BOOL)_guestMode; - (id)parseRouteAddr:(BOOL)_guessMode; - (id)parseGroup:(BOOL)_guessMode; - (id)parseMailBox:(BOOL)_guessMode; - (id)parseAddress:(BOOL)_guessMode; @end @implementation NGMailAddressParser static Class StrClass = Nil; static NSNumber *yesNum = nil; + (void)initialize { if (yesNum == nil) yesNum = [[NSNumber numberWithBool:YES] retain]; StrClass = [NSString class]; } static inline NSString *mkStrObj(const unichar *s, unsigned int l) { // TODO: unicode return [(NSString *)[StrClass alloc] initWithCharacters:s length:l]; } static inline id parseWhiteSpaces(NGMailAddressParser *self, BOOL _guessMode) { id returnValue = nil; char text[self->maxLength]; int length = 0; while (self->dataPos < self->maxLength && ((self->data[self->dataPos] == ' ') || (self->data[self->dataPos] == '\n'))) { text[length++] = ' '; self->dataPos++; } if (length) { if (_guessMode) returnValue = yesNum; else { returnValue = [[(NSString *)[StrClass alloc] initWithCString:text length:length] autorelease]; } } return returnValue; } static void dumpBadString(unichar *text, int length) { char *bytes; NSMutableString *logString; int count, max; max = length * sizeof (unichar); logString = [NSMutableString stringWithCapacity: max]; [logString appendString: @"dumping buggy atom string: "]; bytes = (char *) text; for (count = 0; count < max; count++) { [logString appendFormat: @"0x%X", bytes[count]]; if (count < (max - 1)) [logString appendString: @", "]; } NSLog (@"%@", logString); } static inline id parseAtom(NGMailAddressParser *self, BOOL _guessMode) { int keepPos = self->dataPos; // keep reference for backtracking id returnValue = nil; BOOL isAtom = YES; unichar text[self->maxLength + 2]; // token text int length = 0; // token text length BOOL done = NO; do { if (self->dataPos == self->maxLength) { // end of text is reached isAtom = (length > 0); done = YES; } else { register unichar c = self->data[self->dataPos]; switch (c) { case '(' : case ')': case '<': case '>': case '@' : case ',': case ';': case ':': case '\\': case '"': case '.': case '[': case ']' : case ' ': case 127: isAtom = (length > 0); done = YES; break; default: if (c < 32) { isAtom = (length > 0); done = YES; } else { text[length] = c; // store char in text length++; // increase text size (self->dataPos)++; // go ahead } } } } while (!done); if (isAtom) { if (_guessMode) { NSCAssert(length > 0, @"no atom with length=0"); returnValue = yesNum; } else { NSCAssert(length > 0, @"no atom with length=0"); returnValue = [mkStrObj(text, length) autorelease]; if (!returnValue) { dumpBadString(text, length); } NSCAssert([returnValue isKindOfClass:StrClass], @"got no string .."); } } else { self->dataPos = keepPos; returnValue = nil; } return returnValue; } static inline id parseQuotedPair(NGMailAddressParser *self, BOOL _guessMode) { id returnValue = nil; if ((self->maxLength - (self->dataPos)) < 3) { returnValue = nil; } else { if (self->data[self->dataPos] == '\\') { self->dataPos = self->dataPos + 2; if (_guessMode) returnValue = yesNum; else { returnValue = [mkStrObj(&(self->data[self->dataPos - 1]), 1) autorelease]; } } } return returnValue; } static inline id parseQText(NGMailAddressParser *self, BOOL _guessMode) { int keepPos = self->dataPos; // keep reference for backtracking id returnValue = nil; BOOL isQText = YES; unichar text[self->maxLength + 4]; // token text int length = 0; // token text length BOOL done = YES; do { if (self->dataPos == self->maxLength) { // end of text is reached isQText = (length > 0); done = YES; } else { register unichar c = self->data[self->dataPos]; switch (c) { case '"' : case '\\': case 13 : isQText = (length > 0); done = YES; break; default: { text[length] = c; // store char in text length++; // increase text size (self->dataPos)++; // go ahead } } } } while (!done); if (isQText) { if (_guessMode) { NSCAssert(length > 0, @"no qtext with length=0"); returnValue = yesNum; } else { //NSCAssert(length > 0, @"no qtext with length=0"); returnValue = [mkStrObj(text, length) autorelease]; //NSCAssert([returnValue isKindOfClass:StrClass], @"got no string .."); } } else { self->dataPos = keepPos; returnValue = nil; } return returnValue; } static inline id parseDText(NGMailAddressParser *self, BOOL _guessMode) { int keepPos = self->dataPos; // keep reference for backtracking id returnValue = nil; BOOL isDText = YES; unichar text[self->maxLength]; // token text int length = 0; // token text length BOOL done = YES; do { if (self->dataPos == self->maxLength) { // end of text is reached isDText = (length > 0); done = YES; } else { register unichar c = self->data[self->dataPos]; switch (c) { case '[': case ']': case '\\': case 13: isDText = (length > 0); done = YES; break; default: { text[length] = c; // store char in text length++; // increase text size (self->dataPos)++; // go ahead } } } } while (!done); if (isDText) { if (_guessMode) { NSCAssert(length > 0, @"no dtext with length=0"); returnValue = yesNum; } else { NSCAssert(length > 0, @"no dtext with length=0"); returnValue = [mkStrObj(text, length) autorelease]; NSCAssert([returnValue isKindOfClass:StrClass], @"got no string .."); } } else { self->dataPos = keepPos; returnValue = nil; } return returnValue; } static inline id parseDomainLiteral(NGMailAddressParser *self, BOOL _guessMode) { int keepPos = self->dataPos; id returnValue = nil; BOOL returnOK = NO; if (_guessMode) { if (self->dataPos >= self->maxLength || self->data[self->dataPos] != '[') return nil; (self->dataPos)++; // skip starting '"' if (self->dataPos >= self->maxLength) { return nil; } // parses: "suafdjksfd \"sdafsadf" while (self->data[self->dataPos] != ']') { if (self->data[self->dataPos] == '\\') {// skip quoted chars (self->dataPos)++; } (self->dataPos)++; if (self->dataPos >= self->maxLength) { return nil; } } (self->dataPos)++; // skip closing '"' returnValue = yesNum; } else { if (self->dataPos < self->maxLength && self->data[self->dataPos++] == '[') { NSMutableString *ms; id result = nil; ms = [NSMutableString stringWithCapacity:10]; do { if ((result = parseQuotedPair(self, NO))) [ms appendString:result]; else { if ((result = parseDText(self, NO))) [ms appendString:result]; } } while (result); returnValue = ms; if (self->data[self->dataPos++] == ']') returnOK = YES; } if (!returnOK) { if (returnValue) returnValue = nil; self->dataPos = keepPos; } } return returnValue; } /* constructors */ + (id)mailAddressParserWithData:(NSData *)_data { NSString *uniString; uniString = [NSString stringWithCharacters:(unichar *)[_data bytes] length:([_data length] / sizeof(unichar))]; return [(id)self mailAddressParserWithString:uniString]; } + (id)mailAddressParserWithCString:(const char *)_cString { NSString *nsCString; nsCString = [NSString stringWithCString:_cString]; return [(id)self mailAddressParserWithString:nsCString]; } + (id)mailAddressParserWithString:(NSString *)_string { return [[(NGMailAddressParser *)[self alloc] initWithString: _string] autorelease]; } /* Receives one or more mail addresses. Addresses should be seperated by a comma * * returns a string containing well formated addresses or the input as-is * if it couldn't make sense out of it. * The displayName portion is always quoted and multiple addresses will be * separated by a comma */ + (NSString *) sanitizeMailAddresses:(NSString *)originalAddress { NSMutableString* remainder; NSMutableArray* addressList; NSString *address, *displayName; NSRange r, a, c; NSCharacterSet *whitespace; NSUInteger addrStart, addrEnd, commaPos; if (!originalAddress) return nil; whitespace = [NSCharacterSet whitespaceAndNewlineCharacterSet]; addressList = [NSMutableArray arrayWithCapacity: 1]; remainder = [NSMutableString stringWithString: originalAddress]; if (![remainder length]) return @""; /* Remove all quotes and double quotes. Double quotes will be added back later */ [remainder replaceString: @"'" withString: @""]; [remainder replaceString: @"\"" withString: @""]; /* Remove backslashes too, they won't be added back */ [remainder replaceString: @"\\" withString: @""]; while (remainder) { address = @""; displayName = @""; addrStart = addrEnd = NSNotFound; /* strip leading/trailing comma */ remainder = (NSMutableString *)[remainder stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString: @","]]; /* get address part */ r = [remainder rangeOfString: @"<"]; addrStart = r.location; a = [remainder rangeOfString: @"@"]; if (a.location != NSNotFound) c = [remainder rangeOfString: @"," options: 0 range: NSMakeRange(a.location+1, [remainder length]-a.location-1)]; else if (addrStart != NSNotFound) c = [remainder rangeOfString: @"," options: 0 range: NSMakeRange(addrStart+1, [remainder length]-addrStart-1)]; else c = [remainder rangeOfString: @"," options: 0 range: NSMakeRange(0, [remainder length])]; commaPos = c.location; if ((addrStart == NSNotFound) || (commaPos != NSNotFound && commaPos < addrStart)) addrStart = 0; else addrStart++; // consume the '<' r = [remainder rangeOfString: @">" options: 0 range: NSMakeRange(addrStart, [remainder length] - addrStart)]; addrEnd = r.location; if (addrEnd == NSNotFound && commaPos == NSNotFound) { /* use all remainder if there's no closing '>' */ addrEnd = [remainder length]; } else if (!(commaPos == NSNotFound)) { if (addrEnd == commaPos -1) addrEnd = commaPos-1; // ... , else addrEnd = commaPos; // ... addr, addr } /* get address only if there's actually something in between */ if (addrEnd - addrStart > 0) { address = [remainder substringWithRange: NSMakeRange(addrStart, addrEnd-addrStart)]; address = [address stringByTrimmingCharactersInSet: whitespace]; } /* get displayName part */ if (addrStart != NSNotFound && addrStart > 0) { displayName = [remainder substringFromRange: NSMakeRange(0, addrStart-1)]; displayName = [displayName stringByTrimmingCharactersInSet: whitespace]; } if ([address length]) { if (![displayName length]) { [addressList addObject: address]; } else { /* Standard format for addrs: quoted displayName, address in angle brackets */ [addressList addObject: [NSString stringWithFormat: @"\"%@\" <%@>", displayName, address]]; } } if (!(commaPos == NSNotFound)) addrEnd = commaPos; /* setup for next run */ if (addrEnd != NSNotFound && [remainder length] > 0 && addrEnd+1 < [remainder length]-1) remainder = (NSMutableString *)[remainder substringFromIndex: addrEnd+1]; else remainder = nil; } return [addressList componentsJoinedByString:@","]; } - (id)initWithString:(NSString *)_str { if ((self = [super init])) { _str = [NGMailAddressParser sanitizeMailAddresses:_str]; // TODO: remember some string encoding? self->maxLength = [_str length]; self->data = malloc(self->maxLength*sizeof(unichar)); [_str getCharacters:self->data]; self->dataPos = 0; self->errorPos = -1; } return self; } - (id)init { return [self initWithString:nil]; } - (void)dealloc { if (self->data != NULL) { free(self->data); } self->data = NULL; self->maxLength = 0; self->dataPos = 0; [super dealloc]; } /* parsing */ - (id)_parseQuotedStringInGuessMode { int keepPos; if (self->data[self->dataPos] != '"') return nil; keepPos = self->dataPos; (self->dataPos)++; // skip starting '"' // parses: "suafdjksfd \"sdafsadf" while (self->data[self->dataPos] != '"') { if (self->data[self->dataPos] == '\\') /* skip quoted chars */ (self->dataPos)++; (self->dataPos)++; if (self->dataPos >= self->maxLength) { self->dataPos = keepPos; return nil; } } (self->dataPos)++; // skip closing '"' return yesNum; } - (id)parseQuotedString:(BOOL)_guessMode { int keepPos = self->dataPos; id returnValue = nil; BOOL returnOK = NO; if (_guessMode) return [self _parseQuotedStringInGuessMode]; if (self->dataPos < self->maxLength && data[dataPos++] == '"') { NSMutableString *ms; id result = nil; ms = [NSMutableString stringWithCapacity:10]; do { if ((result = parseQuotedPair(self, NO))) [ms appendString:result]; else { if ((result = parseQText(self, NO))) [ms appendString:result]; } } while (result); returnValue = ms; if (self->dataPos < self->maxLength && data[dataPos++] == '"') returnOK = YES; } if (!returnOK) { returnValue = nil; dataPos = keepPos; } return returnValue; } - (id)parseWord:(BOOL)_guessMode { id returnValue; if (self->dataPos < self->maxLength) { if ((returnValue = [self parseQuotedString:_guessMode]) == nil) returnValue = parseAtom(self, _guessMode); } else returnValue = nil; return returnValue; } - (id)_parsePhraseInGuessMode { BOOL isPhrase = NO; id returnValue = nil; id result; do { if ((result = parseWhiteSpaces(self, YES))) { isPhrase = YES; continue; } if ((result = [self parseWord:YES])) { isPhrase = YES; [(NSMutableString *)returnValue appendString:result]; result = parseWhiteSpaces(self, YES); } } while (result); return !isPhrase ? (NSNumber *)nil : yesNum; } - (id)parsePhrase:(BOOL)_guessMode { BOOL isPhrase = NO; id returnValue = nil; id result = nil; NSString *tmp; if (_guessMode) return [self _parsePhraseInGuessMode]; returnValue = [NSMutableString stringWithCapacity:10]; tmp = nil; do { if ((result = parseWhiteSpaces(self, _guessMode))) { tmp = result; ; // isPhrase = YES; // [returnValue appendString:result]; } else if ((result = [self parseWord:_guessMode])) { isPhrase = YES; if (tmp) [(NSMutableString *)returnValue appendString:tmp]; tmp = nil; [(NSMutableString *)returnValue appendString:result]; if (self->dataPos < self->maxLength) { if (self->data[self->dataPos] == '.') { [(NSMutableString *)returnValue appendString:@"."]; self->dataPos++; } } } } while (result); if (!isPhrase || ([returnValue length] == 0)) returnValue = nil; return returnValue; } - (id)_parseLocalPartInGuessMode { id result; if (![self parseWord:YES]) return nil; do { result = nil; if (self->dataPos < self->maxLength && self->data[self->dataPos] == '.') { self->dataPos++; result = [self parseWord:YES]; } } while (result); return yesNum; } - (id)parseLocalPart:(BOOL)_guessMode { NSMutableString *ms; id returnValue = nil; NSString *result = nil; if (_guessMode) return [self _parseLocalPartInGuessMode]; if ((returnValue = [self parseWord:NO]) == nil) return nil; ms = [[returnValue mutableCopy] autorelease]; if (self->dataPos < self->maxLength) { do { if (self->data[self->dataPos] == '.') { self->dataPos++; result = [self parseWord:NO]; if (result) { NSAssert([result isKindOfClass:StrClass], @"parseWord should return string"); [ms appendString:@"."]; [ms appendString:result]; } } else result = nil; } while (result != nil); } return ms; } - (id)_parseDomainInGuessMode { id returnValue = nil; id result = nil; returnValue = parseAtom(self, YES); if (!result) returnValue = parseDomainLiteral(self, YES); if (returnValue) { do { result = nil; if (self->dataPos < self->maxLength && self->data[self->dataPos] == '.') { self->dataPos++; result = parseAtom(self,YES); if (!result) result = parseDomainLiteral(self, YES); } } while (result); } return returnValue; } - (id)parseDomain:(BOOL)_guessMode { NSMutableString *ms; id result; if (_guessMode) return [self _parseDomainInGuessMode]; if ((result = parseAtom(self, NO)) == nil) result = parseDomainLiteral(self, NO); if (result == nil) return nil; ms = [[result mutableCopyWithZone:[self zone]] autorelease]; do { if (self->dataPos < self->maxLength && self->data[self->dataPos] == '.') { self->dataPos++; result = parseAtom(self,NO); if (result == nil) result = parseDomainLiteral(self, NO); if (result) { [ms appendString:@"."]; [ms appendString:result]; } } else result = nil; } while (result); return ms; } - (id)parseAddrSpec:(BOOL)_guessMode { NSMutableString *returnValue = nil; id result; int keepPos = self->dataPos; BOOL returnStatus = NO; if (_guessMode) { id ret; ret = nil; if ([self parseLocalPart:YES]) { if (self->dataPos < self->maxLength && self->data[self->dataPos] == '@') { dataPos++; if ([self parseDomain:YES]) { ret = yesNum; } } } return ret; } if ((result = [self parseLocalPart:NO]) != nil) { returnValue = [[result mutableCopy] autorelease]; result = nil; if (self->dataPos < self->maxLength && self->data[self->dataPos] == '@') { self->dataPos++; if ((result = [self parseDomain:NO])) { [returnValue appendString:@"@"]; [returnValue appendString:result]; returnStatus = YES; } } } if (!returnStatus) { returnValue = nil; dataPos = keepPos; } return returnValue; } - (id)_parseRouteInGuessMode { id result = nil; int keepPos = self->dataPos; BOOL status = YES; if (self->data[self->dataPos] == '@') { status = NO; if ((result = [self parseDomain:YES])) status = YES; } if (status) { parseWhiteSpaces(self,YES); status = (self->data[self->dataPos] == ':') ? YES : NO; } if (status) return yesNum; self->dataPos = keepPos; return nil; } - (id)parseRoute:(BOOL)_guessMode { NSMutableString *returnValue; id result = nil; int keepPos; BOOL status = YES; if (_guessMode) return [self _parseRouteInGuessMode]; keepPos = self->dataPos; returnValue = [NSMutableString stringWithCapacity:10]; if (self->dataPos < self->maxLength && self->data[self->dataPos] == '@') { status = NO; self->dataPos++; if ((result = [self parseDomain:NO])) { status = YES; [returnValue appendString:result]; } } if (status) { parseWhiteSpaces(self,NO); if (self->dataPos < self->maxLength && self->data[self->dataPos] == ':') { status = YES; self->dataPos++; } else { status = NO; } } if (!status) { returnValue = nil; self->dataPos = keepPos; } return returnValue; } - (id)_parseRouteAddrInGuessMode { int keepPos = self->dataPos; id returnValue = nil; id result = nil; BOOL returnStatus = NO; if (self->dataPos < self->maxLength && self->data[self->dataPos] == '<') { dataPos++; result = [self parseRoute:YES]; parseWhiteSpaces(self, YES); if ((result = [self parseAddrSpec:YES])) { parseWhiteSpaces(self, YES); if (self->data[self->dataPos] == '>') { self->dataPos++; returnStatus = YES; } } else if ((result = [self parseWord:YES])) { parseWhiteSpaces(self, YES); if (self->data[self->dataPos] == '>') { self->dataPos++; returnStatus = YES; } } } if (returnStatus) { returnValue = yesNum; } else { returnValue = nil; dataPos = keepPos; } return returnValue; } - (id)parseRouteAddr:(BOOL)_guessMode { NSMutableDictionary *returnValue = nil; int keepPos; id result = nil; BOOL returnStatus = NO; if (_guessMode) return [self _parseRouteAddrInGuessMode]; keepPos = self->dataPos; returnValue = [NSMutableDictionary dictionaryWithCapacity:2]; if (self->dataPos < self->maxLength && self->data[self->dataPos] == '<') { dataPos++; if ((result = [self parseRoute:NO])) [returnValue setObject:result forKey:@"route"]; parseWhiteSpaces(self, NO); if ((result = [self parseAddrSpec:NO])) { parseWhiteSpaces(self, NO); if (self->dataPos < self->maxLength && self->data[self->dataPos] == '>') { self->dataPos++; [returnValue setObject:result forKey:@"address"]; returnStatus = YES; } } else if ((result = [self parseWord:NO])) { parseWhiteSpaces(self, NO); if (self->dataPos < self->maxLength && self->data[self->dataPos] == '>') { self->dataPos++; [returnValue setObject:result forKey:@"address"]; returnStatus = YES; } } } if (!returnStatus) { returnValue = nil; if (!(self->errorPos == -1)) self->errorPos = self->dataPos; self->dataPos = keepPos; } return returnValue; } - (id)parseMailBox:(BOOL)_guessMode { id returnValue = nil; id result = nil; int keepPos = self->dataPos; BOOL returnStatus = NO; if (_guessMode) { if ((result = [self parseAddrSpec:YES])) { returnStatus = YES; } else { if ((result = [self parsePhrase:YES])) { parseWhiteSpaces(self, YES); if ((result = [self parseRouteAddr:YES])) { returnStatus = YES; } } } if (!returnStatus) { self->dataPos = keepPos; returnValue = nil; } else { returnValue = yesNum; } } else { if ((result = [self parseAddrSpec:NO])) { returnValue = [NGMailAddress mailAddressWithAddress:result displayName:nil route:nil]; returnStatus = YES; } else if ((result = [self parseRouteAddr:NO])) { returnValue = [NGMailAddress mailAddressWithAddress: [(NSDictionary *)result objectForKey:@"address"] displayName:nil route:nil]; returnStatus = YES; } else { returnValue = [[[NGMailAddress alloc] init] autorelease]; if ((result = [self parsePhrase:NO])) { [returnValue setDisplayName:result]; parseWhiteSpaces(self, NO); if ((result = [self parseRouteAddr:NO])) { [returnValue setAddress: [(NSDictionary *)result objectForKey:@"address"]]; [returnValue setRoute: [(NSDictionary *)result objectForKey:@"route"]]; returnStatus = YES; } } } if (!returnStatus) { /* try to read until eof or next ',' */ self->dataPos = keepPos; if ((result = [self parseRouteAddr:NO])) { returnValue = [[[NGMailAddress alloc] init] autorelease]; [returnValue setAddress: [(NSDictionary *)result objectForKey:@"address"]]; returnStatus = YES; } } if (!returnStatus) { /* try to read until eof or next ',' */ self->dataPos = keepPos; if ((result = [self parseWord:NO])) { returnValue = [[[NGMailAddress alloc] init] autorelease]; [returnValue setAddress:result]; returnStatus = YES; } } if (!returnStatus) { if (!(self->errorPos == -1)) self->errorPos = self->dataPos; self->dataPos = keepPos; returnValue = nil; } } return returnValue; } - (id)parseGroup:(BOOL)_guessMode { id returnValue = nil; id result = nil; int keepPos = self->dataPos; BOOL returnStatus = NO; if (_guessMode) { if ((result = [self parsePhrase:YES])) { if (self->dataPos < self->maxLength && self->data[self->dataPos] == ':') { self->dataPos++; parseWhiteSpaces(self, YES); if ((result = [self parseMailBox:YES])) { do { parseWhiteSpaces(self, YES); result = nil; if (self->dataPos < self->maxLength && self->data[self->dataPos] == ',') { self->dataPos++; parseWhiteSpaces(self, YES); result = [self parseMailBox:YES]; } } while (result); parseWhiteSpaces(self, YES); if (self->dataPos < self->maxLength && self->data[self->dataPos] == ';') { self->dataPos++; returnStatus = YES; } } } } if (!returnStatus) { returnValue = nil; self->dataPos = keepPos; } else { returnValue = yesNum; } } else { returnValue = [[[NGMailAddressList alloc] init] autorelease]; if ((result = [self parsePhrase:NO])) { [returnValue setGroupName:result]; if (self->dataPos < self->maxLength && self->data[self->dataPos] == ':') { self->dataPos++; parseWhiteSpaces(self, NO); if ((result = [self parseMailBox:NO])) { [returnValue addAddress:result]; do { parseWhiteSpaces(self, NO); result = nil; if (self->dataPos < self->maxLength && self->data[self->dataPos] == ',') { self->dataPos++; parseWhiteSpaces(self, NO); result = [self parseMailBox:NO]; if (result) { [returnValue addAddress:result]; } } } while (result); parseWhiteSpaces(self, NO); if (self->dataPos < self->maxLength && self->data[self->dataPos] == ';') { self->dataPos++; returnStatus = YES; } } } } if (!returnStatus) { returnValue = nil; self->dataPos = keepPos; } } return returnValue; } - (id)parseAddress:(BOOL)_guessMode { id returnValue = nil; int keepPos = self->dataPos; if (_guessMode) { returnValue = [self parseMailBox:YES]; if (!returnValue) returnValue = [self parseGroup:YES]; if (!returnValue) self->dataPos = keepPos; } else { returnValue = [self parseMailBox:NO]; if (!returnValue) returnValue = [self parseGroup:NO]; if (!returnValue) self->dataPos = keepPos; } return returnValue; } - (NSArray *)parseAddressList { NGMailAddress *address = nil; NSMutableArray *addrs = nil; addrs = [NSMutableArray arrayWithCapacity:16]; while (self->dataPos < self->maxLength) { address = [self parseAddress:NO]; if (address) [addrs addObject:address]; else break; if (self->dataPos < self->maxLength) { parseWhiteSpaces(self, NO); if (self->dataPos < self->maxLength && self->data[self->dataPos] == ',') { self->dataPos++; if (self->dataPos < self->maxLength) parseWhiteSpaces(self, NO); } } } return [[addrs copy] autorelease]; } - (id)parse { dataPos = 0; errorPos = -1; return [self parseAddress:NO]; } - (int)errorPosition { return self->errorPos; } /* description */ - (NSString *)description { return [StrClass stringWithFormat:@"<%@[0x%p]>", NSStringFromClass([self class]), self]; } @end /* NGMailAddressParser */ SOPE/sope-mime/NGMail/NGPop3Support.m0000644000000000000000000001005115004363604016143 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGPop3Support.h" #include "NGPop3Client.h" #include "common.h" @implementation NGPop3Response - (id)initWithLine:(NSString *)_line { if ((self = [super init])) { self->line = [_line copy]; } return self; } - (void)dealloc { [self->line release]; [super dealloc]; } + (id)responseWithLine:(NSString *)_line { return [[[self alloc] initWithLine:_line] autorelease]; } /* accessors */ - (BOOL)isPositive { return [self->line hasPrefix:@"+OK"]; } - (NSString *)line { return self->line; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"", self, [self isPositive] ? "YES" : "NO", [self line]]; } @end /* NGPop3Response */ @implementation NGPop3MessageInfo - (id)initWithNumber:(int)_num size:(int)_size client:(NGPop3Client *)_client{ if ((self = [super init])) { self->messageNumber = _num; self->messageSize = _size; self->client = [_client retain]; } return self; } + (id)infoForMessage:(int)_num size:(int)_size client:(NGPop3Client *)_client { return [[[self alloc] initWithNumber:_num size:_size client:_client] autorelease]; } - (void)dealloc { [self->client release]; [super dealloc]; } /* accessors */ - (int)messageNumber { return self->messageNumber; } - (int)size { return self->messageSize; } - (NGPop3Client *)pop3Client { return self->client; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"", self, [self messageNumber], [self size]]; } @end /* NGPop3Response */ @implementation NGPop3MailDropEnumerator - (id)initWithMessageInfoEnumerator:(NSEnumerator *)_infos { self->msgInfos = [_infos retain]; return self; } - (void)dealloc { [self->msgInfos release]; [super dealloc]; } - (id)nextObject { NGPop3MessageInfo *info = [self->msgInfos nextObject]; NGMimeMessage *message = nil; if (info != nil) { message = [[info pop3Client] messageWithNumber:[info messageNumber]]; if (message == nil) { NSLog(@"ERROR: could not retrieve message %i, skipping", [info messageNumber]); message = [self nextObject]; } } return message; } @end /* NGPop3MailDropEnumerator */ // ******************** Exceptions ******************** @implementation NGPop3Exception @end /* NGPop3Exception */ @implementation NGPop3StateException - (id)init { return [self initWithClient:nil requiredState:0]; } - (id)initWithClient:(NGPop3Client *)_client requiredState:(NGPop3State)_state { NSString *stateString = nil; switch(_state) { case NGPop3State_unconnected: stateString = @"unconnected"; break; case NGPop3State_AUTHORIZATION: stateString = @"AUTHORIZATION"; break; case NGPop3State_TRANSACTION: stateString = @"TRANSACTION"; break; case NGPop3State_UPDATE: stateString = @"UPDATE"; break; default: stateString = @"unknown"; break; } if ((self = [super initWithFormat:@"operation can only perform in state %@", stateString])) { self->requiredState = _state; } return self; } // accessors - (NGPop3State)requiredState { return self->requiredState; } @end /* NGPop3StateException */ SOPE/sope-mime/NGMail/NGMimeMessageParser.h0000644000000000000000000000352315004363604017277 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGMimeMessageParser_H__ #define __NGMime_NGMimeMessageParser_H__ #include /* NGMimeMessageParser This class is used to parse RFC 822 MIME messages. It's the correct class to parse email messages. Usage: data = [NSData dataWithContentsOfMappedFile:@"MyMail.eml"]; parser = [[NGMimeMessageParser alloc] init]; part = [parser parsePartFromData:data]; NSLog(@"Subject: %@", [part valuesOfHeaderFieldWithName:@"subject"]); [parser release]; */ @interface NGMimeMessageParser : NGMimePartParser @end @interface NSData(MimeQPHeaderFieldDecoding) /* This method decodes header fields which contain quoted printable information. Note that the return value can be both, an NSString or an NSData depending on the case. Sample: attachment; filename="langerp=?iso-8859-15?q?=FC=E4=F6=20Name=F6=F6=F6=201234456=2Exls?=" */ - (id)decodeQuotedPrintableValueOfMIMEHeaderField:(NSString *)_field; @end @interface NGMimeRfc822BodyParser : NGMimeBodyParser @end #endif /* __NGMime_NGMimeMessageParser_H__ */ SOPE/sope-mime/NGMail/NGSendMail.m0000644000000000000000000003254015004363604015430 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGSendMail.h" #include "NGMimeMessageGenerator.h" #include "NGMailAddressParser.h" #include "NGMailAddress.h" #include "common.h" // TODO: this class is derived from the LSMailDeliverCommand in OGo Logic, // it still needs a lot of cleanup @implementation NGSendMail + (id)sharedSendMail { static NGSendMail *sendmail = nil; // THREAD if (sendmail == nil) sendmail = [[self alloc] init]; return sendmail; } - (id)initWithExecutablePath:(NSString *)_path { if ((self = [super init])) { NSUserDefaults *ud; ud = [NSUserDefaults standardUserDefaults]; self->isLoggingEnabled = [ud boolForKey:@"SMTPDebugEnabled"]; self->shouldOnlyUseMailboxName = [ud boolForKey:@"UseOnlyMailboxNameForSendmail"]; if ([_path isNotNull]) self->executablePath = [_path copy]; else { #if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY self->executablePath = @"/usr/sbin/sendmail"; #else self->executablePath = @"/usr/lib/sendmail"; #endif } } return self; } - (id)init { NSString *p; p = [[NSUserDefaults standardUserDefaults] stringForKey:@"WOSendMail"]; return [self initWithExecutablePath:p]; } - (void)dealloc { [self->executablePath release]; [super dealloc]; } /* accessors */ - (NSString *)executablePath { return self->executablePath; } - (BOOL)isSendLoggingEnabled { return self->isLoggingEnabled; } - (BOOL)shouldOnlyUseMailboxName { return self->shouldOnlyUseMailboxName; } /* operations */ - (BOOL)isSendMailAvailable { NSFileManager *fm; fm = [NSFileManager defaultManager]; return [fm isExecutableFileAtPath:[self executablePath]]; } /* errors */ - (NSException *)missingMailToSendError { return [NSException exceptionWithName:@"NGSendMailException" reason:@"missing mail content to send" userInfo:nil]; } - (NSException *)cannotWriteTemporaryFileError { return [NSException exceptionWithName:@"NGSendMailException" reason:@"failed to write temporary mail file" userInfo:nil]; } - (NSException *)failedToStartSendMailError:(int)_errorCode { return [NSException exceptionWithName:@"NGSendMailException" reason:@"failed to start sendmail tool" userInfo:nil]; } - (NSException *)failedToSendFileToSendMail:(NSString *)_path { return [NSException exceptionWithName:@"NGSendMailException" reason:@"failed to send message file to sendmail tool" userInfo:nil]; } - (NSException *)failedToSendDataToSendMail:(NSData *)_data { return [NSException exceptionWithName:@"NGSendMailException" reason:@"failed to send message data to sendmail tool" userInfo:nil]; } - (NSException *)_errorExceptionWithReason:(NSString *)_reason { return [NSException exceptionWithName:@"NGSendMailException" reason:_reason userInfo:nil]; #if 0 // TODO: in LSMailDeliverCommand, check whether someone depends on it return [LSDBObjectCommandException exceptionWithStatus:NO object:self reason:_reason userInfo:nil]; #endif } - (NSException *)_handleSendMailErrorCode:(int)_ec sendmail:(NSString *)_cmdl { if (_ec == 32512) { NSString *str; str = [@"NoExecutableSendmailBinary " stringByAppendingString: [self executablePath]]; [self logWithFormat:@"%@ is no executable file", [self executablePath]]; return [self _errorExceptionWithReason:str]; } if (_ec == 17664) { [self logWithFormat:@"sendmail: message file too big!"]; return [self _errorExceptionWithReason:@"MessageFileTooBig"]; } [self logWithFormat:@"[1] Could not write mail to sendmail! <%d>",_ec]; return [self _errorExceptionWithReason:@"FailedToSendMail"]; } /* temporary file */ - (void)_removeMailTmpFile:(NSString *)_path { if ([_path length] < 2) return; [[NSFileManager defaultManager] removeFileAtPath:_path handler:nil]; } - (NSString *)_generateTemporaryFileForPart:(id)_part { NGMimeMessageGenerator *gen; NSString *p; gen = [[NGMimeMessageGenerator alloc] init]; p = [[gen generateMimeFromPartToFile:_part] copy]; [gen release]; gen = nil; return [p autorelease]; } /* parsing mail addresses */ - (NSString *)mailAddrForStr:(NSString *)_str { NGMailAddressParser *parser; NGMailAddress *addr; if (![self shouldOnlyUseMailboxName]) return _str; parser = nil; addr = nil; // TODO: make NGMailAddressParser not throw exceptions, // then remove the handler NS_DURING { parser = [NGMailAddressParser mailAddressParserWithString:_str]; addr = [[parser parseAddressList] lastObject]; } NS_HANDLER { fprintf(stderr,"ERROR: get exception during parsing address %s\n", [[localException description] cString]); parser = nil; addr = nil; } NS_ENDHANDLER; return (addr) ? [addr address] : _str; } /* logging */ - (void)_logMailSend:(NSString *)sendmail ofPath:(NSString *)_p { fprintf(stderr, "%s \n", [sendmail cString]); fprintf(stderr, "read data from %s\n", [_p cString]); } - (void)_logMailSend:(NSString *)sendmail ofData:(NSData *)_data { fprintf(stderr, "%s \n", [sendmail cString]); if ([_data length] > 5000) { NSData *data; data = [_data subdataWithRange:NSMakeRange(0,5000)]; fprintf(stderr, "%s...\n", (unsigned char *)[data bytes]); } else fprintf(stderr, "%s\n", (char *)[_data bytes]); } /* sending the mail */ - (FILE *)openStreamToSendMail:(NSString *)_cmdline { return [_cmdline isNotNull] ? popen([_cmdline cString], "w") : NULL; } - (int)closeStreamToSendMail:(FILE *)_mail { if (_mail == NULL) return 0; return pclose(_mail); } - (NSMutableString *)buildSendMailCommandLineWithSender:(NSString *)_sender { NSMutableString *sendmail; if (![[self executablePath] isNotEmpty]) return nil; sendmail = [NSMutableString stringWithCapacity:256]; [sendmail setString:[self executablePath]]; /* don't treat a line with just "." as EOF */ [sendmail appendString:@" -i "]; /* add sender when available */ if (_sender != nil) { NSString *f; f = [[_sender componentsSeparatedByString:@","] componentsJoinedByString:@" "]; [sendmail appendString:@"-f "]; [sendmail appendString:f]; [sendmail appendString:@" "]; } return sendmail; } - (NSException *)_handleAppendMessageException:(NSException *)_exception { [self logWithFormat:@"catched exception: %@", _exception]; return nil; } - (BOOL)_appendMessageFile:(NSString *)_p to:(FILE *)_fd { NGFileStream *fs; int fileLen; BOOL result; if (_p == nil) { NSLog(@"ERROR: call %s without self->messageTmpFile", __PRETTY_FUNCTION__); return NO; } fileLen = [[[[NSFileManager defaultManager] fileAttributesAtPath:_p traverseLink:NO] objectForKey:NSFileSize] intValue]; if (fileLen == 0) { NSLog(@"ERROR[%s] missing file at path %@", __PRETTY_FUNCTION__, _p); return NO; } fs = [(NGFileStream *)[NGFileStream alloc] initWithPath:_p]; if (![fs openInMode:@"r"]) { NSLog(@"ERROR[%s]: could not open file stream for temp-file for " @"reading: %@", __PRETTY_FUNCTION__, _p); [fs release]; fs = nil; return NO; } result = YES; NS_DURING { int read; int alreadyRead; int bufCnt = 8192; char buffer[bufCnt+1]; alreadyRead = 0; read = (bufCnt > (fileLen - alreadyRead)) ? fileLen - alreadyRead : bufCnt; while ((read = [fs readBytes:buffer count:read]) != 0) { int rc; alreadyRead += read; rc = fwrite(buffer, read, 1, _fd); if (rc == 0) { fprintf(stderr, "%s: Failed to write %i bytes to process\n", __PRETTY_FUNCTION__, alreadyRead); break; } if (alreadyRead == fileLen) break; } } NS_HANDLER { [[self _handleAppendMessageException:localException] raise]; result = NO; } NS_ENDHANDLER; [fs release]; fs = nil; return result; } - (BOOL)_appendData:(NSData *)_data to:(FILE *)_fd { int written; if (![_data isNotEmpty]) return YES; written = fwrite((char *)[_data bytes], [_data length], 1, _fd); if (written > 0) { [self logWithFormat:@"wrote %d, length %d", written, [_data length]]; return YES; } [self logWithFormat:@"[2] Could not write mail to sendmail <%d>", errno]; if ([_data length] > 5000) [self logWithFormat:@"[2] message: [size: %d]", [_data length]]; else [self logWithFormat:@"[2] message: <%s>", (char *)[_data bytes]]; return NO; } - (void)addRecipients:(NSArray *)_recipients toCmdLine:(NSMutableString *)_cmdline { NSEnumerator *enumerator; NSString *str; enumerator = [_recipients objectEnumerator]; while ((str = [enumerator nextObject]) != nil) { NSEnumerator *e; NSString *s; if ([str rangeOfString:@","].length == 0) { [_cmdline appendFormat:@"'%@' ", [self mailAddrForStr:str]]; continue; } e = [[str componentsSeparatedByString:@","] objectEnumerator]; while ((s = [e nextObject])) { s = [[s componentsSeparatedByString:@"'"] componentsJoinedByString:@""]; s = [[s componentsSeparatedByString:@","] componentsJoinedByString:@""]; [_cmdline appendFormat:@"'%@'", [self mailAddrForStr:s]]; } [_cmdline appendString:@" "]; } } /* main entry methods */ - (NSException *)sendMailAtPath:(NSString *)_path toRecipients:(NSArray *)_to sender:(NSString *)_sender { NSMutableString *sendmail; FILE *toMail = NULL; NSException *error; int errorCode; BOOL ok; if (_path == nil) return [self missingMailToSendError]; sendmail = [self buildSendMailCommandLineWithSender:_sender]; [self addRecipients:_to toCmdLine:sendmail]; if ((toMail = [self openStreamToSendMail:sendmail]) == NULL) return [self failedToStartSendMailError:errno]; if ([self isSendLoggingEnabled]) [self _logMailSend:sendmail ofPath:_path]; ok = [self _appendMessageFile:_path to:toMail]; error = nil; if ((errorCode = [self closeStreamToSendMail:toMail]) != 0) { if (ok) { error = [self _handleSendMailErrorCode:errorCode sendmail:sendmail]; } } if (!ok) error = [self failedToSendFileToSendMail:_path]; return error; /* nil means 'everything is awesome' */ } - (NSException *)sendMailData:(NSData *)_data toRecipients:(NSArray *)_to sender:(NSString *)_sender { NSMutableData *cleaned_data; NSMutableString *sendmail; FILE *toMail = NULL; NSException *error; int errorCode, len, mlen, i; const char *bytes; char *mbytes; BOOL ok; if (_data == nil) return [self missingMailToSendError]; sendmail = [self buildSendMailCommandLineWithSender:_sender]; [self addRecipients:_to toCmdLine:sendmail]; if ((toMail = [self openStreamToSendMail:sendmail]) == NULL) return [self failedToStartSendMailError:errno]; if ([self isSendLoggingEnabled]) [self _logMailSend:sendmail ofData:_data]; // // SOPE sucks in many ways and that is one of them. The headers are actually // correctly encoded (trailing \r\n is inserted) but not the base64 encoded // data since it uses SOPE's dataByEncodingBase64 function which says: // // NGBase64Coding.h:- (NSData *)dataByEncodingBase64; /* Note: inserts '\n' every 72 chars */ // len = [_data length]; i = mlen = 0; cleaned_data = [NSMutableData dataWithLength: len]; bytes = [_data bytes]; mbytes = [cleaned_data mutableBytes]; while (i < len) { if (*bytes == '\r' && (i+1 < len) && *(bytes+1) == '\n') { bytes++; i++; } *mbytes = *bytes; mbytes++; bytes++; i++; mlen++; } [cleaned_data setLength: mlen]; ok = [self _appendData:cleaned_data to:toMail]; error = nil; if ((errorCode = [self closeStreamToSendMail:toMail]) != 0) { if (ok) { error = [self _handleSendMailErrorCode:errorCode sendmail:sendmail]; } } if (!ok) error = [self failedToSendDataToSendMail:_data]; return error; /* nil means 'everything is awesome' */ } - (NSException *)sendMimePart:(id)_pt toRecipients:(NSArray *)_to sender:(NSString *)_sender { NSException *error; NSString *tmpfile; if (_pt == nil) return [self missingMailToSendError]; /* generate file for part */ if ((tmpfile = [self _generateTemporaryFileForPart:_pt]) == nil) return [self cannotWriteTemporaryFileError]; /* send file */ error = [self sendMailAtPath:tmpfile toRecipients:_to sender:_sender]; /* delete temporary file */ [self _removeMailTmpFile:tmpfile]; return error; } @end /* NGSendMail */ SOPE/sope-mime/NGMail/NGMBoxReader.m0000644000000000000000000001514015004363604015721 0ustar rootroot/* Copyright (C) 2000-2006 SKYRIX Software AG Copyright (C) 2006 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMBoxReader.h" #include "NGMimeMessageParser.h" #include "common.h" #include @implementation NGMBoxReader static inline int __readByte(NGMBoxReader *self); static inline void __appendByte(NGMBoxReader *self, NSMutableData *_data, IMP _readBytes, int _c); + (id)readerForMBox:(NSString *)_path { NGFileStream *fs; NGBufferedStream *bs; fs = [NGFileStream alloc]; /* to keep gcc 3.4 happy */ fs = [[fs initWithPath:_path] autorelease]; bs = [NGBufferedStream filterWithSource:fs]; [fs openInMode:NGFileReadOnly]; return [[(NGMBoxReader *)[self alloc] initWithSource:bs] autorelease]; } + (id)mboxWithSource:(id)_in { return [[(NGMBoxReader *)[self alloc] initWithSource:_in] autorelease]; } - (id)init { return [self initWithSource:nil]; } - (id)initWithSource:(id)_in { if ((self = [super init])) { self->source = [_in retain]; self->isEndOfStream = NO; self->lastDate = nil; self->separator = @"From -"; self->readByte = [self->source respondsToSelector:@selector(methodForSelector:)] ? (int(*)(id, SEL))[(NSObject *)self->source methodForSelector:@selector(readByte)] : NULL; } return self; } - (void)dealloc { [self->source release]; [self->lastDate release]; [self->separator release]; self->readByte = NULL; [super dealloc]; } - (id)nextMessage { // Macros #define AppendBytes(_buf, _cnt) \ appendBytes(msgData, @selector(appendBytes:length:), _buf, _cnt) #define AppendByte(_c) \ __appendByte(self, msgData, appendBytes, _c) // Method NSMutableData *msgData = nil; IMP appendBytes = NULL; const int bufLen = 256; int bufCnt = 0; int c = 0; char buf[bufLen]; int sepLength = [self->separator length]; const char *sepStrbuf = NULL; sepStrbuf = [self->separator cString]; msgData = [[NSMutableData allocWithZone:[self zone]] initWithCapacity:4096]; appendBytes = [msgData methodForSelector:@selector(appendBytes:length:)]; //read from-line if (self->isEndOfStream) return nil; if (self->lastDate == nil) { // start of MBox from-line length < 255 bufCnt = 0; while (bufCnt < sepLength) { // parse form c = __readByte(self); buf[bufCnt++] = c; } if (strncmp(buf, sepStrbuf, sepLength) != 0) { NSLog(@"WARNING: no %@ at begin of MBox %s", self->separator, buf); } bufCnt = 0; while ((c = __readByte(self)) != '\n') { // parse date < 255 buf[bufCnt++] = c; if (bufCnt >= bufLen) { NSLog(@"WARNING: too long from-line"); break; } } if (buf[bufCnt - 1] == '\r') self->lastDate = [[NSString allocWithZone:[self zone]] initWithCString:buf length:bufCnt-1]; else self->lastDate = [[NSString allocWithZone:[self zone]] initWithCString:buf length:bufCnt]; bufCnt = 0; } c = -2; do { if (c != -2) { AppendBytes(buf, bufCnt); // write buffer to data bufCnt = 0; if (c != '\n') { // no end of line AppendByte(c); while ((c = __readByte(self)) != '\n') { buf[bufCnt++] = c; if (bufCnt >= bufLen) { AppendBytes(buf, bufCnt); bufCnt = 0; } } if (bufCnt > 0) { AppendBytes(buf, bufCnt); bufCnt = 0; } AppendByte(c); } else AppendByte(c); } while ((c = __readByte(self)) != '\n' && bufCnt < sepLength) { // read oly until seperator length if (c == -1) break; buf[bufCnt++] = c; } if (c == -1) break; } while (strncmp(buf, sepStrbuf, sepLength) != 0); if (c == -1) { self->isEndOfStream = YES; } else { // read from-line bufCnt = 0; while ((c = __readByte(self)) != '\n') { // from-line is not longer // than 255 ( I hope it :)) buf[bufCnt++] = c; if (bufCnt >= bufLen) { NSLog(@"WARNING: too long from-line"); break; } } [self->lastDate release]; self->lastDate = [[NSString alloc] initWithCString:buf length:bufCnt]; bufCnt = 0; } if ([msgData length] == 0) // end, no msg data return nil; { // build result NGMimeMessageParser *parser = nil; NGDataStream *stream = nil; id part; *(&part) = nil; parser = [[NGMimeMessageParser alloc] init]; stream = [[NGDataStream alloc] initWithData:msgData]; NS_DURING part = [parser parsePartFromStream:stream]; NS_HANDLER {} NS_ENDHANDLER; if (part == nil) { fprintf(stderr, "mbox: failed to parse message:\n%s", [[NSString stringWithCString:[msgData bytes] length:[msgData length]] cString]); } [parser release]; parser = nil; [stream release]; stream = nil; [msgData release]; msgData = nil; return part; } } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"<%@[0x%p] source=%@ endOfStream=%@", NSStringFromClass([self class]), self, self->source, self->isEndOfStream ? @"YES" : @"NO"]; } /* functions */ static inline int __readByte(NGMBoxReader *self) { return (self->readByte) ? self->readByte(self->source, @selector(readByte)) : [self->source readByte]; } static inline void __appendByte(NGMBoxReader *self, NSMutableData *_data, IMP _readBytes, int _c) { unsigned char c = _c; _readBytes(_data, @selector(appendBytes:length:), &c, 1); } @end /* NGMBoxReader */ SOPE/sope-mime/NGMail/NSData+MimeQP.m0000644000000000000000000001572515004363604015753 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #include @implementation NSData(MimeQPHeaderFieldDecoding) static Class NSStringClass = Nil; static Class NGMimeTypeClass = Nil; - (id)decodeQuotedPrintableValueOfMIMEHeaderField:(NSString *)_name { // check data for 8-bit headerfields (RFC 2047 (MIME PART III)) /* TODO: document This method returns an NSString or an NSData object (or nil). */ enum { NGMimeMessageParser_quoted_start = 1, NGMimeMessageParser_quoted_charSet = 2, NGMimeMessageParser_quoted_qpData = 3, NGMimeMessageParser_quoted_end = 4 } status = NGMimeMessageParser_quoted_start; unsigned int length; const unsigned char *bytes, *firstEq; BOOL foundQP = NO; /* setup statics */ if (NSStringClass == Nil) NSStringClass = [NSString class]; if (NGMimeTypeClass == Nil) NGMimeTypeClass = [NGMimeType class]; /* begin */ length = [self length]; /* check whether the string is long enough to be quoted etc */ if (length <= 6) return self; /* check whether the string contains QP tokens ... */ bytes = [self bytes]; if ((firstEq = memchr(bytes, '=', length)) == NULL) return self; /* process data ... (quoting etc) */ { unichar *buffer; unsigned int bufLen, maxBufLen; NSString *charset; BOOL appendLC, encodedLastWord; int cnt, tmp; unsigned char encoding; buffer = calloc(length + 13, sizeof(unichar)); maxBufLen = length + 3; buffer[maxBufLen - 1] = '\0'; bufLen = 0; encoding = 0; tmp = -1; appendLC = YES; encodedLastWord = NO; charset = nil; status = NGMimeMessageParser_quoted_start; /* copy data up to first '=' sign */ if ((cnt = (firstEq - bytes)) > 0) { for (; bufLen < cnt; bufLen++) buffer[bufLen] = bytes[bufLen]; } for (; cnt < (length - 1); cnt++) { appendLC = YES; if (status == NGMimeMessageParser_quoted_start) { if ((bytes[cnt] == '=') && (bytes[cnt + 1] == '?')) { // found begin cnt++; if (encodedLastWord && tmp != -1) { // We must remove the whitespace added since `tmp` int i; for (i = bufLen - 1; i >= tmp; i--) buffer[i] = '\0'; bufLen = tmp; } tmp = -1; status = NGMimeMessageParser_quoted_charSet; } else if (bytes[cnt] == ' ' || bytes[cnt] == '\r' || bytes[cnt] == '\n' || bytes[cnt] == '\t') { // We must ignore whitespace between qp encoded strings. // Both are valid: // (ab) -> (=?utf-8?q?a?= =?utf-8?q?b?=) // (ab) -> (=?utf-8?q?a?= // =?utf-8?q?b?=) if (tmp == -1) // first whitespace found tmp = bufLen; buffer[bufLen++] = bytes[cnt]; } else { encodedLastWord = NO; buffer[bufLen++] = bytes[cnt]; } } else if (status == NGMimeMessageParser_quoted_charSet) { if (tmp == -1) tmp = cnt; if (bytes[cnt] == '?') { charset = [NSStringClass stringWithCString:(char *)(bytes + tmp) length:(cnt - tmp)]; tmp = -1; if ((length - cnt) > 2) { // set encoding (eg 'q' for quoted printable) cnt++; // skip '?' encoding = bytes[cnt]; cnt++; // skip encoding status = NGMimeMessageParser_quoted_qpData; } else { // unexpected end NSLog(@"WARNING: unexpected end of header"); appendLC = NO; break; } } } else if (status == NGMimeMessageParser_quoted_qpData) { if (tmp == -1) tmp = cnt; if ((bytes[cnt] == '?') && (bytes[cnt + 1] == '=')) { NSData *tmpData; NSString *tmpStr; unsigned int tmpLen; tmpData = _rfc2047Decoding(encoding, (char *)bytes + tmp, cnt - tmp); foundQP = YES; /* create a temporary string for charset conversion ... Note: the headerfield is currently held in ISO Latin 1 */ tmpStr = [NSStringClass stringWithData:tmpData usingEncodingNamed:charset]; if (tmpStr == nil) { NSStringEncoding enc; enc = [NGMimeTypeClass stringEncodingForCharset:charset]; tmpStr = [[[NSStringClass alloc] initWithData:tmpData encoding:enc] autorelease]; // Fall-back to ISO Latin 1 if the decoding using the specified charset // has failed. Note that we shouldn't be doing this here, we should let // the application decide what to do but SOPE is just too lame and does // not expose a failure vs. the initial value of the header if (!tmpStr) tmpStr = [[[NSStringClass alloc] initWithData:tmpData encoding:NSISOLatin1StringEncoding] autorelease]; } tmpLen = [tmpStr length]; if ((tmpLen + bufLen) < maxBufLen) { [tmpStr getCharacters:(buffer + bufLen)]; bufLen += tmpLen; } else { [self errorWithFormat:@"%s: quoted data to large --> ignored %@", __PRETTY_FUNCTION__, tmpStr]; } tmp = -1; cnt++; appendLC = YES; status = NGMimeMessageParser_quoted_start; encodedLastWord = YES; } } } if (appendLC) { if (cnt < length) { buffer[bufLen] = bytes[cnt]; bufLen++; } } buffer[bufLen] = '\0'; while(bufLen > 1 && buffer[bufLen-1] == '\0') bufLen--; { id data; data = nil; if (buffer && foundQP) { data = [[[NSStringClass alloc] initWithCharacters:buffer length:bufLen] autorelease]; if (data == nil) { [self warnWithFormat: @"%s: got no string for buffer '%s', length '%i' !", __PRETTY_FUNCTION__, buffer, bufLen]; } } if (data == nil) data = self; /* we return an NSData */ if (buffer != NULL) free(buffer); buffer = NULL; return data; } } return self; } @end /* NSData(MimeQPHeaderFieldDecoding) */ SOPE/sope-mime/NGMail/NGMimeMessageBodyGenerator.m0000644000000000000000000000213215004363604020607 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeMessageGenerator.h" #include "NGMimeMessage.h" #include "common.h" @implementation NGMimeMessageBodyGenerator /* encoding data */ - (NSData *)encodeData:(NSData *)_data forPart:(id)_part additionalHeaders:(NGMutableHashMap *)_addHeaders { return _data; } @end /* NGMimeMessageBodyGenerator */ SOPE/sope-mime/NGMail/NGSmtpSupport.m0000644000000000000000000001255715004363604016262 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGSmtpSupport.h" #include "common.h" NSString *NGSmtpDescriptionForReplyCode(NGSmtpReplyCode _code) { NSString *text = nil; switch (_code) { // 100 codes, positive preliminary reply // 200 codes, positive completion reply case NGSmtpSystemStatus: // 211 text = @"System status, or system help reply"; break; case NGSmtpHelpMessage: // 214 text = @"Help message"; break; case NGSmtpServiceReady: // 220 text = @" Service ready"; break; case NGSmtpServiceClosingChannel: // 221 text = @" Service closing transmission channel"; break; case NGSmtpActionCompleted: // 250 text = @"Requested mail action okay, completed"; break; case NGSmtpUserNotLocalWillForward: // 251 text = @"User not local; will forward to "; break; // 300 codes, positive intermediate reply case NGSmtpStartMailInput: // 354 text = @"Start mail input; end with ."; break; // 400 codes, transient negative completion reply case NGSmtpServiceNotAvailable: // 421 text = @" Service not available, closing transmission channel"; break; case NGSmtpMailboxBusy: // 450 text = @"Requested mail action not taken: mailbox unavailable [E.g., mailbox busy]"; break; case NGSmtpErrorInProcessing: // 451 text = @"Requested action aborted: local error in processing"; break; case NGSmtpInsufficientStorage: // 452 text = @"Requested action not taken: insufficient system storage"; break; // 500 codes, permanent negative completion reply case NGSmtpInvalidCommand: // 500 text = @"Syntax error, command unrecognized " @"[This may include errors such as command line too long]"; break; case NGSmtpInvalidParameter: // 501 text = @"Syntax error in parameters or arguments"; break; case NGSmtpCommandNotImplemented: // 502 text = @"Command not implemented"; break; case NGSmtpBadCommandSequence: // 503 text = @"Bad sequence of commands"; break; case NGSmtpParameterNotImplemented: // 504 text = @"Command parameter not implemented"; break; case NGSmtpMailboxNotFound: // 550 text = @"Requested action not taken: mailbox unavailable " @"[E.g., mailbox not found, no access]"; break; case NGSmtpUserNotLocalTryForward: // 551 text = @"User not local; please try "; break; case NGSmtpExceededStorageAllocation: // 552 text = @"Requested mail action aborted: exceeded storage allocation"; break; case NGSmtpMailboxNameNotAllowed: // 553 text = @"Requested action not taken: mailbox name not allowed" @"[E.g., mailbox syntax incorrect]"; break; case NGSmtpTransactionFailed: // 554 text = @"Transaction failed"; break; default: text = [NSString stringWithFormat:@"", _code]; break; } return text; } @implementation NGSmtpResponse - (id)initWithCode:(NGSmtpReplyCode)_code text:(NSString *)_text { if ((self = [super init])) { self->code = _code; self->text = [_text copy]; } return self; } + (id)responseWithCode:(NGSmtpReplyCode)_code text:(NSString *)_text { return [[[self alloc] initWithCode:_code text:_text] autorelease]; } - (void)dealloc { [self->text release]; [super dealloc]; } /* accessors */ - (NGSmtpReplyCode)code { return self->code; } - (NSString *)text { return self->text; } /* values */ - (int)intValue { return [self code]; } - (NSString *)stringValue { return [self text]; } /* special accessors */ - (NSString *)lastLine { const char *cstr = [[self text] cString]; unsigned len = [[self text] cStringLength]; if (cstr) { cstr += len; // goto '\0' cstr--; len--; // goto last char while ((*cstr != '\n') && (len > 0)) { cstr--; len--; } } else len = 0; return (len > 0) ? [NSString stringWithCString:(cstr + 1)] : (id)[self text]; } - (BOOL)isPositive { return ((self->code >= 200) && (self->code < 300)); } - (BOOL)isTransientNegative { return ((self->code >= 400) && (self->code < 500)); } - (BOOL)isPermanentNegative { return ((self->code >= 500) && (self->code < 600)); } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"", [self code], [self lastLine]]; } @end /* NGSmtpResponse */ SOPE/sope-mime/NGMail/GNUmakefile0000644000000000000000000000255015004363604015401 0ustar rootroot# GNUstep makefile include ../../config.make include $(GNUSTEP_MAKEFILES)/common.make ifneq ($(frameworks),yes) SUBPROJECT_NAME = NGMail else FRAMEWORK_NAME = NGMail endif #NGMail_PCH_FILE = common.h NGMail_HEADER_FILES_DIR = . NGMail_HEADER_FILES_INSTALL_DIR = /NGMail NGMail_HEADER_FILES = \ NGMailDecls.h \ NGMail.h \ NGMailAddressList.h \ NGMailAddressParser.h \ NGMailAddress.h \ NGMimeMessage.h \ NGMimeMessageGenerator.h\ NGMimeMessageParser.h \ NGMBoxReader.h \ NGPop3Client.h \ NGPop3Support.h \ NGSmtpClient.h \ NGSmtpSupport.h \ NGSendMail.h \ NGMail_OBJC_FILES = \ NGMail.m \ NGMailAddressList.m \ NGMailAddressParser.m \ NGMailAddress.m \ NGMimeMessage.m \ NGMimeMessageGenerator.m\ NGMimeMessageParser.m \ NGMBoxReader.m \ NGPop3Client.m \ NGPop3Support.m \ NGSmtpClient.m \ NGSmtpSupport.m \ NGSendMail.m \ \ NGMimeMessageBodyGenerator.m \ NGMimeMessageMultipartBodyGenerator.m \ NGMimeMessageRfc822BodyGenerator.m \ NGMimeMessageTextBodyGenerator.m \ \ NGMailBase64Encoding.m \ NSData+MimeQP.m \ -include GNUmakefile.preamble ifneq ($(FHS_INSTALL_ROOT),) GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include endif ifneq ($(frameworks),yes) include $(GNUSTEP_MAKEFILES)/subproject.make else include $(GNUSTEP_MAKEFILES)/framework.make endif -include GNUmakefile.postamble SOPE/sope-mime/NGMail/NGMimeMessageTextBodyGenerator.m0000644000000000000000000000217015004363604021456 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeMessageGenerator.h" #include "NGMimeMessage.h" #include "common.h" @implementation NGMimeMessageTextBodyGenerator - (NSData *)encodeData:(NSData *)_data forPart:(id)_part additionalHeaders:(NGMutableHashMap *)_addHeaders { return _base64Encoding(self, _data, _part, _addHeaders); } @end /* NGMimeMessageTextBodyGenerator */ SOPE/sope-mime/NGMail/ChangeLog0000644000000000000000000002435615004363604015111 0ustar rootroot2012-08-27 Francis Lachapelle * NGMailAddressParser.m (+sanitizeMailAddresses:): new method to properly split email addresses from a string. Fixes #1340. 2010-08-23 Wolfgang Sourdeau * NGSmtpClient.m (-quit): we must accept both "connected" and "transaction" states as the latter is a substate of the former and because SOPE so violently crashes otherwise. 2010-08-11 Ludovic Marcotte * NGSendMail.m (sendMailData:toRecipients:sender): we now correctly replace \r\n with \n everywhere in the content. 2010-04-30 Wolfgang Sourdeau * NSData+MimeQP.m (-decodeQuotedPrintableValueOfMIMEHeaderField:): we now strip invalid characters from the resulting string. 2010-04-13 Wolfgang Sourdeau * NGSmtpClient.m (-mailFrom, -recipientTo): we ensure that the provided email address is enclosed within brackets. 2008-09-01 Ludovic Marcotte * NGSmtpClient.m: improved implementation 2007-08-09 Wolfgang Sourdeau * NGSmtpClient.m: properly change connection states (fixes OGo bug #1897) 2005-12-13 Helge Hess * NGMimeMessageParser.m: moved NSData QP category to own file (NSData+MimeQP.m) 2005-07-20 Helge Hess * NGMimeMessage.m: added some convinience methods to access the header fields of a message 2005-07-12 Helge Hess * NGMimeMessage.m: copy hashmap on object creation to make it immutable 2005-04-24 Helge Hess * fixed gcc 4.0 warnings 2005-03-24 Helge Hess * NGMimeMessageGenerator.m: mark To, Cc and Bcc as multivalue header fields to fix #1324 2005-03-24 Helge Hess * NGMimeMessageGenerator.m: minor code cleanups 2005-01-30 Helge Hess * NGMimeMessageGenerator.m: fixed a format bug in an error log which could lead to a crash, moved base64 encoding function to separate file 2004-12-14 Marcus Mueller * NGMail.xcode: minor fixes and updated 2004-11-30 Helge Hess * NGSendMail.m: properly pass the command line to sendmail 2004-10-29 Helge Hess * NGSendMail.m: use fwrite() to write to pipe * NGMimeMessageGenerator.m: minor code cleanups 2004-10-27 Marcus Mueller * NGMail.xcode: added NGSendMail.h 2004-10-27 Helge Hess * NGSendMail.m: use /usr/sbin/sendmail on Cocoa Foundation (/usr/lib/sendmail on all other platforms) * NGSendMail.m: properly setup user defaults object * added new NGSendMail object (derived from mail-deliver command in OGo Logic) 2004-10-04 Marcus Mueller * NGMail.xcode: updated to the current build version 2004-09-21 Marcus Mueller * NGMail.xcode: Fixed dependencies to resemble the make process more closely. Our aim should be to stick to the make process as closely as possible, so we shouldn't introduce dependencies in non-toplevel projects. 2004-08-29 Marcus Mueller * NGMail.xcode: new Xcode project 2004-08-20 Helge Hess * fixed for SOPE 4.3 structure (v4.3.173) 2004-07-22 Helge Hess * NGMBoxReader.m: fixed a gcc 3.4 warning (v4.2.170) 2004-06-10 Helge Hess * NGMailAddressParser.m: added stronger typing for gcc 3.4 (v4.2.161) 2004-06-09 Helge Hess * NGMailAddressParser.m: major code cleanups, cache YES number, cache NSString class (v4.2.160) 2004-02-10 Helge Hess * NGMBoxReader.m, NGPop3Client.m, NGSmtpClient.m: fixed compilation warnings on OSX (v4.2.151) 2004-02-08 Helge Hess * v4.2.150 * NGMimeMessageGenerator.m: expose _base64Encoding function (should be some category?) * GNUmakefile, NGMimeMessageGenerator.m: moved body generators to separate source files Wed Jun 11 11:15:48 2003 Jan Reichmann * NGMimeMessageParser: use unicode, use named encoding to encode header fields (if default 'UseFoundationStringEncodingForMimeHeader' = YES, libFoundation string encoding will be used (v4.2.113) Wed May 14 12:58:44 2003 Jan Reichmann * NGMimeMessageParser.m: code cleanups, fix a decode quoted printable bug (sometimes last char was ignored) (v4.2.107) 2003-04-09 Helge Hess * NGMimeMessageGenerator.m, NGMimeMessageParser.m: some gcc 3.3 signed/unsigned warnings fixed (v4.2.97) * NGPop3Client.m: some gcc 3.3 signed/unsigned warnings fixed (v4.2.96) Mon Feb 17 18:21:33 2003 Jan Reichmann * NGMimeMessageParser: add NGMimeRfc822BodyParser, add delegate method bodyParserForPart: to call the NGMimeRfc822BodyParser (v4.2.86) Mon Jan 27 19:13:34 2003 * NGMimeMessageGenerator.m: code cleanups, use disk blob handling from NGMime (v4.2.73) Tue Jan 21 18:16:46 2003 * NGMimeMessageParser.m: increase version (NGMimePartParser got new instance vars) (v4.2.70) 2003-01-13 Helge Hess * NGMimeMessageParser.h: added some docu to header Mon Oct 21 16:15:58 2002 Jan Reichmann * NGMimeMessageParser.m: remove logs (v4.2.26) 2002-08-15 Helge Hess * NGMimeMessageParser.m: fixed decoding of quoted printable fields, which was completly broken after the last change by JR :-( Still to be tested ... (v4.2.21) fixes SuSE Bug 17579 * NGMimeMessageParser.m: some cleanups, changed some "char" variables to "unsigned char", do not allocate buffer on stack, but in the heap, use NSStringClass more often, moved decoding code in an NSData category to make testing easier Note: the changed from 2002-07-10 probably broke umlaut handling, SuSE Bug 17579 (added a small tool in samples which reproduces the problem) - 2002-07-23 v4.2.19 (hh) - 2002-07-17 v4.2.18 (jr) - 2002-07-17 v4.2.17 (hh) 2002-07-10 Jan Reichmann * NGMimeMessageParser.m: added optimization, got a 100% gain for listing IMAP folders - 2002-07-10 v4.2.16 (hh) [before the changes above were applied ???] - 2002-07-09 v4.2.15 (hh) [extracted from CVS] - 2002-07-09 v4.2.14 (hh) [extracted from CVS] 2002-07-09 Helge Hess * NGMimeMessageParser.m: use NGMimeType string->charset decoding, fixes a bug with uppercase charset names - 2002-07-08 v4.2.13 (hh) [extracted from CVS] - 2002-07-08 v4.2.12 (hh) [extracted from CVS] 2002-07-08 Helge Hess * NGMimeMessage.m: fixed a (non-serious) bug in +initialize (wasn't properly protected against multiple calls), some cleanup - 2002-06-13 v4.2.11 (jr) [extracted from CVS] - 2002-06-11 v4.2.10 (jr) [extracted from CVS] - 2002-06-10 v4.2.9 (jr) [extracted from CVS] - 2002-06-10 v4.2.8 (jr) [extracted from CVS] Mon Jun 10 20:22:20 2002 Jan41 Reichmann * NGMailAddressParser.m: fixed address parsing bug (delete white spaces between phrases) Thu Mar 14 15:05:53 2002 Jan41 Reichmann * NGMailAddressParser.m: fixed mail-address parsing bug Thu Nov 1 16:08:13 2001 Jan41 Reichmann * NGMimeMessageGenerator.m: fixed utf8 encoding bug Thu Oct 25 09:41:00 2001 Helge Hess * NGMimeMessageGenerator.m: fixed content-type access bug (use -contentType method to access content types) Wed Oct 24 15:04:22 2001 Jan41 Reichmann * NGMimeMessageGenerator.m: add 8 bit Headerfield encoding default Wed Oct 24 12:54:58 2001 Helge Hess * updated to SKYRiXgreen version (mail address parser, message gen) Thu Oct 11 17:32:38 2001 Helge Hess * NGMimeMessage.m: make string-header safe Thu Aug 9 13:21:22 2001 Helge Hess * NGMBoxReader.m: use -initWithPath:, no use of NGFileUrl anymore Mon Apr 2 14:09:11 2001 Jan Reichmann * NGMailAddressParser.h: add doc Wed Mar 7 16:46:43 2001 Jan Reichmann * NGMimeMessage.m: fixed body == NSString bug Mon Mar 5 16:29:40 2001 Jan Reichmann * NGMimeMessage.[hm]: if content-type is nil either text or application/octet-stream will be returned Mon Jan 29 16:22:27 2001 Jan Reichmann * NGMimeMessageParser.m: fixed encoding bug Fri Jan 26 18:53:10 2001 Jan Reichmann * NGMimeMessageGenerator.m: fixed content bug * NGMailAddressParser.m: fixed outlock mail-address parse bug Tue Jun 6 17:39:08 2000 Jan Reichmann * NGMailAddressParser.[mh]: fixed type bug (char --> unsigned char) * NGMailAddressParser.m: fixed parse bug Tue May 30 15:25:41 2000 Jan Reichmann * NGMailAddressParser.m: add parseAddressList (addresses seperated by comma) Tue Apr 25 15:29:35 2000 Jan Reichmann * NGMimeMessageGenerator.m (_base64Encoding): if the body should be encoded and the content-type isn`t exits, set application/octet-stream as content-type * NGMimeMessageGenerator.m (_base64Encoding): if no Tue Feb 29 18:27:29 2000 Helge Hess * MOF3 import Thu Sep 2 21:09:41 1999 Helge Hess * added class versions and superclass version checks Wed Aug 25 13:40:32 1999 Jan Reichmann * NGMimeMessageParser.m: L 93 fixed appendLC bug (set appendLC = NO) Thu Jul 22 14:28:12 1999 Jan Reichmann * NGMimeMessageGenerator.m (_base64Encoding): insert quoted-printable encoding for text/* Mimeparts Fri Apr 16 18:00:50 1999 Helge Hess * mbox parser rewritten for better speed Mon Apr 12 16:47:33 1999 Helge Hess * use #include instead of #import, modified headers to support #include Fri Nov 27 15:37:04 1998 Helge Hess * started WIN32 port 1998-10-09 Helge Hess * created ChangeLog SOPE/sope-mime/NGMail/common.h0000644000000000000000000000210115004363604014760 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMail_common_H__ #define __NGMail_common_H__ #include #include #include #include #include #ifndef __MINGW32__ # include #endif #endif /* __NGMail_common_H__ */ SOPE/sope-mime/NGMail/NGMBoxReader.h0000644000000000000000000000272215004363604015716 0ustar rootroot/* Copyright (C) 2000-2006 SKYRIX Software AG Copyright (C) 2006 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMail_NGMBoxReader_H__ #define __NGMail_NGMBoxReader_H__ #import #import #import @class NSString, NSDictionary; @interface NGMBoxReader : NSEnumerator { @protected id source; NSString *lastDate; NSString *separator; BOOL isEndOfStream; int (*readByte)(id, SEL); } + (id)readerForMBox:(NSString *)_path; + (id)mboxWithSource:(id)_source; - (id)initWithSource:(id)_source; - (id)nextMessage; // same as -nextObject @end #endif /* __NGMail_NGMBoxReader_H__ */ SOPE/sope-mime/NGMail/NGMimeMessage.h0000644000000000000000000000375615004363604016132 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMail_NGMimeMessage_H__ #define __NGMail_NGMimeMessage_H__ #import #include @class NGMutatbleHashMap; /* NGMimeMessage represents a RFC822 message with MIME extensions. */ @class NSString, NSArray, NSDictionary, NSEnumerator; @class NGMutableHashMap; @class NGHashMap; @class NGMimeType; @interface NGMimeMessage : NSObject < NGMimePart > { @protected NGMutableHashMap *header; id body; NGMimeType *mimeType; } + (id)messageWithHeader:(NGHashMap *)_headers; - (id)initWithHeader:(NGHashMap *)_headers; // designated initializer /* NGPart */ - (NSEnumerator *)valuesOfHeaderFieldWithName:(NSString *)_name; - (NSEnumerator *)headerFieldNames; - (void)setBody:(id)_body; - (id)body; /* NGMimePart */ - (NGMimeType *)contentType; - (NSString *)contentId; - (NSArray *)contentLanguage; - (NSString *)contentMd5; - (NSString *)encoding; - (NSString *)contentDescription; /* convenience */ - (NSString *)headerForKey:(NSString *)_key; - (NSArray *)headersForKey:(NSString *)_key; - (NSArray *)headerKeys; - (NSDictionary *)headers; - (NSString *)headersAsString; - (void) setHeader: (id) _header forKey: (NSString *)_key; @end #endif /* __NGMail_NGMimeMessage_H__ */ SOPE/sope-mime/NGMail/NGSmtpClient.m0000644000000000000000000006020415004363604016014 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2020 Nicolas Höft This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "NGSmtpClient.h" #include "NGSmtpSupport.h" #include "NGSmtpReplyCodes.h" #include "common.h" // // Useful extension that comes from Pantomime which is also // released under the LGPL. // @interface NSMutableData (DataCleanupExtension) - (NSRange) rangeOfCString: (const char *) theCString; - (NSRange) rangeOfCString: (const char *) theCString options: (unsigned int) theOptions range: (NSRange) theRange; @end @implementation NSMutableData (DataCleanupExtension) - (NSRange) rangeOfCString: (const char *) theCString { return [self rangeOfCString: theCString options: 0 range: NSMakeRange(0,[self length])]; } -(NSRange) rangeOfCString: (const char *) theCString options: (unsigned int) theOptions range: (NSRange) theRange { const char *b, *bytes; int i, len, slen; if (!theCString) { return NSMakeRange(NSNotFound,0); } bytes = [self bytes]; len = [self length]; slen = strlen(theCString); b = bytes; if (len > theRange.location + theRange.length) { len = theRange.location + theRange.length; } if (theOptions == NSCaseInsensitiveSearch) { i = theRange.location; b += i; for (; i <= len-slen; i++, b++) { if (!strncasecmp(theCString,b,slen)) { return NSMakeRange(i,slen); } } } else { i = theRange.location; b += i; for (; i <= len-slen; i++, b++) { if (!memcmp(theCString,b,slen)) { return NSMakeRange(i,slen); } } } return NSMakeRange(NSNotFound,0); } @end @interface NGSmtpClient(PrivateMethods) - (void) _fetchExtensionInfo; - (id) _openSocket; - (BOOL) _startTLS; @end @implementation NGSmtpClient - (BOOL)useSSL { return self->useSSL; } - (BOOL)useStartTLS { return self->useStartTLS; } + (id) clientWithURL: (NSURL *)_url; { return [[(NGSmtpClient *)[self alloc] initWithURL:_url] autorelease]; } - (id)init { NSLog(@"%@: init not supported, use initWithSocket: ..", self); [self release]; return nil; } - (id)initWithSocket:(id)_socket { // designated initializer if ((self = [super init])) { BOOL debug; self->socket = [_socket retain]; NSAssert(self->socket, @"invalid socket parameter"); debug = [[NSUserDefaults standardUserDefaults] boolForKey:@"SMTPDebugEnabled"]; [self setDebuggingEnabled: debug]; self->connection = [(NGBufferedStream *)[NGBufferedStream alloc] initWithSource:_socket]; self->text = [(NGCTextStream *)[NGCTextStream alloc] initWithSource:self->connection]; self->state = [self->socket isConnected] ? NGSmtpState_connected : NGSmtpState_unconnected; } return self; } - (id)initWithURL:(NSURL *)_url { NGInternetSocketAddress *a; int port; NSDictionary *queryComponents = [_url queryComponents]; NSString *value; self->useSSL = [[_url scheme] isEqualToString:@"smtps"]; if (self->useSSL && NSClassFromString(@"NGActiveSSLSocket") == nil) { [self logWithFormat: @"no SSL support available, cannot connect: %@", _url]; [self release]; return nil; } value = [queryComponents valueForKey: @"tls"]; if (value && [value isEqualToString: @"YES"]) self->useStartTLS = YES; else self->useStartTLS = NO; if ((port = [[_url port] intValue]) == 0) { if (self->useSSL && !self->useStartTLS) port = 465; else port = 25; } tlsVerifyMode = TLSVerifyDefault; value = [queryComponents valueForKey: @"tlsVerifyMode"]; if (value) { if ([value isEqualToString: @"allowInsecureLocalhost"]) { tlsVerifyMode = TLSVerifyAllowInsecureLocalhost; } else if ([value isEqualToString: @"none"]) { tlsVerifyMode = TLSVerifyNone; } } a = [NGInternetSocketAddress addressWithPort:port onHost:[_url host]]; self = [self initWithAddress:a]; return self; } - (id)initWithAddress:(id)_address { /* designated init */ if ((self = [super init])) { BOOL debug; [self gotoState:NGSmtpState_unconnected]; self->address = [_address retain]; debug = [[NSUserDefaults standardUserDefaults] boolForKey:@"SMTPDebugEnabled"]; [self setDebuggingEnabled: debug]; } return self; } - (void)dealloc { [self->text release]; [self->connection release]; [self->socket release]; [self->previous_socket release]; [super dealloc]; } // accessors - (id)socket { return self->socket; } - (NGSmtpState)state { return self->state; } - (void)setDebuggingEnabled:(BOOL)_flag { self->isDebuggingEnabled = _flag; } - (BOOL)isDebuggingEnabled { return self->isDebuggingEnabled; } // connection - (id)_openSocket { id sock; BOOL sslSocket = [self useSSL] && ![self useStartTLS]; NS_DURING { if (sslSocket) { sock = [NGActiveSSLSocket socketConnectedToAddress:self->address withVerifyMode: tlsVerifyMode]; } else { sock = [NGActiveSocket socketConnectedToAddress:self->address]; } } NS_HANDLER { sock = nil; } NS_ENDHANDLER; return sock; } - (BOOL)connect { NGSmtpResponse *greeting = nil; [self requireState:NGSmtpState_unconnected]; if (self->isDebuggingEnabled) [NGTextErr writeFormat:@"C: connect to %@\n", self->address]; if ((self->socket = [[self _openSocket] retain]) == nil) return NO; self->connection = [(NGBufferedStream *)[NGBufferedStream alloc] initWithSource:self->socket]; self->text = [(NGCTextStream *)[NGCTextStream alloc] initWithSource:self->connection]; self->state = [self->socket isConnected] ? NGSmtpState_connected : NGSmtpState_unconnected; // receive greetings from server greeting = [self receiveReply]; if (self->isDebuggingEnabled) [NGTextErr writeFormat:@"S: %@\n", greeting]; if ([greeting isPositive]) { [self gotoState:NGSmtpState_connected]; [self _fetchExtensionInfo]; if (self->isDebuggingEnabled) { if (self->extensions.hasPipelining) [NGTextErr writeFormat:@"S: pipelining extension supported.\n"]; if (self->extensions.hasSize) [NGTextErr writeFormat:@"S: size extension supported.\n"]; if (self->extensions.hasHelp) [NGTextErr writeFormat:@"S: help extension supported.\n"]; if (self->extensions.hasExpand) [NGTextErr writeFormat:@"S: expand extension supported.\n"]; if (self->extensions.hasAuthPlain) [NGTextErr writeFormat:@"S: plain auth extension supported.\n"]; if (self->extensions.hasStartTls) [NGTextErr writeFormat:@"S: starttls extension supported.\n"]; } if ([self useStartTLS]) { if (!self->extensions.hasStartTls) { [NSException raise:@"SMTPException" format:@"Server does not support STARTTLS"]; return NO; } if ([self _startTLS]) { // after performing STARTTLS, we have to fetch the supported // extensions again, supported AUTH mechanism may now // have changed [self _fetchExtensionInfo]; return YES; } [self disconnect]; return NO; } return YES; } else { [self disconnect]; return NO; } } - (BOOL) _startTLS { Class socketClass; NGSmtpResponse *reply; id tlsSocket; if (!self->extensions.hasStartTls) { NSLog(@"SMTP: TLS not supported by client"); return NO; } socketClass = NSClassFromString(@"NGActiveSSLSocket"); if (!socketClass) { NSLog(@"SMTP: TLS not supported by client"); return NO; } reply = [self sendCommand: @"STARTTLS"]; if ([reply code] != NGSmtpServiceReady) { NSLog(@"SMTP: unexpected response from STARTTLS command (%d)", [reply code]); return NO; } tlsSocket = [[NGActiveSSLSocket alloc] initWithConnectedActiveSocket: (NGActiveSocket *)self->socket withVerifyMode: tlsVerifyMode]; if (![tlsSocket startTLS]) { NSLog(@"SMTP: unable to perform STARTTLS on socket"); return NO; } // the TLS socket is on top of the connection we // opened before, so we have to keep it self->previous_socket = self->socket; self->socket = tlsSocket; // redirect the connection and text objects // to the new socket [self->text release]; [self->connection release]; self->connection = [(NGBufferedStream *)[NGBufferedStream alloc] initWithSource: self->socket]; self->text = [(NGCTextStream *)[NGCTextStream alloc] initWithSource: self->connection]; NSLog(@"SMTP: STARTTLS successfully performed"); return YES; } - (void)disconnect { [text flush]; [previous_socket close]; [socket close]; [self gotoState:NGSmtpState_unconnected]; } // authentication - (BOOL) authenticateUser: (NSString *) username withPassword: (NSString *) password withMethod: (NSString *) method { BOOL rc; if (self->extensions.hasAuthPlain && [username length] > 0) { char *buffer; const char *utf8Username, *utf8Password; size_t buflen, lenUsername, lenPassword; NSString *authString; NGSmtpResponse *reply; if(!method) method = @"PLAIN"; if([method isEqualToString: @"xoauth2"]) { NSString *oauth2Password, *oauth2Username; oauth2Username = [NSString stringWithFormat: @"user=%@", username]; oauth2Password = [NSString stringWithFormat: @"auth=Bearer %@", password]; utf8Username = [oauth2Username UTF8String]; utf8Password = [oauth2Password UTF8String]; lenUsername = strlen(utf8Username); lenPassword = strlen(utf8Password); buflen = lenUsername + lenPassword + 3; buffer = malloc (sizeof (char) * (buflen + 1)); sprintf (buffer, "%s%c%s%c%c", utf8Username, 1, utf8Password, 1, 1); authString = [[NSData dataWithBytesNoCopy: buffer length: buflen freeWhenDone: YES] stringByEncodingBase64]; } else { utf8Username = [username UTF8String]; utf8Password = [password UTF8String]; if (!utf8Password) utf8Password = 0; lenUsername = strlen (utf8Username); lenPassword = strlen (utf8Password); buflen = lenUsername * 2 + lenPassword + 2; buffer = malloc (sizeof (char) * (buflen + 1)); sprintf (buffer, "%s%c%s%c%s", utf8Username, 0, utf8Username, 0, utf8Password); authString = [[NSData dataWithBytesNoCopy: buffer length: buflen freeWhenDone: YES] stringByEncodingBase64]; } authString = [authString stringByReplacingOccurrencesOfString:@"\n" withString:@""]; reply = [self sendCommand: [NSString stringWithFormat:@"AUTH %@", method]]; if ([reply code] == NGSmtpServerChallenge) { reply = [self sendCommand: authString]; } rc = ([reply code] == NGSmtpAuthenticationSuccess); } else { rc = NO; } return rc; } // state - (void)requireState:(NGSmtpState)_state { if (_state != [self state]) { [NSException raise:@"SMTPException" format:@"require state %i, now in %i", _state, [self state]]; } } - (void)denyState:(NGSmtpState)_state { if ([self state] == _state) { [NSException raise:@"SMTPException" format:@"not allowed in state %i", [self state]]; } } - (void)gotoState:(NGSmtpState)_state { self->state = _state; } - (BOOL)isTransactionInProgress { return (self->state == NGSmtpState_TRANSACTION); } - (void)abortTransaction { [self gotoState:NGSmtpState_connected]; } // replies - (NGSmtpResponse *)receiveReply { NSMutableString *desc = nil; NSString *line = nil; NGSmtpReplyCode code = -1; line = [self->text readLineAsString]; if ([line length] < 4) { NSLog(@"SMTP: reply has invalid format (%@)", line); return nil; } code = [[line substringToIndex:3] intValue]; //if (self->isDebuggingEnabled) // [NGTextErr writeFormat:@"S: reply with code %i follows ..\n", code]; desc = [NSMutableString stringWithCapacity:[line length]]; while ([line characterAtIndex:3] == '-') { if ([line length] < 4) { NSLog(@"SMTP: reply has invalid format (text=%@, line=%@)", desc, line); break; } [desc appendString:[line substringFromIndex:4]]; [desc appendString:@"\n"]; line = [self->text readLineAsString]; } if ([line length] >= 4) [desc appendString:[line substringFromIndex:4]]; return [NGSmtpResponse responseWithCode:code text:desc]; } // commands - (NGSmtpResponse *)sendCommand:(NSString *)_command { if (self->isDebuggingEnabled) { [NGTextOut writeFormat:@"C: %@\n", _command]; [NGTextOut flush]; } [text writeString:_command]; [text writeString:@"\r\n"]; [text flush]; return [self receiveReply]; } - (NGSmtpResponse *)sendCommand:(NSString *)_command argument:(NSString *)_argument { if (self->isDebuggingEnabled) { [NGTextOut writeFormat:@"C: %@ %@\n", _command, _argument]; [NGTextOut flush]; } [text writeString:_command]; [text writeString:@" "]; [text writeString:_argument]; [text writeString:@"\r\n"]; [text flush]; return [self receiveReply]; } // service commands - (void)_fetchExtensionInfo { NGSmtpResponse *reply = nil; NSString *hostName = nil; NGActiveSocket* sock; NGInternetSocketAddress* sockAddr; if (previous_socket) { sock = self->previous_socket; } else { sock = self->socket; } sockAddr = (NGInternetSocketAddress *)[sock localAddress]; if ([sockAddr isIPv6] && [[sockAddr hostName] isEqualToString: [sockAddr address]]) { hostName = [NSString stringWithFormat:@"[IPv6:%@]", [sockAddr address]]; } else { hostName = [sockAddr hostName]; } reply = [self sendCommand:@"EHLO" argument:hostName]; if ([reply code] == NGSmtpActionCompleted) { NSEnumerator *lines = [[[reply text] componentsSeparatedByString:@"\n"] objectEnumerator]; NSString *line = nil; if (self->isDebuggingEnabled) [NGTextErr writeFormat:@"S: %@\n", reply]; while ((line = [lines nextObject])) { if ([line hasPrefix:@"EXPN"]) self->extensions.hasExpand = YES; else if ([line hasPrefix:@"SIZE"]) self->extensions.hasSize = YES; else if ([line hasPrefix:@"PIPELINING"]) self->extensions.hasPipelining = YES; else if ([line hasPrefix:@"HELP"]) self->extensions.hasHelp = YES; else if (([line hasPrefix:@"STARTTLS"])) self->extensions.hasStartTls = YES; // We skip "AUTH=PLAIN ..." here, as it's redundant with "AUTH PLAIN ..." and will // break things on components splitting else if ([line hasPrefix:@"AUTH "]) { NSArray *methods; methods = [line componentsSeparatedByString: @" "]; self->extensions.hasAuthPlain = [methods containsObject: @"PLAIN"]; } } lines = nil; } else { if (self->isDebuggingEnabled) { [NGTextErr writeFormat:@"S: %@\n", reply]; [NGTextErr writeFormat:@" .. could not get extension info.\n"]; } } } - (BOOL)_simpleServiceCommand:(NSString *)_command expectCode:(NGSmtpReplyCode)_code { NGSmtpResponse *reply = nil; [self denyState:NGSmtpState_unconnected]; reply = [self sendCommand:_command]; if (self->isDebuggingEnabled) [NGTextErr writeFormat:@"S: %@\n", reply]; if ([reply isPositive]) { if ([reply code] != _code) NSLog(@"SMTP(%@): expected reply code %i, got code %i ..", _command, _code, [reply code]); return YES; } return NO; } - (BOOL)quit { NGSmtpResponse *reply = nil; [self denyState:NGSmtpState_unconnected]; reply = [self sendCommand:@"QUIT"]; if (self->isDebuggingEnabled) [NGTextErr writeFormat:@"S: %@\n", reply]; if ([reply isPositive]) { unsigned int waitBytes = 0; if ([reply code] == NGSmtpServiceClosingChannel) { // wait for connection close .. while ([self->connection readByte] != -1) waitBytes++; } else NSLog(@"SMTP(QUIT): unexpected reply code (%i), disconnecting ..", [reply code]); return YES; } return NO; } - (BOOL)helloWithHostname:(NSString *)_host { NGSmtpResponse *reply = nil; [self denyState:NGSmtpState_unconnected]; reply = [self sendCommand:@"HELO" argument:_host]; if (self->isDebuggingEnabled) [NGTextErr writeFormat:@"S: %@\n", reply]; if ([reply isPositive]) { if ([reply code] != NGSmtpActionCompleted) { NSLog(@"SMTP(HELO): expected reply code %i, got code %i ..", NGSmtpActionCompleted, [reply code]); } return YES; } return NO; } - (BOOL)hello { NSString *hostName = nil; hostName = [(NGInternetSocketAddress *)[self->socket localAddress] hostName]; return [self helloWithHostname:hostName]; } - (BOOL)noop { return [self _simpleServiceCommand:@"NOOP" expectCode:NGSmtpActionCompleted]; } - (BOOL)reset { if ([self _simpleServiceCommand:@"RSET" expectCode:NGSmtpActionCompleted]) { if ([self isTransactionInProgress]) [self abortTransaction]; return YES; } else return NO; } - (NSString *)help { NGSmtpResponse *reply = nil; [self denyState:NGSmtpState_unconnected]; reply = [self sendCommand:@"HELP"]; if (self->isDebuggingEnabled) [NGTextErr writeFormat:@"S: %@\n", reply]; if ([reply isPositive]) { if ([reply code] != NGSmtpHelpMessage) { NSLog(@"SMTP(HELP): expected reply code %i, got code %i ..", NGSmtpHelpMessage, [reply code]); } return [reply text]; } return nil; } - (NSString *)helpForTopic:(NSString *)_topic { NGSmtpResponse *reply = nil; [self denyState:NGSmtpState_unconnected]; reply = [self sendCommand:@"HELP" argument:_topic]; if (self->isDebuggingEnabled) [NGTextErr writeFormat:@"S: %@\n", reply]; if ([reply isPositive]) { if ([reply code] != NGSmtpHelpMessage) { NSLog(@"SMTP(HELP): expected reply code %i, got code %i ..", NGSmtpHelpMessage, [reply code]); } return [reply text]; } return nil; } - (BOOL)verifyAddress:(id)_address { NGSmtpResponse *reply = nil; [self denyState:NGSmtpState_unconnected]; reply = [self sendCommand:@"VRFY" argument:[_address stringValue]]; if (self->isDebuggingEnabled) [NGTextErr writeFormat:@"S: %@\n", reply]; if ([reply isPositive]) { if ([reply code] != NGSmtpActionCompleted) { NSLog(@"SMTP(VRFY): expected reply code %i, got code %i ..", NGSmtpActionCompleted, [reply code]); } return YES; } else if ([reply code] == NGSmtpMailboxNotFound) { return NO; } else { NSLog(@"SMTP(VRFY): expected positive or 550 reply code, got code %i ..", [reply code]); return NO; } } // transaction commands - (NSString *) _sanitizeAddress: (NSString *) _address { NSString *saneAddress; if ([_address hasPrefix: @"<"]) saneAddress = _address; else saneAddress = [NSString stringWithFormat: @"<%@>", _address]; return saneAddress; } - (BOOL)mailFrom:(id)_sender { NGSmtpResponse *reply; NSString *sender; [self requireState:NGSmtpState_connected]; sender = [self _sanitizeAddress: [_sender stringValue]]; reply = [self sendCommand: @"MAIL" argument: [@"FROM:" stringByAppendingString: sender]]; if ([reply isPositive]) { if ([reply code] != NGSmtpActionCompleted) { NSLog(@"SMTP(MAIL FROM): expected reply code %i, got code %i ..", NGSmtpActionCompleted, [reply code]); } [self gotoState:NGSmtpState_TRANSACTION]; return YES; } else if ([[reply text] length]) { NSLog(@"SMTP(MAIL FROM) error: %@", [reply text]); [NSException raise: @"SMTPException" format: @"%@", [reply text]]; } return NO; } - (BOOL)recipientTo:(id)_receiver { NGSmtpResponse *reply = nil; NSString *rcpt = nil; [self requireState:NGSmtpState_TRANSACTION]; rcpt = [self _sanitizeAddress: [_receiver stringValue]]; reply = [self sendCommand: @"RCPT" argument: [@"TO:" stringByAppendingString: rcpt]]; if ([reply isPositive]) { if ([reply code] != NGSmtpActionCompleted) { NSLog(@"SMTP(RCPT TO): expected reply code %i, got code %i ..", NGSmtpActionCompleted, [reply code]); } return YES; } else if ([[reply text] length]) { NSString* smtpError = [reply text]; NSLog(@"SMTP(RCPT TO) error: %@", smtpError); if(![smtpError containsString:rcpt]) { smtpError = [NSString stringWithFormat: @"%@ - %@", smtpError, rcpt]; } [NSException raise: @"SMTPException" format: @"%@", smtpError]; } return NO; } - (BOOL)sendData:(NSData *)_data { NGSmtpResponse *reply = nil; NSMutableData *cleaned_data; NSRange r1; const char *bytes; char *mbytes; int len, mlen; [self requireState:NGSmtpState_TRANSACTION]; reply = [self sendCommand:@"DATA"]; if (self->isDebuggingEnabled) [NGTextErr writeFormat:@"S: %@\n", reply]; if (([reply code] >= 300) && ([reply code] < 400)) { if ([reply code] != NGSmtpStartMailInput) { NSLog(@"SMTP(DATA): expected reply code %i, got code %i ..", NGSmtpStartMailInput, [reply code]); } [self->text flush]; // // SOPE sucks in many ways and that is one of them. The headers are actually // correctly encoded (trailing \r\n is inserted) but not the base64 encoded // data since it uses SOPE's dataByEncodingBase64 function which says: // // NGBase64Coding.h:- (NSData *)dataByEncodingBase64; /* Note: inserts '\n' every 72 chars */ // len = [_data length]; mlen = 0; cleaned_data = [NSMutableData dataWithLength: len*2]; bytes = [_data bytes]; mbytes = [cleaned_data mutableBytes]; while (len > 0) { if (*bytes == '\n' && *(bytes-1) != '\r' && mlen > 0) { *mbytes = '\r'; mbytes++; mlen++; } *mbytes = *bytes; mbytes++; bytes++; len--; mlen++; } [cleaned_data setLength: mlen]; // // According to RFC 2821 section 4.5.2, we must check for the character // sequence "."; any occurrence have its period duplicated // to avoid data transparency. // r1 = [cleaned_data rangeOfCString: "\r\n."]; while (r1.location != NSNotFound) { [cleaned_data replaceBytesInRange: r1 withBytes: "\r\n.." length: 4]; r1 = [cleaned_data rangeOfCString: "\r\n." options: 0 range: NSMakeRange(NSMaxRange(r1)+1, [cleaned_data length]-NSMaxRange(r1)-1)]; } if (self->isDebuggingEnabled) [NGTextErr writeFormat:@"C: data(%i bytes) ..\n", [cleaned_data length]]; [self->connection safeWriteBytes:[cleaned_data bytes] count:[cleaned_data length]]; [self->connection safeWriteBytes:"\r\n.\r\n" count:5]; [self->connection flush]; reply = [self receiveReply]; if (self->isDebuggingEnabled) [NGTextErr writeFormat:@"S: %@\n", reply]; if ([reply isPositive]) { [self gotoState:NGSmtpState_connected]; return YES; } else { NSLog(@"SMTP(DATA): mail input failed, got code %i ..", [reply code]); } } if ([[reply text] length]) { NSLog(@"SMTP(DATA) error: %@", [reply text]); [NSException raise: @"SMTPException" format: @"%@", [reply text]]; } return NO; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"", self, [self socket]]; } @end /* NGSmtpClient */ SOPE/sope-mime/NGMail/NGSmtpClient.h0000644000000000000000000000563315004363604016014 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMail_NGSmtpClient_H__ #define __NGMail_NGSmtpClient_H__ #import #import #import @class NSString; @class NGSmtpResponse; /* RFC 821 - SMTP This class implements the Simple Mail Transfer Protocol as specified in RFC821. */ typedef enum { NGSmtpState_unconnected = 1, NGSmtpState_connected, NGSmtpState_TRANSACTION } NGSmtpState; @interface NGSmtpClient : NSObject { @protected id socket; id previous_socket; NGBufferedStream *connection; id text; id address; NGSmtpState state; BOOL isDebuggingEnabled; struct { BOOL hasExpand:1; BOOL hasSize:1; BOOL hasHelp:1; BOOL hasPipelining; BOOL hasAuthPlain; BOOL hasStartTls; } extensions; BOOL useStartTLS; BOOL useSSL; int tlsVerifyMode; } + (id)clientWithURL:(NSURL *)_url; - (id)initWithURL:(NSURL *)_url; - (id)initWithAddress:(id)_address; // accessors - (id)socket; - (NGSmtpState)state; - (void)setDebuggingEnabled:(BOOL)_flag; - (BOOL)isDebuggingEnabled; // connection - (BOOL)connect; - (void)disconnect; - (BOOL)useSSL; - (BOOL)useStartTLS; // authentication - (BOOL) authenticateUser: (NSString *) username withPassword: (NSString *) password withMethod: (NSString *) method; // state - (void)requireState:(NGSmtpState)_state; - (void)denyState:(NGSmtpState)_state; - (void)gotoState:(NGSmtpState)_state; // replies - (NGSmtpResponse *)receiveReply; // commands - (NGSmtpResponse *)sendCommand:(NSString *)_command; - (NGSmtpResponse *)sendCommand:(NSString *)_command argument:(NSString *)arg; // service commands - (BOOL)quit; - (BOOL)helloWithHostname:(NSString *)_host; - (BOOL)hello; - (BOOL)noop; - (BOOL)reset; - (NSString *)help; - (NSString *)helpForTopic:(NSString *)_topic; - (BOOL)verifyAddress:(id)_address; // transaction commands - (BOOL)mailFrom:(id)_sender; - (BOOL)recipientTo:(id)_receiver; - (BOOL)sendData:(NSData *)_data; @end #endif /* __NGMail_NGSmtpClient_H__ */ SOPE/sope-mime/NGMail/COPYING0000644000000000000000000006130315004363604014363 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-mime/NGMail/README0000644000000000000000000000031015004363604014177 0ustar rootrootNGMail ====== Class-Hierachy NSObject NGMBoxReader NGPop3Client NGPop3MessageInfo NGSmtpClient NGSmtpResponse NSException NGPop3Exception NGPop3StateException SOPE/sope-mime/NGMail/NGPop3Client.h0000644000000000000000000000552015004363604015705 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMail_NGPop3Client_H__ #define __NGMail_NGPop3Client_H__ #import #include #include @class NSString, NSData; @class NGBufferedStream; @class NGMimeMessage; typedef enum { NGPop3State_unconnected = 1, NGPop3State_AUTHORIZATION, NGPop3State_TRANSACTION, NGPop3State_UPDATE } NGPop3State; @class NGPop3Response, NGPop3MessageInfo; @interface NGPop3Client : NSObject { @protected id socket; NGBufferedStream *connection; id text; NGPop3State state; NGPop3Response *lastResponse; BOOL isDebuggingEnabled; } + (id)pop3Client; - (id)initWithSocket:(id)_socket; // designated initializer /* accessors */ - (id)socket; - (NGPop3State)state; - (NGPop3Response *)lastResponse; - (void)setDebuggingEnabled:(BOOL)_flag; - (BOOL)isDebuggingEnabled; /* connection */ - (BOOL)connectToHost:(id)_host; - (BOOL)connectToAddress:(id)_address; - (void)disconnect; /* state */ - (void)requireState:(NGPop3State)_state; - (void)gotoState:(NGPop3State)_state; /* commands */ - (NGPop3Response *)sendCommand:(NSString *)_command; - (NGPop3Response *)sendCommand:(NSString *)_command argument:(NSString *)arg; - (NGPop3Response *)sendCommand:(NSString *)_command intArgument:(int)_arg; /* service commands */ - (BOOL)login:(NSString *)_user password:(NSString *)_passwd; - (BOOL)quit; - (BOOL)statMailDropCount:(int *)_count size:(int *)_size; - (NGPop3MessageInfo *)listMessage:(int)_messageNumber; - (NSEnumerator *)listMessages; - (NSData *)retrieveMessage:(int)_msgNumber; - (BOOL)deleteMessage:(int)_msgNumber; - (BOOL)noop; - (BOOL)reset; /* optional service commands */ - (NSData *)retrieveMessage:(int)_msgNumber bodyLineCount:(int)_numberOfLines; - (NSDictionary *)uniqueIdMappings; - (NSString *)uniqueIdOfMessage:(int)_msgNumber; /* MIME support */ - (NSEnumerator *)messageEnumerator; - (NGMimeMessage *)messageWithNumber:(int)_messageNumber; @end #endif /* __NGMail_NGPop3Client_H__ */ SOPE/sope-mime/NGMail/NGMailAddressList.h0000644000000000000000000000275115004363604016754 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMail_NGMailAddressList_H__ #define __NGMail_NGMailAddressList_H__ #import @class NSMutableSet, NSSet, NSString, NSEnumerator; @class NGMailAddress; @interface NGMailAddressList : NSObject < NSCoding, NSCopying > { @protected NSMutableSet *addresses; NSString *groupName; } + (id)mailAddressListWithAddresses:(NSSet *)_addresses groupName:(NSString *)_groupName; - (id)init; - (id)initWithAddresses:(NSSet *)_addresses groupName:(NSString *)_groupName; // addresses - (void)addAddress:(NGMailAddress *)_address; // accessors - (NSEnumerator *)addresses; - (void)setGroupName:(NSString *)_name; - (NSString *)groupName; @end #endif /* __NGMail_NGMailAddressList_H__ */ SOPE/sope-mime/NGMail/NGMimeMessageMultipartBodyGenerator.m0000644000000000000000000000230415004363604022512 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeMessageGenerator.h" #include "NGMimeMessage.h" #include "common.h" @implementation NGMimeMessageMultipartBodyGenerator - (id)multipartBodyGenerator:(NGMimeBodyGenerator *)_gen generatorForPart:(id)_part { id gen; gen = [[[NGMimeMessageGenerator alloc] init] autorelease]; [gen setUseMimeData:self->useMimeData]; return gen; } @end /* NGMimeMessageMultipartBodyGenerator */ SOPE/sope-mime/NGMail/NGMail.h0000644000000000000000000000253515004363604014612 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMail_H__ #define __NGMail_H__ #import #include #include #include #include #include #include #include #include #include // kit class @interface NGMail : NSObject @end #define LINK_NGMail \ static void __link_NGMail(void) { \ [NGMail self]; \ __link_NGMail(); \ } #endif /* __NGMail_H__ */ SOPE/sope-mime/NGMail/NGSendMail.h0000644000000000000000000000334615004363604015425 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMail_NGSendMail_H__ #define __NGMail_NGSendMail_H__ #import #include /* NGSendMail An interface to the local sendmail binary for deliverying mail. */ @class NSString, NSArray, NSData, NSException; @interface NGSendMail : NSObject { NSString *executablePath; BOOL isLoggingEnabled; BOOL shouldOnlyUseMailboxName; } + (id)sharedSendMail; - (id)initWithExecutablePath:(NSString *)_path; /* accessors */ - (NSString *)executablePath; - (BOOL)isSendLoggingEnabled; - (BOOL)shouldOnlyUseMailboxName; /* operations */ - (BOOL)isSendMailAvailable; - (NSException *)sendMailAtPath:(NSString *)_path toRecipients:(NSArray *)_to sender:(NSString *)_sender; - (NSException *)sendMimePart:(id)_pt toRecipients:(NSArray *)_to sender:(NSString *)_sender; - (NSException *)sendMailData:(NSData *)_data toRecipients:(NSArray *)_to sender:(NSString *)_sender; @end #endif /* __NGMail_NGSendMail_H__ */ SOPE/sope-mime/NGMail/NGMailAddressList.m0000644000000000000000000000620415004363604016756 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMailAddressList.h" #include "common.h" @implementation NGMailAddressList + (id)mailAddressListWithAddresses:(NSSet *)_addresses groupName:(NSString *)_groupName { return [[[NGMailAddressList alloc] initWithAddresses:_addresses groupName:_groupName] autorelease]; } - (id)init { if ((self = [super init])) { self->addresses = [[NSMutableSet alloc] init]; } return self; } - (id)initWithAddresses:(NSSet *)_addresses groupName:(NSString *)_groupName { if ((self = [self init])) { if (_addresses) [self->addresses unionSet:_addresses]; self->groupName = [_groupName copy];; } return self; } - (void)dealloc { [self->addresses release]; [self->groupName release]; [super dealloc]; } - (void)addAddress:(NGMailAddress *)_address { [self->addresses addObject:_address]; } /* equality */ - (BOOL)isEqual:(id)_anObject { if ([_anObject isKindOfClass:[NGMailAddressList class]]) { BOOL result = NO; NSSet *set = nil; if (![self->groupName isEqualToString:[_anObject groupName]]) return NO; set = [[NSSet alloc] initWithObjectsFromEnumerator: [(NGMailAddressList *)_anObject addresses]]; result = [self->addresses isEqualToSet:set]; [set release]; set = nil; return result; } return NO; } /* NSCoding */ - (void)encodeWithCoder:(NSCoder *)_encoder { [_encoder encodeObject:self->addresses]; [_encoder encodeObject:self->groupName]; } - (id)initWithCoder:(NSCoder *)_decoder { id _addresses, _groupName; _addresses = [_decoder decodeObject]; _groupName = [_decoder decodeObject]; return [self initWithAddresses:_addresses groupName:_groupName]; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { return [[NGMailAddressList allocWithZone:_zone] initWithAddresses:self->addresses groupName:self->groupName]; } /* accessors */ - (NSEnumerator *)addresses { return [self->addresses objectEnumerator]; } - (void)setGroupName:(NSString *)_name { ASSIGN(self->groupName, _name); } - (NSString *)groupName { return self->groupName; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"GroupName: %s \n %@\n", [self->groupName cString], self->addresses]; } @end /* NGMailAddressList */ SOPE/sope-mime/NGMail/NGSmtpSupport.h0000644000000000000000000000270715004363604016251 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMail_NGSmtpSupport_H__ #define __NGMail_NGSmtpSupport_H__ #import #include @class NSString; NSString *NGSmtpDescriptionForReplyCode(NGSmtpReplyCode _code); @interface NGSmtpResponse : NSObject { @protected NGSmtpReplyCode code; NSString *text; } + (id)responseWithCode:(NGSmtpReplyCode)_code text:(NSString *)_text; // accessors - (NGSmtpReplyCode)code; - (NSString *)text; // special accessors - (NSString *)lastLine; - (BOOL)isPositive; // <400 code groups - (BOOL)isTransientNegative; // 400 code group - (BOOL)isPermanentNegative; // 500 code group @end #endif /* __NGMail_NGSmtpSupport_H__ */ SOPE/sope-mime/NGMail/NGMimeMessageParser.m0000644000000000000000000000676115004363604017313 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeMessageParser.h" #include "NGMimeMessage.h" #include "common.h" #include @interface NGMimeMessageParserDelegate : NSObject @end @implementation NGMimeMessageParserDelegate static Class NGMimeMessageParserClass = Nil; + (void)initialize { if (NGMimeMessageParserClass == Nil) NGMimeMessageParserClass = [NGMimeMessageParser class]; } - (id)parser:(NGMimePartParser *)_p parseHeaderField:(NSString *)_field data:(NSData *)_data { NGMimeMessageParser *parser = nil; id v; if ([_p isKindOfClass:NGMimeMessageParserClass]) return nil; parser = [[NGMimeMessageParserClass alloc] init]; v = [parser valueOfHeaderField:_field data:_data]; [parser release]; parser = nil; return v; } - (id)parser:(NGMimePartParser *)_parser bodyParserForPart:(id)_part { id ctype; NGMimeType *contentType; ctype = [_part contentType]; contentType = ([ctype isKindOfClass:[NGMimeType class]]) ? ctype : [NGMimeType mimeType:[ctype stringValue]]; if ([[contentType type] isEqualToString:@"message"] && [[contentType subType] isEqualToString:@"rfc822"]) { return [[[NGMimeRfc822BodyParser alloc] init] autorelease]; } return nil; } @end /* NGMimeMessageParserDelegate */ @implementation NGMimeMessageParser static Class NSStringClass = Nil; + (void)initialize { if (NSStringClass == Nil) NSStringClass = [NSString class]; } - (id)init { NGMimeMessageParserDelegate *localDelegate; if ((self = [super init])) { localDelegate = [NGMimeMessageParserDelegate new]; [self setDelegate:localDelegate]; [localDelegate release]; } return self; } /* factory */ - (id)producePartWithHeader:(NGHashMap *)_header { return [NGMimeMessage messageWithHeader:_header]; } /* header field specifics */ - (id)valueOfHeaderField:(NSString *)_name data:(id)_data { // check data for 8-bit headerfields (RFC 2047 (MIME PART III)) /* check whether we got passed a string ... */ if ([_data isKindOfClass:NSStringClass]) { NSLog(@"%s: WARNING unexpected class for headerfield %@ (value %@)", __PRETTY_FUNCTION__, _name, _data); return [super valueOfHeaderField:_name data:_data]; } _data = [_data decodeQuotedPrintableValueOfMIMEHeaderField:_name]; return [super valueOfHeaderField:_name data:_data]; } @end /* NGMimeMessageParser */ @implementation NGMimeRfc822BodyParser - (id)parseBodyOfPart:(id)_part data:(NSData *)_data delegate:(id)_d { id body; id parser; // NGMimeMessageParser parser = [[NGMimeMessageParser alloc] init]; body = [parser parsePartFromData:_data]; [parser release]; parser = nil; return body; } @end /* NGMimeRfc822BodyParser */ SOPE/sope-mime/NGMail/libNGMail.def0000644000000000000000000000144015004363604015602 0ustar rootrootEXPORTS __objc_class_name_NGMBoxReader; __objc_class_name_NGMail; __objc_class_name_NGMailAddress; __objc_class_name_NGMailAddressList; __objc_class_name_NGMailAddressParser; __objc_class_name_NGMimeMessage; __objc_class_name_NGMimeMessageBodyGenerator; __objc_class_name_NGMimeMessageGenerator; __objc_class_name_NGMimeMessageMultipartBodyGenerator; __objc_class_name_NGMimeMessageParser; __objc_class_name_NGMimeMessageRfc822BodyGenerator; __objc_class_name_NGMimeMessageTextBodyGenerator; __objc_class_name_NGPop3Client; __objc_class_name_NGPop3Exception; __objc_class_name_NGPop3MailDropEnumerator; __objc_class_name_NGPop3MessageInfo; __objc_class_name_NGPop3Response; __objc_class_name_NGPop3StateException; __objc_class_name_NGSmtpClient; __objc_class_name_NGSmtpResponse; SOPE/sope-mime/NGMail/NGMailAddress.m0000644000000000000000000000700315004363604016120 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMailAddress.h" #include "common.h" @implementation NGMailAddress + (id)mailAddressWithAddress:(NSString *)_address displayName:(NSString *)_owner route:(NSString *)_route { return [[[NGMailAddress alloc] initWithAddress:_address displayName:_owner route:_route] autorelease]; } - (id)initWithAddress:(NSString *)_address displayName:(NSString *)_owner route:(NSString *)_route { if ((self = [self init])) { NSZone *zone = [self zone]; self->address = [_address copyWithZone:zone]; self->displayName = [_owner copyWithZone:zone]; self->route = [_route copyWithZone:zone]; } return self; } - (void)dealloc { [self->address release]; [self->displayName release]; [self->route release]; [super dealloc]; } /* equality */ - (BOOL)isEqual:(id)_anObject { if ([_anObject isKindOfClass:[NGMailAddress class]]) { NGMailAddress *a = _anObject; return (([self->address isEqualToString:[a address]]) && ([self->displayName isEqualToString:[a displayName]]) && ([self->route isEqualToString:[a route]])); } return NO; } - (NSUInteger)hash { return [self->address hash]; } /* NSCoding */ - (void)encodeWithCoder:(NSCoder *)_encoder { [_encoder encodeObject:address]; [_encoder encodeObject:displayName]; [_encoder encodeObject:route]; } - (id)initWithCoder:(NSCoder *)_decoder { id _address, _displayName, _route; _address = [_decoder decodeObject]; _displayName = [_decoder decodeObject]; _route = [_decoder decodeObject]; return [self initWithAddress:_address displayName:_displayName route:_route]; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { return [[NGMailAddress allocWithZone:_zone] initWithAddress:self->address displayName:self->displayName route:self->route]; } - (id)copy { return [self copyWithZone:[self zone]]; } /* accessors */ - (void)setAddress:(NSString *)_string { ASSIGN(self->address, _string); } - (NSString *)address { return self->address; } - (void)setDisplayName:(NSString *)_displayName { ASSIGN(self->displayName, _displayName); } - (NSString *)displayName { return self->displayName; } - (void)setRoute:(NSString *)_route { ASSIGN(self->route, _route); } - (NSString *)route { return self->route; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"\"%s\" <%s> | route: %s", [self->displayName cString], [self->address cString], [self->route cString]]; } @end /* NGMailAddress */ SOPE/sope-mime/NGMail/NGMail.m0000644000000000000000000000332215004363604014612 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMail.h" #include "NGMBoxReader.h" #include "NGPop3Client.h" #include "NGSmtpClient.h" #include "NGMimeMessage.h" #include "NGMimeMessageParser.h" #include "NGMimeMessageGenerator.h" #include "NGMailAddress.h" #include "NGMailAddressList.h" #include "NGMailAddressParser.h" #import #import @implementation NGMail /* all this is required when compiling on GNUstep without shared libraries. eg gprof profiling only works with static binaries, therefore this is sometimes required. sigh. */ - (void)_staticLinkClasses { [NGMailAddress self]; [NGMailAddressList self]; [NGMailAddressParser self]; [NGMimeMessage self]; [NGMimeMessageParser self]; [NGMimeMessageGenerator self]; [NGMBoxReader self]; [NGPop3Client self]; [NGSmtpClient self]; [NGMime self]; } - (void)_staticLinkModules { [NGStreams class]; [NGMime class]; } @end /* NGMail */ SOPE/sope-mime/NGMail/NGPop3Support.h0000644000000000000000000000361315004363604016144 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMail_NGPop3Support_H__ #define __NGMail_NGPop3Support_H__ #import #include @class NSString; @interface NGPop3Response : NSObject { @protected NSString *line; } + (id)responseWithLine:(NSString *)_line; // accessors - (BOOL)isPositive; - (NSString *)line; @end @interface NGPop3MessageInfo : NSObject { @protected NGPop3Client *client; int messageNumber; int messageSize; } + (id)infoForMessage:(int)_num size:(int)_size client:(NGPop3Client *)_client; // accessors - (int)messageNumber; - (int)size; - (NGPop3Client *)pop3Client; @end #import @interface NGPop3MailDropEnumerator : NSEnumerator { @protected NSEnumerator *msgInfos; } - (id)initWithMessageInfoEnumerator:(NSEnumerator *)_infos; - (id)nextObject; @end @interface NGPop3Exception : NSException @end @interface NGPop3StateException : NGPop3Exception { @protected NGPop3State requiredState; } - (id)initWithClient:(NGPop3Client *)_client requiredState:(NGPop3State)_state; - (NGPop3State)requiredState; @end #endif /* __NGMail_NGPop3Support_H__ */ SOPE/sope-mime/NGMail/NGPop3Client.m0000644000000000000000000003740715004363604015723 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGPop3Client.h" #include "NGPop3Support.h" #include "NGMimeMessageParser.h" #include "NGMimeMessage.h" #include "common.h" @implementation NGPop3Client + (id)pop3Client { NGActiveSocket *s; s = [NGActiveSocket socketInDomain:[NGInternetSocketDomain domain]]; return [[[self alloc] initWithSocket:s] autorelease]; } - (id)init { NSLog(@"%@: init not supported, use initWithSocket: ..", self); [self release]; return nil; } - (id)initWithSocket:(id)_socket { if ((self = [super init])) { self->socket = [_socket retain]; NSAssert(self->socket, @"invalid socket parameter"); self->connection = [(NGBufferedStream *)[NGBufferedStream alloc] initWithSource:_socket]; self->text = [(NGCTextStream *)[NGCTextStream alloc] initWithSource:self->connection]; self->state = [self->socket isConnected] ? NGPop3State_AUTHORIZATION : NGPop3State_unconnected; } return self; } - (void)dealloc { [self->text release]; [self->connection release]; [self->socket release]; [self->lastResponse release]; [super dealloc]; } /* accessors */ - (id)socket { return self->socket; } - (NGPop3State)state { return self->state; } - (NGPop3Response *)lastResponse { return self->lastResponse; } - (void)setDebuggingEnabled:(BOOL)_flag { self->isDebuggingEnabled = _flag; } - (BOOL)isDebuggingEnabled { return self->isDebuggingEnabled; } /* connection */ - (BOOL)connectToAddress:(id)_address { NSString *greeting = nil; [self requireState:NGPop3State_unconnected]; [self->socket connectToAddress:_address]; // receive greeting from server greeting = [self->text readLineAsString]; if (self->isDebuggingEnabled) [NGTextErr writeFormat:@"S: %@\n", greeting]; // is it a welcome ? if (![greeting hasPrefix:@"+OK"]) return NO; // we are welcome, need to authorize [self gotoState:NGPop3State_AUTHORIZATION]; return YES; } - (BOOL)connectToHost:(id)_host { return [self connectToAddress:[NGInternetSocketAddress addressWithService:@"pop3" onHost:_host protocol:@"tcp"]]; } - (void)disconnect { [text flush]; [socket close]; [self gotoState:NGPop3State_unconnected]; } /* commands */ - (NGPop3Response *)receiveSimpleReply { NSString *line = [self->text readLineAsString]; if (line) { NGPop3Response *response = [NGPop3Response responseWithLine:line]; ASSIGN(self->lastResponse, response); } else { [self->lastResponse release]; self->lastResponse = nil; } return self->lastResponse; } - (BOOL)receiveMultilineReply:(NSMutableData *)_data { enum { NGPop3_begin, NGPop3_foundCR, NGPop3_foundCRLF, NGPop3_foundCRLFP, NGPop3_done } pState = NGPop3_begin; void (*addBytes)(id self, SEL _cmd, void *buffer, unsigned int _bufLen); int c; addBytes = (void*)[_data methodForSelector:@selector(appendBytes:length:)]; do { c = [self->connection readByte]; if (c == -1) { NSLog(@"ERROR: connection was shut down .."); break; } /* if (c >= 32) printf("%i '%c'\n", c, c); else printf("%i\n", c); */ NSAssert((c >= 0) && (c <= 255), @"invalid byte read .."); if (pState == NGPop3_foundCRLFP) { if (c == '\r') { // CR LF . CR addBytes(_data, @selector(appendBytes:length:), "\r\n", 2); c = [self->connection readByte]; if (c == '\n') { pState = NGPop3_done; } else { char c8 = c; NSLog(@"WARNING: found strange sequence: 'CR LF . CR 0x%x'", c); addBytes(_data, @selector(appendBytes:length:), ".\r", 2); addBytes(_data, @selector(appendBytes:length:), &c8, 1); pState = NGPop3_begin; } } else if (c == '\n') { // CR LF . LF NSLog(@"WARNING: found strange sequence: 'CR LF . LF'"); addBytes(_data, @selector(appendBytes:length:), "\r\n.\n", 4); pState = NGPop3_begin; } else { // CR LF . (.|other) char c8 = c; if (c != '.') NSLog(@"WARNING: expected '\\r\\n.\\r' or '\\r\\n..', got '\\r\\n.%c'", c); addBytes(_data, @selector(appendBytes:length:), "\r\n", 2); addBytes(_data, @selector(appendBytes:length:), &c8, 1); pState = NGPop3_begin; continue; } } else if (pState == NGPop3_foundCRLF) { if (c == '.') { // found: CR LF . pState = NGPop3_foundCRLFP; continue; } else if (c == '\r') { addBytes(_data, @selector(appendBytes:length:), "\r\n", 2); pState = NGPop3_foundCR; continue; } else { char c8 = c; addBytes(_data, @selector(appendBytes:length:), "\r\n", 2); addBytes(_data, @selector(appendBytes:length:), &c8, 1); pState = NGPop3_begin; } } else if (pState == NGPop3_foundCR) { if (c == '\n') { // found CR LF pState = NGPop3_foundCRLF; continue; } else { char c8 = c; addBytes(_data, @selector(appendBytes:length:), "\r", 1); addBytes(_data, @selector(appendBytes:length:), &c8, 1); pState = NGPop3_begin; } } else if (c == '\r') { pState = NGPop3_foundCR; continue; } /* else if (c == '\n') { NSLog(@"WARNING: found LF without leading CR .."); pState = NGPop3_foundCRLF; continue; }*/ else { char c8 = c; addBytes(_data, @selector(appendBytes:length:), &c8, 1); } } while(pState != NGPop3_done); return (pState == NGPop3_done) ? YES : NO; } - (NGPop3Response *)sendCommand:(NSString *)_command { if (self->isDebuggingEnabled) { [NGTextOut writeFormat:@"C: %@\n", _command]; [NGTextOut flush]; } [text writeString:_command]; [text writeString:@"\r\n"]; [text flush]; return [self receiveSimpleReply]; } - (NGPop3Response *)sendCommand:(NSString *)_command argument:(NSString *)_argument { if (self->isDebuggingEnabled) { if (![_command isEqualToString:@"PASS"]) [NGTextOut writeFormat:@"C: %@ %@\n", _command, _argument]; else [NGTextOut writeFormat:@"C: PASS \n"]; } [text writeString:_command]; [text writeFormat:@" %s\r\n", [_argument cString]]; [text flush]; return [self receiveSimpleReply]; } - (NGPop3Response *)sendCommand:(NSString *)_command intArgument:(int)_argument { if (self->isDebuggingEnabled) { if (![_command isEqualToString:@"PASS"]) [NGTextOut writeFormat:@"C: %@ %i\n", _command, _argument]; else [NGTextOut writeFormat:@"C: PASS \n"]; } [text writeString:_command]; [text writeFormat:@" %i\r\n", _argument]; [text flush]; return [self receiveSimpleReply]; } - (NGPop3Response *)sendCommand:(NSString *)_command intArgument:(int)_arg1 intArgument:(int)_arg2 { if (self->isDebuggingEnabled) { if (![_command isEqualToString:@"PASS"]) [NGTextOut writeFormat:@"C: %@ %i %i\n", _command, _arg1, _arg2]; else [NGTextOut writeFormat:@"C: PASS \n"]; } [text writeString:_command]; [text writeFormat:@" %i %i\r\n", _arg1, _arg2]; [text flush]; return [self receiveSimpleReply]; } // state - (void)requireState:(NGPop3State)_state { if (_state != [self state]) { [[[NGPop3StateException alloc] initWithClient:self requiredState:_state] raise]; } } - (void)gotoState:(NGPop3State)_state { self->state = _state; } // service commands - (BOOL)login:(NSString *)_user password:(NSString *)_passwd { NGPop3Response *reply = nil; [self requireState:NGPop3State_AUTHORIZATION]; reply = [self sendCommand:@"USER" argument:_user]; if ([reply isPositive]) { reply = [self sendCommand:@"PASS" argument:_passwd]; if ([reply isPositive]) { [self gotoState:NGPop3State_TRANSACTION]; return YES; } } NSLog(@"POP3 authorization of user %@ failed ..", _user); return NO; } - (BOOL)quit { NGPop3Response *reply = nil; reply = [self sendCommand:@"QUIT"]; if ([reply isPositive]) { unsigned int waitBytes = 0; if (self->state == NGPop3State_TRANSACTION) self->state = NGPop3State_UPDATE; if (self->isDebuggingEnabled) [NGTextErr writeFormat:@"S: %@\n", [reply line]]; // wait for connection close .. while ([self->connection readByte] != -1) waitBytes++; self->state = NGPop3State_unconnected; } return [reply isPositive]; } - (BOOL)statMailDropCount:(int *)_count size:(int *)_size { NGPop3Response *reply = nil; [self requireState:NGPop3State_TRANSACTION]; *_count = 0; *_size = 0; reply = [self sendCommand:@"STAT"]; if ([reply isPositive]) { const char *cstr = [[reply line] cString]; while ((*cstr != '\0') && (*cstr != ' ')) cstr++; if (*cstr == '\0') return NO; cstr++; *_count = atoi(cstr); while ((*cstr != '\0') && (*cstr != ' ')) cstr++; if (*cstr == '\0') return NO; cstr++; *_size = atoi(cstr); return YES; } else return NO; } - (NGPop3MessageInfo *)listMessage:(int)_messageNumber { NGPop3Response *reply = nil; [self requireState:NGPop3State_TRANSACTION]; reply = [self sendCommand:@"LIST" intArgument:_messageNumber]; if ([reply isPositive]) { const char *cstr = index([[reply line] cString], ' '); if (cstr) { int msgNum; cstr++; msgNum = atoi(cstr); cstr = index(cstr, ' ') + 1; if (cstr > (char *)1) { NGPop3MessageInfo *info = nil; int msgSize = atoi(cstr); info = [NGPop3MessageInfo infoForMessage:msgNum size:msgSize client:self]; return info; } } NSLog(@"ERROR: invalid reply line '%@' ..", [reply line]); } return nil; } - (NSEnumerator *)listMessages { NGPop3Response *reply = nil; [self requireState:NGPop3State_TRANSACTION]; reply = [self sendCommand:@"LIST"]; if ([reply isPositive]) { NSMutableArray *array = nil; NSString *line = nil; array = [NSMutableArray arrayWithCapacity:128]; line = [self->text readLineAsString]; while ((line != nil) && (![line isEqualToString:@"."])) { NGPop3MessageInfo *info = nil; const char *cstr = (char *)[line cString]; int msgNum, msgSize; msgNum = atoi(cstr); cstr = index(cstr, ' ') + 1; if (cstr > (char *)1) msgSize = atoi(cstr); else { NSLog(@"WARNING(%s): invalid reply line '%@'", __PRETTY_FUNCTION__, line); msgSize = 0; } info = [NGPop3MessageInfo infoForMessage:msgNum size:msgSize client:self]; if (info) [array addObject:info]; else NSLog(@"ERROR: could not produce info for line '%@'", line); line = [self->text readLineAsString]; } return [array objectEnumerator]; } else return nil; } - (NSData *)retrieveMessage:(int)_msgNumber { NGPop3Response *reply = nil; [self requireState:NGPop3State_TRANSACTION]; reply = [self sendCommand:@"RETR" intArgument:_msgNumber]; if ([reply isPositive]) { NSMutableData *data = nil; const char *cstr = index([[reply line] cString], ' '); unsigned msgSize = -1; if (cstr) { cstr++; msgSize = atoi(cstr); data = [NSMutableData dataWithCapacity:msgSize + 1]; } else data = [NSMutableData dataWithCapacity:1024]; if ([self receiveMultilineReply:data]) { if ((msgSize > 0) && ([data length] > msgSize)) { NSLog(@"data was longer than message size .."); //[data setLength:msgSize]; } return data; } } return nil; } - (BOOL)deleteMessage:(int)_msgNumber { NGPop3Response *reply = nil; [self requireState:NGPop3State_TRANSACTION]; reply = [self sendCommand:@"DELE" intArgument:_msgNumber]; if ([reply isPositive]) { return YES; } return NO; } - (BOOL)noop { [self requireState:NGPop3State_TRANSACTION]; return [[self sendCommand:@"NOOP"] isPositive]; } - (BOOL)reset { [self requireState:NGPop3State_TRANSACTION]; return [[self sendCommand:@"RSET"] isPositive]; } // optional service commands - (NSData *)retrieveMessage:(int)_msgNumber bodyLineCount:(int)_numberOfLines { NGPop3Response *reply = nil; [self requireState:NGPop3State_TRANSACTION]; reply = [self sendCommand:@"TOP" intArgument:_msgNumber intArgument:_numberOfLines]; if ([reply isPositive]) { NSMutableData *data = nil; data = [NSMutableData dataWithCapacity:1024]; if ([self receiveMultilineReply:data]) return data; } return nil; } - (NSDictionary *)uniqueIdMappings { NGPop3Response *reply = nil; [self requireState:NGPop3State_TRANSACTION]; reply = [self sendCommand:@"UIDL"]; if ([reply isPositive]) { NSMutableDictionary *dict = nil; NSString *line = nil; dict = [NSMutableDictionary dictionaryWithCapacity:256]; line = [self->text readLineAsString]; while ((line != nil) && (![line isEqualToString:@"."])) { const char *cstr = index([line cString], ' '); if (cstr) { int msgNum = atoi([line cString]); cstr++; [dict setObject:[NSString stringWithCString:cstr] forKey:[NSNumber numberWithInt:msgNum]]; } else { NSLog(@"WARNING(%s): invalid reply line '%@'", __PRETTY_FUNCTION__, line); } line = [self->text readLineAsString]; } return dict; } else return nil; } - (NSString *)uniqueIdOfMessage:(int)_messageNumber { NGPop3Response *reply = nil; [self requireState:NGPop3State_TRANSACTION]; reply = [self sendCommand:@"UIDL" intArgument:_messageNumber]; if ([reply isPositive]) { const char *cstr = index([[reply line] cString], ' '); if (cstr) { // found message number cstr = index(cstr + 1, ' '); if (cstr) { // found u-id cstr++; return [NSString stringWithCString:cstr]; } } NSLog(@"ERROR: invalid reply line '%@' ..", [reply line]); } return nil; } /* MIME support */ - (NSEnumerator *)messageEnumerator { return [[[NGPop3MailDropEnumerator alloc] initWithMessageInfoEnumerator:[self listMessages]] autorelease]; } - (NGMimeMessage *)messageWithNumber:(int)_messageNumber { NSData *msgData = [self retrieveMessage:_messageNumber]; if (msgData) { NGDataStream *msgStream; NGMimeMessageParser *parser; NGMimeMessage *message; msgStream = [[NGDataStream alloc] initWithData:msgData]; parser = [[NGMimeMessageParser alloc] init]; *(&message) = nil; NS_DURING message = (NGMimeMessage *)[parser parsePartFromStream:msgStream]; NS_HANDLER message = nil; NS_ENDHANDLER; message = [message retain]; [parser release]; parser = nil; [msgStream release]; msgStream = nil; msgData = nil; return [message autorelease]; } else return nil; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"", self, [self socket]]; } @end /* NGPop3Client */ SOPE/sope-mime/NGMail/NGMailAddress.h0000644000000000000000000000304415004363604016114 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMail_NGMailAddress_H__ #define __NGMail_NGMailAddress_H__ #import @class NSString; @interface NGMailAddress : NSObject < NSCopying, NSCoding > { @protected NSString *address; NSString *displayName; NSString *route; } + (id)mailAddressWithAddress:(NSString *)_address displayName:(NSString *)_owner route:(NSString *)_route; - (id)initWithAddress:(NSString *)_address displayName:(NSString *)_owner route:(NSString *)_route; // equality - (BOOL)isEqual:(id)_anObject; // accessors - (void)setAddress:(NSString *)_string; - (NSString *)address; - (void)setDisplayName:(NSString *)_displayName; - (NSString *)displayName; - (void)setRoute:(NSString *)_route; - (NSString *)route; @end #endif /* __NGMail_NGMailAddress_H__ */ SOPE/sope-mime/NGMail/NGSmtpReplyCodes.h0000644000000000000000000001215315004363604016642 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMail_NGSmtpReplyCodes_H__ #define __NGMail_NGSmtpReplyCodes_H__ /* SMTP reply groups: 1yz Positive Preliminary reply The command has been accepted, but the requested action is being held in abeyance, pending confirmation of the information in this reply. The sender-SMTP should send another command specifying whether to continue or abort the action. [Note: SMTP does not have any commands that allow this type of reply, and so does not have the continue or abort commands.] 2yz Positive Completion reply The requested action has been successfully completed. A new request may be initiated. 3yz Positive Intermediate reply The command has been accepted, but the requested action is being held in abeyance, pending receipt of further information. The sender-SMTP should send another command specifying this information. This reply is used in command sequence groups. 4yz Transient Negative Completion reply The command was not accepted and the requested action did not occur. However, the error condition is temporary and the action may be requested again. The sender should return to the beginning of the command sequence (if any). It is difficult to assign a meaning to "transient" when two different sites (receiver- and sender- SMTPs) must agree on the interpretation. Each reply in this category might have a different time value, but the sender-SMTP is encouraged to try again. A rule of thumb to determine if a reply fits into the 4yz or the 5yz category (see below) is that replies are 4yz if they can be repeated without any change in command form or in properties of the sender or receiver. (E.g., the command is repeated identically and the receiver does not put up a new implementation.) 5yz Permanent Negative Completion reply The command was not accepted and the requested action did not occur. The sender-SMTP is discouraged from repeating the exact request (in the same sequence). Even some "permanent" error conditions can be corrected, so the human user may want to direct the sender-SMTP to reinitiate the command sequence by direct action at some point in the future (e.g., after the spelling has been changed, or the user has altered the account status). Second digit description: The second digit encodes responses in specific categories: x0z Syntax These replies refer to syntax errors, syntactically correct commands that don't fit any functional category, and unimplemented or superfluous commands. x1z Information These are replies to requests for information, such as status or help. x2z Connections These are replies referring to the transmission channel. x3z Unspecified as yet. x4z Unspecified as yet. x5z Mail system These replies indicate the status of the receiver mail system vis-a-vis the requested transfer or other mail system action. */ typedef enum { NGSmtpInvalidReplyCode = -1, // 100 codes, positive preliminary reply // 200 codes, positive completion reply NGSmtpSystemStatus = 211, NGSmtpHelpMessage = 214, NGSmtpServiceReady = 220, NGSmtpServiceClosingChannel = 221, NGSmtpAuthenticationSuccess = 235, NGSmtpActionCompleted = 250, NGSmtpUserNotLocalWillForward = 251, // 300 codes, positive intermediate reply NGSmtpServerChallenge = 334, NGSmtpStartMailInput = 354, // 400 codes, transient negative completion reply NGSmtpServiceNotAvailable = 421, NGSmtpMailboxBusy = 450, NGSmtpErrorInProcessing = 451, NGSmtpInsufficientStorage = 452, // 500 codes, permanent negative completion reply NGSmtpInvalidCommand = 500, NGSmtpInvalidParameter = 501, NGSmtpCommandNotImplemented = 502, NGSmtpBadCommandSequence = 503, NGSmtpParameterNotImplemented = 504, NGSmtpMailboxNotFound = 550, NGSmtpUserNotLocalTryForward = 551, NGSmtpExceededStorageAllocation = 552, NGSmtpMailboxNameNotAllowed = 553, NGSmtpTransactionFailed = 554 } NGSmtpReplyCode; #endif /* __NGMail_NGSmtpReplyCodes_H__ */ SOPE/sope-mime/NGMail/NGMail-Info.plist0000644000000000000000000000133615004363604016405 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable NGMail CFBundleGetInfoString CFBundleIdentifier org.OpenGroupware.SOPE.mime.NGMail CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType FMWK CFBundleShortVersionString CFBundleSignature ???? CFBundleVersion 4.5 SOPE/sope-mime/NGMail/NGMimeMessageRfc822BodyGenerator.m0000644000000000000000000000221415004363604021477 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeMessageGenerator.h" #include "NGMimeMessage.h" #include "common.h" @implementation NGMimeMessageRfc822BodyGenerator - (id)generatorForPart:(id)_part { id gen; gen = [[[NGMimeMessageGenerator alloc] init] autorelease]; [gen setUseMimeData:self->useMimeData]; return gen; } @end /* NGMimeMessageRfc822BodyGenerator */ SOPE/sope-mime/NGMail/NGMailDecls.h0000644000000000000000000000207415004363604015563 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMail_NGStreamDecls_H__ #define __NGMail_NGStreamDecls_H__ #if BUILD_libNGMail_DLL # define NGMail_EXPORT __declspec(dllexport) #elif libNGMail_ISDLL # define NGMail_EXPORT extern __declspec(dllimport) #else # define NGMail_EXPORT extern #endif #endif /* __NGMail_NGStreamDecls_H__ */ SOPE/sope-mime/NGMail/NGMailBase64Encoding.m0000644000000000000000000000543115004363604017231 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeMessageGenerator.h" #include "NGMimeMessage.h" #include #include "common.h" /* Defaults Mail_Use_8bit_Encoding_For_Text[BOOL] -- Use 8bit content-transfer-encoding for text messages */ NSData * _base64Encoding(NGMimeBodyGenerator *self, NSData *_data_, id_part, NGMutableHashMap *_addHeaders) { NSString *transEnc = nil; const char *bytes = NULL; unsigned length = 0; /* kinda hack, treat NGMimeFileData objects as already encoded */ if ([_data_ isKindOfClass:[NGMimeFileData class]]) return _data_; /* encoding */ bytes = [_data_ bytes]; length = [_data_ length]; // Force encoding if the content is bigger than 72 bytes or if it contains // non-ascii characters. if (length < 72) { while (length > 0) { if ((unsigned char)*bytes > 127) { break; } bytes++; length--; } } if (length > 0) { // should be encoded NGMimeType *type; type = [_part contentType]; if ([[type type] isEqualToString:@"text"]) { NSUserDefaults *ud; BOOL use8bit; ud = [NSUserDefaults standardUserDefaults]; use8bit = [ud boolForKey:@"Mail_Use_8bit_Encoding_For_Text"]; if (use8bit) transEnc = @"8bit"; else { _data_ = [_data_ dataByEncodingQuotedPrintable]; transEnc = @"quoted-printable"; } } else { NGMimeType *appOctet; _data_ = [_data_ dataByEncodingBase64]; transEnc = @"base64"; appOctet = [NGMimeType mimeType:@"application" subType:@"octet-stream"]; if (type == nil) [_addHeaders setObject:appOctet forKey:@"content-type"]; } [_addHeaders setObject:transEnc forKey:@"content-transfer-encoding"]; } if ([_data_ length]) [_addHeaders setObject:[NSNumber numberWithInt:[_data_ length]] forKey:@"content-length"]; return _data_; } SOPE/sope-mime/NGMail/GNUmakefile.preamble0000644000000000000000000000150015004363604017161 0ustar rootroot# compilation settings SOPE_ROOT=../.. ADDITIONAL_CPPFLAGS += -Wall ifeq ($(PRECOMPILED_HEADERS),yes) ADDITIONAL_CPPFLAGS += -Winvalid-pch endif NGMail_INCLUDE_DIRS += \ -I.. -I$(SOPE_ROOT) \ -I$(SOPE_ROOT)/sope-core/NGStreams/ \ -I$(SOPE_ROOT)/sope-core/NGExtensions/ \ -I$(SOPE_ROOT)/sope-core/ ifeq ($(frameworks),yes) NGMail_LIBRARIES_DEPEND_UPON += \ -framework NGMime \ -framework NGStreams -framework NGExtensions -framework EOControl \ -framework DOM -framework SaxObjC endif # library/framework search pathes DEP_DIRS = \ .. \ $(SOPE_ROOT)/sope-core/EOControl $(SOPE_ROOT)/sope-core/NGExtensions \ $(SOPE_ROOT)/sope-core/NGStreams \ $(SOPE_ROOT)/sope-xml/DOM $(SOPE_ROOT)/sope-xml/SaxObjC ifeq ($(frameworks),yes) ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir)) endif SOPE/sope-mime/NGMail/NGMimeMessageGenerator.h0000644000000000000000000000306615004363604017773 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGMimeMessageGenerator_H__ #define __NGMime_NGMimeMessageGenerator_H__ #include #include /* Generates RFC 2822 MIME message parts. */ @interface NGMimeMessageBodyGenerator : NGMimeBodyGenerator @end @interface NGMimeMessageTextBodyGenerator : NGMimeTextBodyGenerator @end @interface NGMimeMessageMultipartBodyGenerator : NGMimeMultipartBodyGenerator @end @interface NGMimeMessageRfc822BodyGenerator : NGMimeRfc822BodyGenerator @end @interface NGMimeMessageGenerator : NGMimePartGenerator @end extern NSData * _base64Encoding(NGMimeBodyGenerator *self, NSData *_data_, id_part, NGMutableHashMap *_addHeaders); #endif /*__NGMime_NGMimeMessageGenerator_H__ */ SOPE/sope-mime/NGMail/NGMailAddressParser.h0000644000000000000000000000313215004363604017267 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMail_NGMailAddressParser_H__ #define __NGMail_NGMailAddressParser_H__ #import #import @class NSData, NSArray; @class NGMailAddressList; /* use RFC 822 */ @interface NGMailAddressParser : NSObject { @private unichar *data; int dataPos; int errorPos; int maxLength; } + (id)mailAddressParserWithString:(NSString *)_string; + (id)mailAddressParserWithData:(NSData *)_data; + (id)mailAddressParserWithCString:(const char *)_cString; - (id)initWithString:(NSString *)_str; + (NSString *)sanitizeMailAddresses:(NSString *)originalAddress; /* parsing */ - (id)parse; // returns NGMailAddressList/NGMailAddress or nil on error - (NSArray *)parseAddressList; /* error information */ - (int)errorPosition; @end #endif /* __NGMail_NGMailAddressParser_H__ */ SOPE/sope-mime/NGMail/NGMimeMessageGenerator.m0000644000000000000000000002633515004363604020004 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeMessageGenerator.h" #include "NGMimeMessage.h" #include #include "common.h" #include @implementation NGMimeMessageGenerator static BOOL debugOn = NO; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; debugOn = [ud boolForKey:@"NGMimeGeneratorDebugEnabled"]; if (debugOn) NSLog(@"WARNING[%@]: NGMimeGeneratorDebugEnabled is enabled!", self); } /* header field specifics */ - (BOOL)isMultiValueCommaHeaderField:(NSString *)_headerField { /* This is called by the superclass when generating fields. Currently checks for: to, cc, bcc */ unsigned len; unichar c0, c1; if ((len = [_headerField length]) < 2) return [super isMultiValueCommaHeaderField:_headerField]; c0 = [_headerField characterAtIndex:0]; c1 = [_headerField characterAtIndex:1]; switch (len) { case 2: if ((c0 == 't' || c0 == 'T') && ((c1 == 'o' || c1 == 'O'))) return YES; if ((c0 == 'c' || c0 == 'C') && ((c1 == 'c' || c1 == 'C'))) return YES; break; case 3: if ((c0 == 'b' || c0 == 'B') && ((c1 == 'c' || c1 == 'C'))) { c0 = [_headerField characterAtIndex:2]; if (c0 == 'c' || c0 == 'C') return YES; } break; } return [super isMultiValueCommaHeaderField:_headerField]; } int _encodeWord(const char *bytes, unsigned int length, NSMutableData *destination) { const char *iso = "=?utf-8?q?"; unsigned int isoLen = 10; const char *isoEnd = "?="; unsigned int isoEndLen = 2; char *des = NULL; unsigned int desLen = 0; int retval = -1; desLen = length*3 + isoLen + isoEndLen; des = calloc(desLen + 2, sizeof(char)); if (!des) { return -1; } memcpy(des, iso, isoLen); desLen = NGEncodeQuotedPrintableMime((unsigned char *) bytes, length, (unsigned char *)(des + isoLen), desLen - isoLen - isoEndLen); if ((int)desLen != -1) { memcpy(des + isoLen + desLen, isoEnd, isoEndLen); [destination appendBytes: des length: (isoLen + desLen + isoEndLen)]; retval = 0; } free(des); return retval; } /* This function assumes the format of MIME header parameters. The no-MIME headers will continue to be correctly encoded, just it will be several q-encoded words separated as if they were header MIME parameters. Also, it assumes that the header MIME parameters are correctly generated by the client, and does not try to enforce that parameter names should not be encoded. */ - (id)_escapeFieldValue:(NSData *)_data { NSMutableData *encodedHeader = nil; const char *bytes; unsigned int valueLength = 0; unsigned int lastPosition; unsigned int i; BOOL doEnc = NO; unsigned int encodingPos = 0; unsigned int asciiPos = 0; unsigned int parameterPos = 0; BOOL quoted = NO; // NSString *str; // TODO: this s***s big time! // NSLog (@"class: '%@'", NSStringFromClass ([_data class])); // #if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY // str = [[NSString alloc] initWithData:_data // encoding:NSISOLatin1StringEncoding]; // str = [str autorelease]; // #else // str = [[NSString alloc] initWithData:_data // encoding:NSISOLatin9StringEncoding]; // #endif // bytes = [str cString]; // length = [str cStringLength]; bytes = (char*) [_data bytes]; valueLength = [_data length]; lastPosition = valueLength - 1; for (i=0; i < valueLength; i++) { unsigned char chr = (unsigned char)bytes[i]; BOOL endWord = NO; if (i == lastPosition) { endWord = YES; if (chr > 127) doEnc = YES; } else if (chr > 127) { doEnc = YES; } else if (chr == ';') { if (encodingPos == i) { // this is to skip contiguous ';' encodingPos += 1; } else { endWord = YES; } } else if (chr == '=' && !doEnc && i > 0) { if (((unsigned char)bytes[i-1] != '=') && ((unsigned char)bytes[i+1] != '=')) { parameterPos = encodingPos; encodingPos = i + 1; if ((unsigned char)bytes[i+1] == '"') quoted = YES; } } if (endWord) { if (!doEnc) { encodingPos = i +1; if ((i == lastPosition) && encodedHeader) { [encodedHeader appendBytes: "\n" length: 1]; [encodedHeader appendBytes: bytes + asciiPos length: valueLength - asciiPos]; } } else { unsigned int lenAscii; unsigned int lenParameter; unsigned int lenEncode; unsigned int afterCrLfPos; if (encodedHeader == nil) encodedHeader = [NSMutableData data]; // calculate length of the sections if (asciiPos == encodingPos) { lenAscii = 0; lenParameter = 0; } else { if (asciiPos > parameterPos) { // no parameter in this case lenAscii = encodingPos - asciiPos; lenParameter = 0; } else { lenAscii = parameterPos - asciiPos; lenParameter = encodingPos - parameterPos; } } lenEncode = i + 1 - encodingPos; if (lenAscii) { // add no encoded bytes as they are [encodedHeader appendBytes: bytes + asciiPos length: lenAscii]; } if (lenAscii || asciiPos > 0) { // we need a crlf+space to split the header value afterCrLfPos = asciiPos + lenAscii; if ((unsigned char)bytes[afterCrLfPos] == ' ') { if ((afterCrLfPos+1 != lastPosition) && (unsigned char)bytes[afterCrLfPos+1] != ' ') { if (lenParameter == 0) { // assure the space is not encoded [encodedHeader appendBytes: "\n " length: 2]; encodingPos += 1; lenEncode -= 1; } else { // the space after the mime delimiter will be recicled as continue-line [encodedHeader appendBytes: "\n" length: 1]; } } else { // 2 spaces at begin of line we must quote the second [encodedHeader appendBytes: "\n \\ " length: 4]; // we must adjust pointer to bypass the two altered spaces if (lenParameter) { parameterPos += 2; lenParameter -= 2; } else { encodingPos += 2; lenEncode -= 2; } } } else { [encodedHeader appendBytes: "\n " length: 2]; } } if (lenParameter) { // add parameter lvalue as is it [encodedHeader appendBytes: bytes + parameterPos length: lenParameter]; } // dont encode ';' termination // and check if it is fully quoted if needed if (chr == ';') { lenEncode -= 1; if ((unsigned char)bytes[i-1] != '"') quoted = NO; } else if (quoted && (chr != '"')) { quoted = NO; } if (quoted) { encodingPos += 1; lenEncode -= 2; // because we left two characters aside [encodedHeader appendBytes: "\"" length: 1]; } if (_encodeWord (bytes+encodingPos, lenEncode, encodedHeader) == 0) { doEnc = NO; asciiPos = i + 1; encodingPos = i + 1; if (quoted) { [encodedHeader appendBytes: "\"" length: 1]; quoted = NO; } if (chr == ';') { [encodedHeader appendBytes: ";" length: 1]; } } else { [self logWithFormat: @"WARNING: Error during quoted-printable encoding"]; return _data; } } } } if (encodedHeader == nil) return _data; return encodedHeader; } - (NSData *)generateDataForHeaderField:(NSString *)_hf value:(id)_value { NSData *data; // TODO: properly deal with header field values, add proper quoting // prior passing the value up? data = [super generateDataForHeaderField:_hf value:_value]; return [self _escapeFieldValue: data]; } /* content-transfer-encoding */ - (id)defaultBodyGenerator { NGMimeMessageBodyGenerator *gen; gen = [[NGMimeMessageBodyGenerator alloc] init]; [gen setUseMimeData:self->useMimeData]; return gen; } - (id)generatorForBodyOfPart:(id)_part { /* called by -generateBodyData:? */ id bodyGen; NGMimeType *contentType; NSString *type; Class generatorClass; if (self->delegateRespondsTo.generatorGeneratorForBodyOfPart) { bodyGen = [self->delegate mimePartGenerator:self generatorForBodyOfPart:self->part]; if (bodyGen != nil) return bodyGen; } if ((contentType = [_part contentType]) == nil) contentType = [self defaultContentTypeForPart:_part]; if (contentType == nil) { [self logWithFormat:@"WARNING(%s): missing content-type in part 0x%p.", __PRETTY_FUNCTION__, _part]; return nil; } type = [contentType type]; generatorClass = Nil; if ([type isEqualToString:NGMimeTypeMultipart]) generatorClass = [NGMimeMessageMultipartBodyGenerator class]; else if ([type isEqualToString:NGMimeTypeText]) generatorClass = [NGMimeMessageTextBodyGenerator class]; else if (([type isEqualToString:NGMimeTypeMessage]) && [[contentType subType] isEqualToString:@"rfc822"]) { generatorClass = [NGMimeMessageRfc822BodyGenerator class]; } if (generatorClass == Nil) { [self debugWithFormat: @"found no body generator class for part with type: %@", contentType]; return nil; } if (debugOn) { [self debugWithFormat:@"using body generator class %@ for part: %@", generatorClass, _part]; } /* allocate generator */ bodyGen = [[[generatorClass alloc] init] autorelease]; [(id)bodyGen setUseMimeData:self->useMimeData]; return bodyGen; } /* debugging */ - (BOOL)isDebuggingEnabled { return debugOn; } @end /* NGMimeMessageGenerator */ SOPE/sope-mime/GNUmakefile0000644000000000000000000000220715004363604014271 0ustar rootroot# GNUstep makefile include ../config.make include $(GNUSTEP_MAKEFILES)/common.make include ./Version ifneq ($(frameworks),yes) LIBRARY_NAME = libNGMime else FRAMEWORK_NAME = NGMime endif libNGMime_HEADER_FILES_DIR = . libNGMime_HEADER_FILES_INSTALL_DIR = /NGMime libNGMime_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION) libNGMime_INSTALL_DIR=$(SOPE_SYSLIBDIR) libNGMime_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION) ifneq ($(frameworks),yes) libNGMime_SUBPROJECTS = NGMime NGMail NGImap4 else libNGMime_SUBPROJECTS = NGMime SUBPROJECTS = NGMail NGImap4 endif # framework support NGMime_HEADER_FILES = $(libNGMime_HEADER_FILES) NGMime_OBJC_FILES = $(libNGMime_OBJC_FILES) NGMime_SUBPROJECTS = $(libNGMime_SUBPROJECTS) # building -include GNUmakefile.preamble ifneq ($(FHS_INSTALL_ROOT),) GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include endif ifneq ($(frameworks),yes) include $(GNUSTEP_MAKEFILES)/library.make else include $(GNUSTEP_MAKEFILES)/framework.make include $(GNUSTEP_MAKEFILES)/aggregate.make endif -include GNUmakefile.postamble # package macosx-pkg :: all ../maintenance/make-osxpkg.sh sope-mime SOPE/sope-mime/ChangeLog0000644000000000000000000002317615004363604014001 0ustar rootroot2008-09-01 Ludovic Marcotte * NGMail: improvements (v4.7.3) 2008-03-04 Marcus Mueller * README-OSX.txt: Updated 2008-01-29 Albrecht Dress * fixes for OGo bug #789 (reply-to QP encoding) (v4.7.2) 2007-08-29 Helge Hess * MacOS Version overflow (v4.7.1) 2007-08-24 Wolfgang Sourdeau * NGImap4: a fix for OGo bug #1905 (folders with slashes) (v4.7.255) 2007-08-16 Wolfgang Sourdeau * NGImap4: added support for non-system IMAP4 flags (OGo bug #1899) (v4.7.254) 2007-08-29 Helge Hess * NGMime: some gstep-base hackaround (OGo bug #1890) (v4.7.253) 2007-08-01 Wolfgang Sourdeau * NGImap4: fixed some gstep-base issue (OGo bug #1893) (v4.7.252) 2007-08-01 Wolfgang Sourdeau * NGImap4: added support for bodystructure fetches (fixes OGo bug #1892) (v4.7.251) 2007-08-09 Wolfgang Sourdeau * NGMail: fixed some connection states in NGSmtpClient (OGo bug #1897) (v4.7.250) 2007-07-15 Helge Hess * NGImap4: fixed an encoding issue on gstep-base/Cocoa (OGo bug #1885) (v4.7.249) 2007-06-01 Helge Hess * NGMime: code refactoring, fixed OGo bug #1856 (QP decoding) (v4.7.248) 2007-05-28 Helge Hess * NGMime: fixed compilation on gnustep-base (v4.7.247) * NGMime: improved text body encoding (v4.7.246) 2007-05-15 Wolfgang Sourdeau * NGMime.m: encode string body contents using the charset of the content-type (when available) (OGo bug #1873) (v4.7.245) 2007-05-28 Helge Hess * NGImap4: changed behaviour wrt bug 1875 (v4.7.244) 2007-02-12 Helge Hess * NGImap4: fixed a gstep-base compilation warning (v4.7.243) 2006-08-03 Wolfgang Sourdeau * NGImap4: improved subfolder handling (v4.5.242) 2006-07-04 Helge Hess * use %p for pointer formats, fixed gcc 4.1 warnings, use -isNotEmpty when appropriate (v4.5.241) 2006-02-22 Helge Hess * NGMime: hardcoded CET/UTC in tzname parsing (v4.5.240) 2005-12-13 Helge Hess * NGMail: some code cleanups / reorgs (v4.5.239) * v4.5.238 * NGImap4: fixed QP handling in IMAP4 envelopes (#1587) * NGMime: code cleanups 2005-11-17 Helge Hess * properly include string.h where required to avoid warnings (v4.5.237) 2005-09-18 Helge Hess * NGMime: fixed a linking issue on OSX (v4.5.236) 2005-08-30 Helge Hess * do not use PCH warning flags with older compilers (v4.5.235) 2005-08-27 Helge Hess * added some PCH support (v4.5.234) 2005-08-17 Helge Hess * build NGImap4 and NGMail frameworks (v4.5.233) 2005-08-10 Helge Hess * added OSX framework support (v4.5.232) 2005-07-27 Helge Hess * NGImap4: fixed a gcc 4.0 warning (v4.5.231) 2005-07-26 Helge Hess * NGImap4: fixed a compatibility issue with Cocoa (v4.5.230) 2005-07-20 Helge Hess * NGMime, NGMail: added some convinience methods to access the header fields of a part (v4.5.229) 2005-07-15 Helge Hess * NGImap4: fixed a parsing bug in ACL responses (v4.5.228) 2005-07-14 Helge Hess * NGImap4: fixed default names of NGImap4Connection, some code reorgs (v4.5.227) 2005-07-13 Helge Hess * NGImap4: added -description to imap4-connection (v4.5.226) 2005-07-12 Helge Hess * NGMime: headers hashmap is now properly made immutable (v4.5.225) 2005-07-11 Helge Hess * NGMime: added a safeguard for some edge case (v4.5.224) * NGImap4: added NGImap4Connection, NGImap4ConnectionManager (v4.5.223) 2005-07-07 Helge Hess * NGImap4: added method to store flags for MSN sequences (v4.5.222) 2005-07-05 Helge Hess * NGImap4ResponseNormalizer.[hm], NGImap4Client.[hm], NGImap4ResponseParser.m: added some ACL related commands (v4.5.221) 2005-04-24 Helge Hess * NGMime, NGImap4, NGMail: fixed gcc 4.0 warnings (v4.5.220) 2005-03-24 Helge Hess * NGMime, NGMail: fixed OGo bug #1324 by adding support for multivalue header fields (v4.5.219) * NGMime: minor code cleanups (v4.5.218) 2005-03-05 Helge Hess * NGMime: fixed an issue with incorrect header field termination (v4.5.217) * NGImap4: fixed a MacOSX incompatibility (v4.5.216) 2005-03-03 Helge Hess * NGImap4: added some debugging facilities (v4.5.215) 2005-02-14 Helge Hess * NGImap4: changed base64 encoding in Sieve client to fix OGo bug #1228 (v4.5.214) 2005-02-12 Helge Hess * NGImap4: reworked qualifier generation, fixed handling of OR qualifiers (v4.5.213) * NGImap4: improved copying, cleaned up sort ordering (v4.5.212) 2005-02-08 Helge Hess * NGImap4: added method to retrieve selected folder (v4.5.211) * NGImap4: change in API: NGImap4Envelope now uses lists for 'from' and 'reply-to' headers (v4.5.210) 2005-01-31 Helge Hess * NGImap4: added support for creating envelope objects from body structure dictionaries (v4.5.209) 2005-01-30 Helge Hess * NGImap4: code cleanup in response normalizer (v4.5.208) * NGImap4: some fix in the Sieve script upload (v4.5.207) 2005-01-30 Helge Hess * v4.5.206 * NGMail: fixed a crasher in a warn-log (occurred if no content-type was set), major reorgs * NGMime: some code cleanups, added MIME generation debugging, improved NGMimeJoinedData, make reorgs * NGImap4: minor code cleanups 2005-01-04 Helge Hess * NGImap4: fixed a small warning with Xcode (v4.5.205) 2004-12-09 Helge Hess * NGMime: fixed an issue with future date headers and libFoundation (v4.5.204) 2004-12-03 Helge Hess * NGImap4: fixed an error handler in the Sieve client (v4.5.203) 2004-11-30 Helge Hess * NGMail: fixed a bug in NGSendMail (v4.5.202) 2004-11-28 Helge Hess * NGImap4: improvements in the Sieve client (v4.5.201) 2004-11-19 Helge Hess * NGImap4: minor code cleanups (v4.5.200) 2004-11-16 Helge Hess * NGImap4: minor code cleanups in NGSieveClient (v4.5.199) 2004-11-13 Helge Hess * NGMime: added support for 'reply-type' parameter in text MIME types (v4.5.198) 2004-11-08 Helge Hess * NGImap4: fixed a bug with parsing envelopes that are reported with data headers ({count} syntax) (v4.5.197) 2004-10-30 Thierry Delhaise * NGImap4: fixed OGo bug #958 (IMAP4 parser broke with Courier) (v4.3.196) 2004-10-29 Helge Hess * NGMime: minor cleanups (v4.3.195) 2004-10-28 Helge Hess * NGImap4: added a constructor to NGImap4Envelope (v4.3.194) 2004-10-27 Helge Hess * NGImap4: enhanced NGImap4EnvelopeAddress (v4.3.193) * NGMail: support special sendmail location on MacOSX (v4.3.192) * NGMail: fixed a bug in NGSendMail (v4.3.191) * NGMail: added NGSendMail object (v4.3.190) 2004-10-08 Helge Hess * NGImap4: minor improvement in an error condition (v4.3.189) 2004-10-06 Helge Hess * NGMime: added special case for +0530 timezone (v4.3.188) 2004-10-02 Helge Hess * v4.3.187 * NGMime, NGMail: minor cleanups * NGImap4: decode quoted printable subjects and addresses * NGImap4: fixed long subject envelope processing (v4.3.186) * NGImap4: improved processing of envelope responses (v4.3.185) 2004-10-01 Helge Hess * NGImap4: added processing of envelope responses (v4.3.184) * NGImap4: NGImap4Client improvements (v4.3.183) 2004-09-30 Helge Hess * NGMime: fixed OGo buf #936 (v4.3.182) 2004-09-29 Helge Hess * NGImap4: minor improvements (v4.3.181) 2004-09-21 Marcus Mueller * sope-mime.xcode: fixes 2004-09-07 Helge Hess * NGImap4: removed some crash situations wrt OGo bug #883 (v4.3.179) 2004-09-05 Helge Hess * fixed common.h files not to depend on libFoundation internals (v4.3.178) 2004-09-01 Helge Hess * fhs.make (move-headers-to-fhs): moved NGMail and NGImap4 headers to FHS root (v4.3.177) 2004-08-29 Helge Hess * added hack to install the project in FHS locations - the library, its headers, the tools and the resources will be installed in FHS_INSTALL_ROOT if specified (eg make FHS_INSTALL_ROOT=/usr/local) (v4.3.175) * added ChangeLog for libNGMime SOPE/sope-mime/fhs.make0000644000000000000000000000224415004363604013637 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) FHS_INCLUDE_DIR=$(FHS_INSTALL_ROOT)/include/ FHS_BIN_DIR=$(FHS_INSTALL_ROOT)/bin/ ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib64/ else FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib/ endif NONFHS_LIBDIR="$(GNUSTEP_LIBRARIES)/$(GNUSTEP_TARGET_LDIR)/" NONFHS_LIBNAME="$(LIBRARY_NAME)$(LIBRARY_NAME_SUFFIX)$(SHARED_LIBEXT)" fhs-header-dirs :: $(MKDIRS) $(FHS_INCLUDE_DIR)$(libNGMime_HEADER_FILES_INSTALL_DIR) $(MKDIRS) $(FHS_INCLUDE_DIR)/NGImap4 $(MKDIRS) $(FHS_INCLUDE_DIR)/NGMail move-headers-to-fhs :: fhs-header-dirs @echo "moving headers to $(FHS_INCLUDE_DIR) .." mv $(GNUSTEP_HEADERS)$(libNGMime_HEADER_FILES_INSTALL_DIR)/*.h \ $(FHS_INCLUDE_DIR)$(libNGMime_HEADER_FILES_INSTALL_DIR)/ mv $(GNUSTEP_HEADERS)/NGImap4/*.h $(FHS_INCLUDE_DIR)/NGImap4/ mv $(GNUSTEP_HEADERS)/NGMail/*.h $(FHS_INCLUDE_DIR)/NGMail/ move-libs-to-fhs :: @echo "moving libs to $(FHS_LIB_DIR) .." mv $(NONFHS_LIBDIR)/$(NONFHS_LIBNAME)* $(FHS_LIB_DIR)/ move-to-fhs :: move-headers-to-fhs move-libs-to-fhs after-install :: move-to-fhs endif SOPE/sope-mime/Version0000644000000000000000000000024015004363604013562 0ustar rootroot# version file MAJOR_VERSION:=4 MINOR_VERSION:=9 SUBMINOR_VERSION:=3 # v4.5.214 requires libNGExtensions v4.5.146 # v4.2.149 requires libNGStreams v4.2.34 SOPE/sope-mime/NGImap4/0000755000000000000000000000000015004363604013415 5ustar rootrootSOPE/sope-mime/NGImap4/NGImap4Message.h0000644000000000000000000000530515004363604016275 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __Database_NGImap4_NGImap4Message_H__ #define __Database_NGImap4_NGImap4Message_H__ #import #include #include @class NSArray, NSMutableDictionary; @class EOGlobalID; @class NGHashMap; @class NGImap4Context, NGImap4Folder, NGImap4FolderMailRegistry; @interface NGImap4Message : NSObject { @protected NGHashMap *headers; unsigned uid; int size; NSArray *flags; id message; id bodyStructure; NSData *rawData; NGImap4Context *context; NGImap4Folder *folder; // not retained NGImap4FolderMailRegistry *mailRegistry; NSURL *url; EOGlobalID *globalID; NSMutableDictionary *bodyStructureContent; NSString *removeFlagNotificationName; NSString *addFlagNotificationName; int isRead; } - (id)initWithUid:(unsigned)_uid folder:(NGImap4Folder *)_folder context:(NGImap4Context *)_ctx; - (id)initWithUid:(unsigned)_uid headers:(NGHashMap *)_header size:(unsigned)_size flags:(NSArray *)_flags folder:(NGImap4Folder *)_folder context:(NGImap4Context *)_ctx; /* accessors */ - (NSException *)lastException; - (void)resetLastException; - (NGHashMap *)headers; - (int)size; - (unsigned)uid; - (NSArray *)flags; - (NSData *)contentsOfPart:(NSString *)_part; - (id)bodyStructure; - (id)message; - (NSData *)rawData; - (NGImap4Folder *)folder; - (NGImap4Context *)context; - (NSURL *)url; - (EOGlobalID *)globalID; /* flag processing */ - (void)addFlag:(NSString *)_flag; - (void)removeFlag:(NSString *)_flag; - (BOOL)isRead; - (void)markRead; - (void)markUnread; - (BOOL)isFlagged; - (void)markFlagged; - (void)markUnFlagged; - (BOOL)isAnswered; - (void)markAnswered; - (void)markNotAnswered; /* equality */ - (BOOL)isEqual:(id)_obj; - (BOOL)isEqualToNGImap4Message:(NGImap4Message *)_messages; @end #endif /* __Database_NGImap4_NGImap4Message_H__ */ SOPE/sope-mime/NGImap4/NGImap4FolderFlags.m0000644000000000000000000000503415004363604017105 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4FolderFlags.h" #include "imCommon.h" @implementation NGImap4FolderFlags - (id)initWithFlagArray:(NSArray *)_array { if ((self = [super init])) { self->flags = [_array copy]; // TODO: this is pretty weird self->listFlags.noselect = [self->flags containsObject:@"noselect"]; self->listFlags.noinferiors = [self->flags containsObject:@"noinferiors"]; self->listFlags.nonexistent = [self->flags containsObject:@"nonexistent"]; self->listFlags.haschildren = [self->flags containsObject:@"haschildren"]; self->listFlags.marked = [self->flags containsObject:@"marked"]; self->listFlags.unmarked = [self->flags containsObject:@"unmarked"]; self->listFlags.hasnochildren = [self->flags containsObject:@"hasnochildren"]; } return self; } - (id)init { return [self initWithFlagArray:nil]; } - (void)dealloc { [self->flags release]; [super dealloc]; } /* accessors */ - (NSArray *)flagArray { return self->flags; } - (BOOL)doNotSelectFolder { return self->listFlags.noselect ? YES : NO; } - (BOOL)doesNotSupportSubfolders { return self->listFlags.noinferiors ? YES : NO; } - (BOOL)doesNotExist { return self->listFlags.nonexistent ? YES : NO; } - (BOOL)hasSubfolders { return self->listFlags.haschildren ? YES : NO; } - (BOOL)hasNoSubfolders { return self->listFlags.hasnochildren ? YES : NO; } - (BOOL)isMarked { return self->listFlags.marked ? YES : NO; } - (BOOL)isUnmarked { return self->listFlags.unmarked ? YES : NO; } /* operations */ - (void)allowFolderSelect { NSMutableArray *ma; NSArray *tmp; self->listFlags.noselect = NO; tmp = self->flags; ma = [tmp mutableCopy]; [ma removeObject:@"noselect"]; self->flags = [ma copy]; [tmp release]; } @end /* NGImap4FolderFlags */ SOPE/sope-mime/NGImap4/EOQualifier+IMAPAdditions.m0000644000000000000000000003443115004363604020326 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "imCommon.h" @interface EOQualifier(PrivateMethodes) - (NSString *)qualifierDescription; - (NSException *)invalidImap4SearchQualifier:(NSString *)_reason; - (NSException *)appendToImap4SearchString:(NSMutableString *)_search insertNot:(BOOL)_insertNot; - (NSException *)appendToImap4SearchString:(NSMutableString *)_search; - (id)imap4SearchString; @end @implementation EOQualifier(IMAPAdditions) static NSDictionary *dateLocale = nil; static void initDateLocale() { NSArray *shortMonthNames; shortMonthNames = [NSArray arrayWithObjects: @"Jan", @"Feb", @"Mar", @"Apr", @"May", @"Jun", @"Jul", @"Aug", @"Sep", @"Oct", @"Nov", @"Dec", nil]; dateLocale = [NSDictionary dictionaryWithObject: shortMonthNames forKey: @"NSShortMonthNameArray"]; [dateLocale retain]; } - (BOOL)isImap4UnseenQualifier { /* a special key/value qualifier */ return NO; } /* building search qualifiers */ static NSArray *FlagKeyWords = nil; static NSArray *OtherKeyWords = nil; static BOOL debugOn = NO; static void _initImap4SearchCategory(void) { NSUserDefaults *ud; if (FlagKeyWords) return; ud = [NSUserDefaults standardUserDefaults]; FlagKeyWords = [[NSArray alloc] initWithObjects: @"ANSWERED", @"DELETED", @"DRAFT", @"FLAGGED", @"NEW", @"OLD", @"RECENT", @"SEEN", @"UNANSWERED", @"UNDELETED", @"UNDRAFT", @"UNFLAGGED", @"UNSEEN", nil]; OtherKeyWords = [[NSArray alloc] initWithObjects: @"ALL", @"BCC", @"BODY", @"CC", @"FROM", @"SUBJECT", @"TEXT", @"TO", @"KEYWORD", @"UID", @"UNKEYWORD", @"SIZE", @"DATE", nil]; debugOn = [ud boolForKey:@"ImapDebugQualifierGeneration"]; } - (NSException *)invalidImap4SearchQualifier:(NSString *)_reason { if (_reason == nil) _reason = @"unknown reason"; return [NSException exceptionWithName:@"NGImap4SearchQualifierException" reason:_reason userInfo:nil]; } - (BOOL)isImap4NotQualifier { return NO; } - (BOOL)isImap4KeyValueQualifier { return NO; } - (NSException *)appendToImap4SearchString:(NSMutableString *)_search insertNot:(BOOL)_insertNot { return [self invalidImap4SearchQualifier:@"expected key/value qualifier"]; } - (NSException *)appendToImap4SearchString:(NSMutableString *)_search { return [self appendToImap4SearchString:_search insertNot:NO]; } - (id)imap4SearchString { /* returns exception on fail */ [self logWithFormat:@"ERROR(%s): subclass %@ must overide this method!", __PRETTY_FUNCTION__, [self class]]; return nil; } @end /* EOQualifier(IMAPAdditions) */ @implementation EOAndQualifier(IMAPAdditions) - (NSException *)appendToImap4SearchString:(NSMutableString *)_search { NSArray *quals; unsigned i, lCount; quals = [self qualifiers]; if ((lCount = [quals count]) == 0) /* no subqualifiers */ return nil; if (lCount == 1) { // TODO: use appendToImap4SearchString? [_search appendString:[[quals objectAtIndex:0] imap4SearchString]]; return nil; } [_search appendString: @"("]; for (i = 0; i < lCount; i++) { EOQualifier *qualifier; NSException *error; qualifier = [quals objectAtIndex:i]; if (debugOn) [self logWithFormat:@" append subqualifier: %@", qualifier]; if (i > 0) [_search appendString: @" "]; if ((error = [qualifier appendToImap4SearchString:_search])) return error; } [_search appendString: @")"]; return nil /* no error */; } - (id)imap4SearchString { /* returns exception on fail */ NSMutableString *search; NSException *error; unsigned lCount; _initImap4SearchCategory(); if (debugOn) { [self logWithFormat: @"generate IMAP4 expression for AND qualifier: %@", self]; } if ((lCount = [[self qualifiers] count]) == 0) /* no subqualifiers */ return nil; if (lCount == 1) { NSString *uniqueSearch = [[[self qualifiers] objectAtIndex:0] imap4SearchString]; if (debugOn) [self logWithFormat:@" generated: '%@'", uniqueSearch]; return uniqueSearch; } search = [NSMutableString stringWithCapacity:lCount * 3]; if ((error = [self appendToImap4SearchString:search]) != nil) { if (debugOn) [self logWithFormat:@" error: %@", error]; return error; } if (debugOn) [self logWithFormat:@" generated: '%@'", search]; return search; } @end /* EOAndQualifier(IMAPAdditions) */ @implementation EOOrQualifier(IMAPAdditions) - (NSException *)appendToImap4SearchString:(NSMutableString *)_search { // TODO: move generation to this method id s; s = [self imap4SearchString]; if ([s isKindOfClass:[NSException class]]) return s; [_search appendString:s]; return nil; } - (id)imap4SearchString { /* returns exception on fail */ NSArray *quals; NSMutableString *search; unsigned i, lCount; NSException *error; _initImap4SearchCategory(); if (debugOn) { [self logWithFormat: @"generate IMAP4 expression for or-qualifier: %@", self]; } quals = [self qualifiers]; if ((lCount = [quals count]) == 0) /* no subqualifiers */ return nil; if (lCount == 1) return [[quals objectAtIndex:0] imap4SearchString]; search = [NSMutableString stringWithCapacity:lCount * 32]; /* Note: or queries are specified as: OR so we need to wrap more ORs in multiple "OR" IMAP4 expressions eg: "OR (OR (subject "abc") (subject "nbc")) from "duck"" */ if ((error = [[quals objectAtIndex:0] appendToImap4SearchString:search])) return error; for (i = 1; i < lCount; i++) { EOQualifier *qualifier; qualifier = [quals objectAtIndex:i]; [search insertString:@"OR (" atIndex:0]; [search appendString:@") ("]; if ((error = [qualifier appendToImap4SearchString:search])) return error; [search appendString:@")"]; } if (debugOn) [self logWithFormat:@" generated: '%@'", search]; return search; } @end /* EOOrQualifier(IMAPAdditions) */ @implementation EOKeyValueQualifier(IMAPAdditions) - (BOOL)isImap4KeyValueQualifier { return YES; } - (BOOL)isImap4UnseenQualifier { // TODO: this is rather weird: flags suggests an array value! if (![[self key] isEqualToString:@"flags"]) return NO; return [[self value] isEqualToString:@"unseen"]; } - (NSException *)appendFlagsCheckToImap4SearchString:(NSMutableString *)search insertNot:(BOOL)insertNot { NSEnumerator *enumerator = nil; id lvalue, uvalue; SEL lselector; lvalue = [self value]; lselector = [self selector]; // TODO: add support for <> qualifier? (seen => unseen) if (sel_isEqual(lselector, EOQualifierOperatorEqual)) { lvalue = [NSArray arrayWithObject:lvalue]; } else if (!sel_isEqual(lselector, EOQualifierOperatorContains)) { return [self invalidImap4SearchQualifier: @"unexpected EOKeyValueQualifier selector"]; } if (![lvalue isKindOfClass:[NSArray class]]) { return [self invalidImap4SearchQualifier: @"expected an array in contains-qualifier"]; } enumerator = [lvalue objectEnumerator]; while ((lvalue = [enumerator nextObject]) != nil) { uvalue = [lvalue uppercaseString]; if (insertNot) [search appendString:@"NOT "]; if ([FlagKeyWords containsObject:uvalue]) [search appendString:uvalue]; else [search appendFormat: @"KEYWORD %@", lvalue]; } return nil; } - (NSString *)imap4OperatorForDateKeyword:(NSString *)dkey andComparisonSelector:(SEL)lselector { NSString *operatorPrefix, *dateOperator, *imap4Operator; if (sel_isEqual(lselector, EOQualifierOperatorEqual)) dateOperator = @"ON"; else if (sel_isEqual(lselector, EOQualifierOperatorGreaterThan) || sel_isEqual(lselector, EOQualifierOperatorGreaterThanOrEqualTo)) dateOperator = @"SINCE"; else if (sel_isEqual(lselector, EOQualifierOperatorLessThan) || sel_isEqual(lselector, EOQualifierOperatorLessThanOrEqualTo)) dateOperator = @"BEFORE"; else dateOperator = nil; if (dateOperator) { if ([dkey isEqualToString: @"SENT-DATE"]) operatorPrefix = @"SENT"; else operatorPrefix = @""; imap4Operator = [NSString stringWithFormat: @"%@%@ ", operatorPrefix, dateOperator]; } else imap4Operator = nil; return imap4Operator; } - (NSException *)appendToImap4SearchString:(NSMutableString *)search insertNot:(BOOL)insertNot { // TODO: this needs to get reworked /* returns exception on fail */ NSString *lkey; id lvalue; SEL lselector; lkey = [[self key] uppercaseString]; lvalue = [self value]; lselector = [self selector]; if ([lkey isEqualToString:@"FLAGS"]) { /* NOTE: special "not" processing! */ return [self appendFlagsCheckToImap4SearchString:search insertNot:insertNot]; } /* not a flag */ if (insertNot) [search appendString:@"NOT "]; if ([lkey isEqualToString:@"DATE"] || [lkey isEqualToString:@"RECEIVE-DATE"] || [lkey isEqualToString:@"SENT-DATE"]) { NSString *s; if (![lvalue isKindOfClass:[NSCalendarDate class]]) { return [self invalidImap4SearchQualifier: @"expected a NSDate as value"]; } if ((s = [self imap4OperatorForDateKeyword:lkey andComparisonSelector:lselector]) == nil) return [self invalidImap4SearchQualifier:@"unexpected selector"]; [search appendString:s]; // TODO: much faster without descriptionWithCalendarFormat:?! if (!dateLocale) initDateLocale(); s = [lvalue descriptionWithCalendarFormat:@"\"%d-%b-%Y\"" locale:dateLocale]; [search appendString:s]; return nil; } if ([lkey isEqualToString:@"UID"]) { if (!sel_isEqual(lselector, EOQualifierOperatorEqual)) { return [self invalidImap4SearchQualifier:@"unexpected qualifier 2"]; } [search appendString:@"UID "]; [search appendString:[lvalue stringValue]]; return nil; } if ([lkey isEqualToString:@"MODSEQ"]) { if (!sel_isEqual(lselector, EOQualifierOperatorGreaterThanOrEqualTo)) { return [self invalidImap4SearchQualifier:@"'MODSEQ' can only take 'EOQualifierOperatorGreaterThanOrEqualTo' as qualifier operator"]; } [search appendString:@"MODSEQ "]; [search appendString:[lvalue stringValue]]; return nil; } if ([lkey isEqualToString:@"SIZE"]) { if (sel_isEqual(lselector, EOQualifierOperatorGreaterThan) || sel_isEqual(lselector, EOQualifierOperatorGreaterThanOrEqualTo)) [search appendString:@"LARGER "]; else if (sel_isEqual(lselector, EOQualifierOperatorLessThan) || sel_isEqual(lselector, EOQualifierOperatorLessThanOrEqualTo)) [search appendString:@"SMALLER "]; else return [self invalidImap4SearchQualifier:@"unexpected qualifier 3"]; [search appendString:[lvalue stringValue]]; return nil; } if ([OtherKeyWords containsObject:lkey]) { // TODO: actually most keywords only allow for contains! Eg "subject abc" // is a contains query, not an equal query! /* RFC 3501: In all search keys that use strings, a message matches the key if the string is a substring of the field. The matching is case-insensitive. Would be: "a caseInsensitiveLike: '*ABC*'" */ if (!sel_isEqual(lselector, EOQualifierOperatorEqual) && !sel_isEqual(lselector, EOQualifierOperatorCaseInsensitiveLike) && !sel_isEqual(lselector, EOQualifierOperatorContains)) { [self logWithFormat:@"IMAP4 generation: got: %@, allowed: %@", NSStringFromSelector(lselector), NSStringFromSelector(EOQualifierOperatorEqual)]; return [self invalidImap4SearchQualifier: @"unexpected qualifier, disallowed comparison on " @"OtherKeyWords)"]; } [search appendString:lkey]; [search appendString:@" \""]; [search appendString:[lvalue stringValue]]; [search appendString:@"\""]; return nil; } if (!sel_isEqual(lselector, EOQualifierOperatorEqual) && !sel_isEqual(lselector, EOQualifierOperatorCaseInsensitiveLike)) return [self invalidImap4SearchQualifier:@"unexpected qualifier 5"]; [search appendString:@"HEADER "]; [search appendString:lkey]; [search appendString:@" \""]; [search appendString:[lvalue stringValue]]; [search appendString:@"\""]; return nil; } - (id)imap4SearchString { /* returns exception on fail */ NSMutableString *search; NSException *error; _initImap4SearchCategory(); if ([self isImap4UnseenQualifier]) { if (debugOn) [self logWithFormat:@"is unseen: %@ (%@)", self, [self class]]; return @"unseen"; } search = [NSMutableString stringWithCapacity:256]; if ((error = [self appendToImap4SearchString:search])) return error; return search; } @end /* EOKeyValueQualifier(IMAPAdditions) */ @implementation EONotQualifier(IMAPAdditions) - (BOOL)isImap4NotQualifier { return YES; } - (NSException *)appendToImap4SearchString:(NSMutableString *)_search { /* TODO: we do this because the key/value qualifier can generate multiple queries */ return [[self qualifier] appendToImap4SearchString:_search insertNot:YES]; } - (id)imap4SearchString { /* returns exception on fail */ NSMutableString *search; NSException *error; _initImap4SearchCategory(); search = [NSMutableString stringWithCapacity:256]; if ((error = [self appendToImap4SearchString:search])) return error; return search; } @end /* EONotQualifier(IMAPAdditions) */ SOPE/sope-mime/NGImap4/NGImap4Functions.h0000644000000000000000000000441715004363604016664 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGImap4_NGImap4Functions_H__ #define __NGMime_NGImap4_NGImap4Functions_H__ #import #include @class NSString, NSException; @interface NGImap4FolderHandler : NSObject + (id)sharedImap4FolderHandler; - (NGImap4Folder *)subfolderWithName:(NSString *)_name parentFolder:(id)_parent ignoreCase:(BOOL)_caseIns; - (BOOL)isFolder:(id)_child aSubfolderOf:(id)_parent; - (NSException *)createSubfolderWithName:(NSString *)_name parentFolder:(id)_parent append:(BOOL)_append; @end NGImap4Folder *_subFolderWithName(id self, NSString *_name, BOOL _caseIns); BOOL _checkResult(NGImap4Context *_ctx, NSDictionary *_dict, const char *_command); BOOL _isSubFolder(id self, id_folder); BOOL _hasNewMessagesInSubFolder(id self, BOOL _fetch); BOOL _hasUnseenMessagesInSubFolder(id self, BOOL _fetch); BOOL _deleteSubFolder(id self, NGImap4Folder *_folder); BOOL _copySubFolder(id self, id _f, id _toFolder); BOOL _moveSubFolder(id self, NGImap4Folder *_f, id_folder); BOOL _createSubFolderWithName(id self, NSString *_name, BOOL _app); NSString *SaneFolderName(NSString *folderName); #endif /* __NGMime_NGImap4_NGImap4Functions_H__ */ SOPE/sope-mime/NGImap4/NGImap4FolderGlobalID.h0000644000000000000000000000264015004363604017461 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGImap4_NGImap4FolderGlobalID_H__ #define __NGImap4_NGImap4FolderGlobalID_H__ #include @interface NGImap4FolderGlobalID : EOGlobalID < NSCopying > { EOGlobalID *serverGlobalID; NSString *absoluteName; } + (id)imap4FolderGlobalIDWithServerGlobalID:(EOGlobalID *)_gid andAbsoluteName:(NSString *)_name; - (id)initWithServerGlobalID:(EOGlobalID *)_gid andAbsoluteName:(NSString *)_name; /* accessors */ - (EOGlobalID *)serverGlobalID; - (NSString *)absoluteName; /* comparison */ - (BOOL)isEqualToImap4FolderGlobalID:(NGImap4FolderGlobalID *)_other; @end #endif /* __NGImap4_NGImap4FolderGlobalID_H__ */ SOPE/sope-mime/NGImap4/NGImap4ServerRoot.h0000644000000000000000000000663315004363604017030 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __Networking_NGImap4_NGImap4ServerRoot_H__ #define __Networking_NGImap4_NGImap4ServerRoot_H__ #import #include #include @class NSArray, NSString, NSMutableArray, NSNumber; @class NGHashMap, NGImap4Context, EOQualifier; @interface NGImap4ServerRoot : NSObject { @private NSString *name; NGImap4Context *context; NSArray *subFolders; BOOL noinferiors; } + (id)serverRootWithContext:(NGImap4Context *)_context; - (id)initServerRootWithContext:(NGImap4Context *)_context; - (NSException *)lastException; - (void)resetLastException; - (BOOL)isEqual:(id)_obj; - (BOOL)isEqualToServerRoot:(NGImap4ServerRoot *)_root; - (NGImap4Context *)context; - (NGImap4Folder *)parentFolder; - (NSString *)name; - (NSString *)absoluteName; - (BOOL)renameTo:(NSString *)_name; - (BOOL)isInTrash; - (NSArray *)messageFlags; - (NSArray *)messages; - (NSArray *)messagesForQualifier:(EOQualifier *)_qualifier; - (NSArray *)messagesForQualifier:(EOQualifier *)_qualifier maxCount:(int)_cnt; - (BOOL)deleteMessages:(NSArray *)_messages; - (BOOL)deleteAllMessages; - (BOOL)moveMessages:(NSArray *)_messages toFolder:(NGImap4Folder *)_folder; - (BOOL)copyMessages:(NSArray *)_messages toFolder:(NGImap4Folder *)_folder; - (BOOL)appendMessage:(NSData *)_msg; - (BOOL)hasNewMessagesSearchRecursiv:(BOOL)_recursiv; - (BOOL)hasNewMessagesSearchRecursiv:(BOOL)_recursiv fetchOnDemand:(BOOL)_fetch; - (BOOL)hasNewMessagesSearchRecursiv:(BOOL)_recursiv fetchOnDemand:(BOOL)_fetch; - (BOOL)hasUnseenMessagesSearchRecursiv:(BOOL)_recursiv; - (BOOL)addFlag:(NSString *)_flag toMessages:(NSArray *)_messages; - (BOOL)removeFlag:(NSString *)_flag fromMessages:(NSArray *)_messages; - (NSArray *)subFolders; - (NGImap4Folder *)subFolderWithName:(NSString *)_name caseInsensitive:(BOOL)_caseIns; - (BOOL)deleteSubFolder:(NGImap4Folder *)_folder; - (BOOL)createSubFolderWithName:(NSString *)_name; - (BOOL)copySubFolder:(NGImap4Folder *)_f to:(NGImap4Folder *)_folder; - (BOOL)moveSubFolder:(NGImap4Folder *)_f to:(NGImap4Folder *)_folder; - (BOOL)isReadOnly; - (BOOL)noselect; - (BOOL)noinferiors; - (BOOL)nonexistent; - (BOOL)haschildren; - (BOOL)marked; - (BOOL)unmarked; - (int)exists; - (int)recent; - (int)unseen; - (BOOL)status; - (void)select; - (void)expunge; - (void)resetFolder; - (void)resetSubFolders; - (void)resetStatus; - (void)resetSync; - (void)bulkFetchHeadersFor:(NSArray *)_array inRange:(NSRange)_aRange; - (void)bulkFetchHeadersFor:(NSArray *)_array inRange:(NSRange)_aRange withAllUnread:(BOOL)_unread; @end #endif /* __Networking_NGImap4_NGImap4ServerRoot_H__ */ SOPE/sope-mime/NGImap4/imCommon.h0000644000000000000000000000263115004363604015346 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGImap4_common_H__ #define __NGImap4_common_H__ #import #if NeXT_Foundation_LIBRARY # import # import #endif #include #include #include #include #include #include @interface NSObject(NGImap4_OSXHacks) - (void)subclassResponsibility:(SEL)_acmd; - (void)notImplemented:(SEL)_acmd; @end @interface NSException (NGImap4_setUserInfo) - (id)setUserInfo:(NSDictionary *)_info; @end #endif /* __NGImap4_common_H__ */ SOPE/sope-mime/NGImap4/GNUmakefile0000644000000000000000000000331315004363604015467 0ustar rootroot# GNUstep makefile include ../../config.make include $(GNUSTEP_MAKEFILES)/common.make include ../Version ifneq ($(frameworks),yes) SUBPROJECT_NAME = NGImap4 else FRAMEWORK_NAME = NGImap4 endif #NGImap4_PCH_FILE = imCommon.h NGImap4_HEADER_FILES_DIR = . NGImap4_HEADER_FILES_INSTALL_DIR = /NGImap4 NGImap4_HEADER_FILES = \ NGImap4ResponseParser.h \ NGImap4Client.h \ NGImap4Support.h \ NGImap4Folder.h \ NGImap4Context.h \ NGImap4Message.h \ NGImap4ServerRoot.h \ NGImap4FileManager.h \ NGImap4.h \ NGImap4DataSource.h \ NSString+Imap4.h \ NGSieveClient.h \ NGImap4Envelope.h \ NGImap4EnvelopeAddress.h \ NGImap4Connection.h \ NGImap4MailboxInfo.h \ NGImap4ConnectionManager.h \ NGImap4_OBJC_FILES = \ NGImap4ResponseParser.m \ NGImap4Client.m \ NGImap4Support.m \ NGImap4.m \ NGImap4Folder.m \ NGImap4Context.m \ NGImap4Message.m \ NGImap4ServerRoot.m \ NGImap4Functions.m \ NGImap4FileManager.m \ NGImap4DataSource.m \ NSString+Imap4.m \ NGSieveClient.m \ EOQualifier+IMAPAdditions.m \ EOSortOrdering+IMAPAdditions.m \ \ NGImap4MessageGlobalID.m \ NGImap4FolderGlobalID.m \ NGImap4ServerGlobalID.m \ NGImap4FolderMailRegistry.m \ NGImap4FolderFlags.m \ NGImap4ResponseNormalizer.m \ NGImap4Envelope.m \ NGImap4EnvelopeAddress.m \ \ NGImap4Connection.m \ NGImap4MailboxInfo.m \ NGImap4ConnectionManager.m \ include GNUmakefile.preamble ifneq ($(FHS_INSTALL_ROOT),) GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include endif ifneq ($(frameworks),yes) include $(GNUSTEP_MAKEFILES)/subproject.make else include $(GNUSTEP_MAKEFILES)/framework.make endif -include GNUmakefile.postamble SOPE/sope-mime/NGImap4/NGImap4ResponseNormalizer.m0000644000000000000000000006145715004363604020571 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4ResponseNormalizer.h" #include "NGImap4Client.h" #include "imCommon.h" @interface NGImap4Client(UsedPrivates) - (NSString *)delimiter; - (NSString *)_imapFolder2Folder:(NSString *)_folder; @end @implementation NGImap4ResponseNormalizer static __inline__ NSArray * _imapFlags2Flags(NGImap4ResponseNormalizer *, NSArray *); static NSDictionary *VersionPrefixDict = nil; static NSNumber *YesNumber = nil; static NSNumber *NoNumber = nil; static Class DictClass = Nil; static Class StrClass = Nil; static int LogImapEnabled = -1; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; static BOOL didInit = NO; if (didInit) return; didInit = YES; YesNumber = [[NSNumber numberWithBool:YES] retain]; NoNumber = [[NSNumber numberWithBool:NO] retain]; DictClass = [NSDictionary class]; StrClass = [NSString class]; LogImapEnabled = [ud boolForKey:@"ImapLogEnabled"]?1:0; /* cyrus - * OK defiant Cyrus IMAP4 v2.0.16 server ready courier - * OK Courier-IMAP ready. Copyright 1998-2002 Double Precision, Inc. See COPYING for distribution information. */ if (VersionPrefixDict == nil) { VersionPrefixDict = [[DictClass alloc] initWithObjectsAndKeys: @"cyrus imap4 v", @"cyrus", @" imap4rev1 ", @"washington", @"courier", @"courier", nil]; } } - (id)initWithClient:(NGImap4Client *)_client { if ((self = [super init])) { self->client = _client; /* non-retained */ } return self; } /* primary */ - (NSMutableDictionary *)normalizeResponse:(NGHashMap *)_map { /* Filter for all responses result : NSNumber (response result) exists : NSNumber (number of exists mails in selected folder recent : NSNumber (number of recent mails in selected folder expunge : NSArray (message sequence number of expunged mails in selected folder) */ NSMutableDictionary *result; id obj; NSDictionary *respRes; if (_map == nil) return (id)[NSMutableDictionary dictionary]; respRes = [[_map objectEnumeratorForKey:@"ResponseResult"] nextObject]; result = [NSMutableDictionary dictionaryWithCapacity:32]; [result setObject:_map forKey:@"RawResponse"]; if ((obj = [_map objectForKey:@"bye"])) { [result setObject:NoNumber forKey:@"result"]; [result setObject:obj forKey:@"reason"]; [self->client closeConnection]; return result; } if ([[respRes objectForKey:@"result"] isEqual:@"ok"]) { [result setObject:YesNumber forKey:@"result"]; } else { id tmp = nil; [result setObject:NoNumber forKey:@"result"]; if ((tmp = [respRes objectForKey:@"description"]) != nil) { [result setObject:tmp forKey:@"reason"]; } return result; } if ((obj = [[_map objectEnumeratorForKey:@"exists"] nextObject]) != nil) { // [result setObject:obj forKey:@"exists"]; } if ((obj = [[_map objectEnumeratorForKey:@"recent"] nextObject]) != nil) { [result setObject:obj forKey:@"recent"]; } if ((obj = [_map objectsForKey:@"expunge"]) != nil) [result setObject:obj forKey:@"expunge"]; return result; } - (NSDictionary *)normalizeSortResponse:(NGHashMap *)_map { /* filter for sort response (search : NSArray (msn)) */ id obj; NSMutableDictionary *result; result = [self normalizeResponse:_map]; if ((obj = [[_map objectEnumeratorForKey:@"sort"] nextObject]) != nil) [result setObject:obj forKey:@"sort"]; return result; } - (NSDictionary *)normalizeCapabilityResponse:(NGHashMap *)_map { /* filter for capability response: capability : NSArray */ id obj; NSMutableDictionary *result; result = [self normalizeResponse:_map]; if ((obj = [[_map objectEnumeratorForKey:@"capability"] nextObject])) [result setObject:obj forKey:@"capability"]; return result; } - (NSArray *)_normalizeNamespace:(NSArray *)_namespace { NSMutableArray *result; NSDictionary *currentNS; NSMutableDictionary *newNS; NSString *newPrefix; int count, max; max = [_namespace count]; result = [NSMutableArray arrayWithCapacity: max]; for (count = 0; count < max; count++) { currentNS = [_namespace objectAtIndex: count]; newNS = [currentNS mutableCopy]; newPrefix = [self->client _imapFolder2Folder: [currentNS objectForKey: @"prefix"]]; [newNS setObject: newPrefix forKey: @"prefix"]; [result addObject: newNS]; [newNS release]; } return result; } - (NSDictionary *)normalizeNamespaceResponse:(NGHashMap *)_map { NSMutableDictionary *result; NSDictionary *rawResponse; NSArray *namespace; result = [self normalizeResponse:_map]; rawResponse = [result objectForKey: @"RawResponse"]; namespace = [rawResponse objectForKey: @"personal"]; if (namespace) [result setObject: [self _normalizeNamespace: namespace] forKey: @"personal"]; namespace = [rawResponse objectForKey: @"other users"]; if (namespace) [result setObject: [self _normalizeNamespace: namespace] forKey: @"other users"]; namespace = [rawResponse objectForKey: @"shared"]; if (namespace) [result setObject: [self _normalizeNamespace: namespace] forKey: @"shared"]; return result; } - (NSDictionary *)normalizeThreadResponse:(NGHashMap *)_map { /* filter for thread response: thread : NSArray (msn) */ id obj; NSMutableDictionary *result; result = [self normalizeResponse:_map]; if ((obj = [[_map objectEnumeratorForKey:@"thread"] nextObject])) [result setObject:obj forKey:@"thread"]; return result; } - (NSDictionary *)normalizeSearchResponse:(NGHashMap *)_map { /* filter for search response: search : NSArray (msn) */ id obj; NSMutableDictionary *result; result = [self normalizeResponse:_map]; if ((obj = [[_map objectEnumeratorForKey:@"search"] nextObject])) [result setObject:obj forKey:@"search"]; return result; } - (NSDictionary *)normalizeSelectResponse:(NGHashMap *)_map { /* filter for select response flags : NSArray unseen : NSNumber access : NSString ([READ-WRITE], ... ) Eg: 17 select "INBOX" * FLAGS (\Answered \Flagged \Draft \Deleted \Seen) * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen \*)] * OK (seen state failure) Unable to preserve \Seen state: System I/O \ error * 0 EXISTS * 0 RECENT * OK [UIDVALIDITY 1016867500] * OK [UIDNEXT 18948] * OK [NOMODSEQ] Sorry, modsequences have not been enabled on this \ mailbox 17 OK [READ-WRITE] Completed */ NSDictionary *obj; NSEnumerator *enumerator; NSMutableDictionary *result; id flags; result = [self normalizeResponse:_map]; if ((flags = [[_map objectEnumeratorForKey:@"flags"] nextObject]) != nil) [result setObject:_imapFlags2Flags(self, flags) forKey:@"flags"]; // TODO: document the contents of this dictionary enumerator = [_map objectEnumeratorForKey:@"ok"]; while ((obj = [enumerator nextObject]) != nil) { id o; if ([obj isKindOfClass:DictClass]) { if ((o = [obj objectForKey:@"unseen"])) [result setObject:o forKey:@"unseen"]; else if ((o = [obj objectForKey:@"HIGHESTMODSEQ"])) [result setObject:o forKey:@"highestmodseq"]; else if ((o = [obj objectForKey:@"UIDNEXT"])) [result setObject:o forKey:@"uidnext"]; else if ((o = [obj objectForKey:@"UIDVALIDITY"])) [result setObject:o forKey:@"uidvalidity"]; } else [self warnWithFormat:@"unexpected OK object: %@", obj]; } enumerator = [_map objectEnumeratorForKey:@"no"]; while ((obj = [enumerator nextObject]) != nil) { id o; // TODO: document this if ([obj isKindOfClass:DictClass]) { if ((o = [obj objectForKey:@"ALERT"]) != nil) [result setObject:o forKey:@"alert"]; } else // TODO: this looks wrong, its not safe that this is the ALERT result? [result setObject:obj forKey:@"alert"]; } obj = [_map objectForKey:@"ResponseResult"]; if ((obj = [obj objectForKey:@"flag"])) [result setObject:obj forKey:@"access"]; return result; } - (NSDictionary *)normalizeStatusResponse:(NGHashMap *)_map { /* filter for status response messages : NSNumber recent : NSNumber unseen : NSNumber */ NSDictionary *obj; NSMutableDictionary *result; id o; result = [self normalizeResponse:_map]; obj = [[_map objectEnumeratorForKey:@"status"] nextObject]; obj = [obj objectForKey:@"flags"]; if ((o = [obj objectForKey:@"messages"]) != nil) [result setObject:o forKey:@"messages"]; if ((o = [obj objectForKey:@"recent"]) != nil) { if ([result objectForKey:@"recent"] == nil) [result setObject:o forKey:@"recent"]; } if ((o = [obj objectForKey:@"unseen"]) != nil) [result setObject:o forKey:@"unseen"]; // support x-guid (dovecot) if ((o = [obj objectForKey:@"x-guid"]) != nil) [result setObject:o forKey:@"x-guid"]; return result; } /* filter for fetch response fetch : NSArray (fetch responses) 'header' - RFC822.HEADER and BODY[HEADER.FIELDS (...)] 'text' - RFC822.TEXT 'size' - SIZE 'flags' - FLAGS 'uid' - UID 'msn' - message sequence number 'message' - RFC822 'body' - (dictionary with bodystructure) This walks over all 'fetch' responses in the map and adds a 'normalized' dictionary for each response to the 'fetch' key of the normalized response dictionary (as retrieved by 'normalizeResponse') */ - (NSDictionary *)normalizeFetchResponsePart:(id)obj { // TODO: shouldn't we use a specific object instead of NSDict for that? NSDictionary *entry; NSEnumerator *keyEnum; NSString *key; NSString *keys[9]; id values[9]; unsigned count; id (*objForKey)(id, SEL, id); /* Process one 'fetch' reponse dictionary, walk over each key of the dict and check for a collection of known response keys. */ count = 0; keyEnum = [obj keyEnumerator]; objForKey = (void *)[obj methodForSelector:@selector(objectForKey:)]; // TODO: this should add some error handling wrt the count? // TODO: this could return multiple values for the same key?! => fix that while (((key = [keyEnum nextObject]) != nil) && (count < 9)) { unsigned klen; unichar c; if ((klen = [key length]) < 3) continue; c = [key characterAtIndex:0]; switch (c) { case 'b': /* Note: we check for _prefix_! eg body[1] is valid too */ if (klen > 17 && [key hasPrefix:@"body[header.fields"]) { keys[count] = @"header"; values[count] = objForKey(obj, @selector(objectForKey:), key); count++; } else if (klen > 3 && [key hasPrefix:@"body"]) { keys[count] = key; values[count] = objForKey(obj, @selector(objectForKey:), key); count++; } break; case 'e': if (klen == 8 && [key isEqualToString:@"envelope"]) { keys[count] = @"envelope"; values[count] = objForKey(obj, @selector(objectForKey:), key); count++; } break; case 'f': if (klen == 5 && [key isEqualToString:@"flags"]) { id rawFlags; rawFlags = objForKey(obj, @selector(objectForKey:), key); keys[count] = @"flags"; values[count] = _imapFlags2Flags(self, rawFlags); count++; } break; case 'm': if (klen == 3 && [key isEqualToString:@"msn"]) { keys[count] = @"msn"; values[count] = objForKey(obj, @selector(objectForKey:), key); count++; } else if (klen == 6 && [key isEqualToString:@"modseq"]) { keys[count] = @"modseq"; values[count] = objForKey(obj, @selector(objectForKey:), key); count++; } break; case 'r': if (klen == 6 && [key isEqualToString:@"rfc822"]) { keys[count] = @"message"; values[count] = objForKey(obj, @selector(objectForKey:), key); count++; } else if (klen == 13 && [key isEqualToString:@"rfc822.header"]) { keys[count] = @"header"; values[count] = objForKey(obj, @selector(objectForKey:), key); count++; } else if (klen == 11 && [key isEqualToString:@"rfc822.text"]) { keys[count] = @"text"; values[count] = objForKey(obj, @selector(objectForKey:), key); count++; } else if (klen == 11 && [key isEqualToString:@"rfc822.size"]) { keys[count] = @"size"; values[count] = objForKey(obj, @selector(objectForKey:), key); count++; } break; case 'u': if (klen == 3 && [key isEqualToString:@"uid"]) { keys[count] = @"uid"; values[count] = objForKey(obj, @selector(objectForKey:), key); count++; } break; case 'v': if ([key isEqualToString:@"vanished"]) { keys[count] = key; values[count] = objForKey(obj, @selector(objectForKey:), key); count++; } break; } } /* create dictionary */ entry = count > 0 ? [[DictClass alloc] initWithObjects:values forKeys:keys count:count] : nil; return entry; /* returns retained object! */ } - (NSDictionary *)normalizeFetchResponse:(NGHashMap *)_map { /* Raw Sample (Courier): C[0x8b4e754]: 27 uid fetch 635 (body) S[0x8c8b4e4]: * 627 FETCH (UID 635 BODY ("text" "plain" ("charset" "iso-8859-1" "format" "flowed") NIL NIL "8bit" 2474 51)) S[0x8c8b4e4]: * 627 FETCH (FLAGS (\Seen)) S[0x8c8b4e4]: 27 OK FETCH completed. - this results in two result records (one for UID and one for FLAGS) TODO: should we coalesce? Raw Sample (Cyrus): C[0x8c8ec64]: 14 uid fetch 20199 (body) S[0x8da46a4]: * 93 FETCH (UID 20199 BODY ((("TEXT" "PLAIN" ("CHARSET" "utf-8") NIL "signed data" "7BIT" 691 17) ("APPLICATION" "PKCS7-SIGNATURE" ("NAME" "smime.p7s") NIL "signature" "BASE64" 2936) "SIGNED") ("TEXT" "PLAIN" ("CHARSET" "us-ascii") NIL NIL "7BIT" 146 4) "MIXED")) S[0x8da46a4]: 14 OK Completed - UID key is mapped to 'uid' - BODY key is mapped to a nested body structure - MSN is added for the '93'? (TODO: make sure this is the case) Sample returns (not for the above code!): { // other message stuff fetch = ( { header = < NSData containing the header >; size = 3314; uid = 20187; msn = 72; flags = ( answered, deleted, seen ); }, ... for each fetch message ... ) } */ NSMutableDictionary *result; id obj; NSEnumerator *enumerator; NSMutableArray *fetchResponseRecords, *fetchResponseVanishedRecords; // TODO: describe what the generic normalize does. // Q: do we need to run this before the following section or can we // call this method just before [result setObject:...] ? (I guess // the latter, because 'result' is not accessed, but who knows // about side effects in this JR cruft :-( ) result = [self normalizeResponse:_map]; fetchResponseRecords = [[NSMutableArray alloc] initWithCapacity:512]; /* walk over each response tag which is keyed by 'fetch' in the hashmap */ enumerator = [_map objectEnumeratorForKey:@"fetch"]; while ((obj = [enumerator nextObject]) != nil) { NSDictionary *entry; if ((entry = [self normalizeFetchResponsePart:obj]) == nil) continue; [fetchResponseRecords addObject:entry]; [entry release]; entry = nil; } /* make response array immutable and add to normalized result */ obj = [fetchResponseRecords copy]; [fetchResponseRecords release]; [result setObject:obj forKey:@"fetch"]; [obj release]; /* walk over each response tag which is keyed by 'vanished' in the hashmap */ fetchResponseVanishedRecords = [[NSMutableArray alloc] initWithCapacity:512]; enumerator = [_map objectEnumeratorForKey:@"vanished"]; while ((obj = [enumerator nextObject]) != nil) { [fetchResponseVanishedRecords addObjectsFromArray:obj]; } /* add response array to normalized result */ [result setObject:fetchResponseVanishedRecords forKey:@"vanished"]; [fetchResponseVanishedRecords release]; return result; } - (NSDictionary *)normalizeQuotaResponse:(NGHashMap *)_map { /* filter for quota responses */ NSMutableDictionary *result, *quotaRoot, *quota, *tmp; id obj; NSEnumerator *enumerator; result = [self normalizeResponse:_map]; quotaRoot = [_map objectForKey:@"quotaRoot"]; quota = [_map objectForKey:@"quota"]; enumerator = [quotaRoot keyEnumerator]; tmp = [NSMutableDictionary dictionaryWithCapacity:[quota count]]; while ((obj = [enumerator nextObject])) { NSString *qRoot; NSDictionary *qDesc; qRoot = [quotaRoot objectForKey:obj]; if (![qRoot isNotEmpty]) { if (LogImapEnabled) { [self logWithFormat:@"%s: missing quotaroot for %@", __PRETTY_FUNCTION__, obj]; } continue; } qDesc = [quota objectForKey:qRoot]; if ([qDesc count] == 0) { if (LogImapEnabled) { [self logWithFormat:@"%s: missing quota description for" @" folder %@ root %@", __PRETTY_FUNCTION__, obj, qRoot]; } continue; } [tmp setObject:qDesc forKey:[self->client _imapFolder2Folder:obj]]; } [result setObject:tmp forKey:@"quotas"]; return result; } /* ** filter for open connection */ - (NSDictionary *)normalizeOpenConnectionResponse:(NGHashMap *)_map { NSMutableDictionary *result; id obj; result = [self normalizeResponse:_map]; obj = [[_map objectEnumeratorForKey:@"ok"] nextObject]; if (obj == nil) { [result setObject:NoNumber forKey:@"result"]; return result; } if ([obj isKindOfClass:DictClass]) obj = [(NSDictionary *)obj objectForKey:@"comment"]; if ([obj isKindOfClass:StrClass]) { NSEnumerator *enumerator; id key; NSString *lowServer; [result setObject:obj forKey:@"server"]; enumerator = [VersionPrefixDict keyEnumerator]; lowServer = [obj lowercaseString]; while ((key = [enumerator nextObject])) { NSString *pref; NSArray *vers; NSRange r; pref = [VersionPrefixDict objectForKey:key]; r = [lowServer rangeOfString:pref]; if (r.length == 0) continue; [result setObject:key forKey:@"serverKind"]; if (![key isEqualToString:@"cyrus"]) continue; /* cyrus server, collect version */ vers = [[lowServer substringFromIndex:(r.location + [pref length])] componentsSeparatedByString:@"."]; if ([vers count] > 2) { NSNumber *n; n = [NSNumber numberWithInt:[[vers objectAtIndex:0] intValue]]; [result setObject:n forKey:@"version"]; n = [NSNumber numberWithInt:[[vers objectAtIndex:1] intValue]]; [result setObject:n forKey:@"subversion"]; n = [NSNumber numberWithInt:[[vers objectAtIndex:2] intValue]]; [result setObject:n forKey:@"tag"]; } break; } } [result setObject:YesNumber forKey:@"result"]; return result; } /* ** filter for list ** list : NSDictionary (folder name as key and flags as value) */ - (NSDictionary *)normalizeListResponse:(NGHashMap *)_map { NSMutableDictionary *result; id obj; NSAutoreleasePool *pool; NSDictionary *rr; pool = [[NSAutoreleasePool alloc] init]; result = [self normalizeResponse:_map]; if ((obj = [_map objectsForKey:@"list"]) != nil) { NSEnumerator *enumerator; NSDictionary *o; NSMutableDictionary *folder; enumerator = [obj objectEnumerator]; folder = [[NSMutableDictionary alloc] init]; while ((o = [enumerator nextObject])) { [folder setObject:_imapFlags2Flags(self, [o objectForKey:@"flags"]) forKey:[self->client _imapFolder2Folder:[o objectForKey:@"folderName"]]]; } [result setObject:folder forKey:@"list"]; [folder release]; } rr = [result retain]; [pool release]; return [rr autorelease]; } - (NSDictionary *)normalizeListStatusResponse:(NGHashMap *)_map { NSMutableDictionary *result; id obj; NSAutoreleasePool *pool; NSDictionary *rr; pool = [[NSAutoreleasePool alloc] init]; result = [self normalizeResponse:_map]; if ((obj = [_map objectsForKey:@"list"]) != nil) { NSEnumerator *enumerator; NSDictionary *o; NSMutableDictionary *folder; enumerator = [obj objectEnumerator]; folder = [[NSMutableDictionary alloc] init]; while ((o = [enumerator nextObject])) { [folder setObject:_imapFlags2Flags(self, [o objectForKey:@"flags"]) forKey:[[self->client _imapFolder2Folder:[o objectForKey:@"folderName"]] substringFromIndex:1]]; } [result setObject:folder forKey:@"list"]; [folder release]; } if ((obj = [_map objectsForKey:@"status"]) != nil) { NSEnumerator *enumerator; NSDictionary *o; NSMutableDictionary *folder; enumerator = [obj objectEnumerator]; folder = [[NSMutableDictionary alloc] init]; while ((o = [enumerator nextObject])) { [folder setObject:[o objectForKey:@"flags"] forKey:[[self->client _imapFolder2Folder:[o objectForKey:@"folderName"]] substringFromIndex:1]]; } [result setObject:folder forKey:@"status"]; [folder release]; } rr = [result retain]; [pool release]; return [rr autorelease]; } /* flags */ static inline NSArray * _imapFlags2Flags(NGImap4ResponseNormalizer *self, NSArray *_flags) { NSEnumerator *enumerator; NSArray *result; id obj, *objs; unsigned cnt; objs = calloc([_flags count] + 2, sizeof(id)); enumerator = [_flags objectEnumerator]; cnt = 0; while ((obj = [enumerator nextObject])) { if ([obj isNotEmpty]) { if ([obj hasPrefix:@"\\"]) objs[cnt] = [obj substringFromIndex:1]; else objs[cnt] = obj; cnt++; } } result = [NSArray arrayWithObjects:objs count:cnt]; if (objs) free(objs); return result; } /* ACL */ - (NSDictionary *)normalizeGetACLResponse:(NGHashMap *)_map { /* Raw Sample (Cyrus): 21 GETACL INBOX * ACL INBOX test.et.di.cete-lyon lrswipcda helge lrwip 21 OK Completed */ NSMutableDictionary *result; id obj; result = [self normalizeResponse:_map]; if ((obj = [[_map objectEnumeratorForKey:@"acl"] nextObject]) != nil) [result setObject:obj forKey:@"acl"]; if ((obj = [[_map objectEnumeratorForKey:@"mailbox"] nextObject]) != nil) [result setObject:obj forKey:@"mailbox"]; return result; } - (NSDictionary *)normalizeListRightsResponse:(NGHashMap *)_map { /* Raw Sample (Cyrus): 16 listrights INBOX anyone * LISTRIGHTS INBOX anyone "" l r s w i p c d a 0 1 2 3 4 5 6 7 8 9 16 OK Completed */ NSMutableDictionary *result; id obj; result = [self normalizeResponse:_map]; if ((obj = [[_map objectEnumeratorForKey:@"listrights"] nextObject])) [result setObject:obj forKey:@"listrights"]; if ((obj = [[_map objectEnumeratorForKey:@"requiredRights"] nextObject])) [result setObject:obj forKey:@"requiredRights"]; if ((obj = [[_map objectEnumeratorForKey:@"mailbox"] nextObject]) != nil) [result setObject:obj forKey:@"mailbox"]; if ((obj = [[_map objectEnumeratorForKey:@"uid"] nextObject]) != nil) [result setObject:obj forKey:@"uid"]; return result; } - (NSDictionary *)normalizeMyRightsResponse:(NGHashMap *)_map { /* Raw Sample (Cyrus): 18 myrights INBOX * MYRIGHTS INBOX lrswipcda 18 OK Completed */ NSMutableDictionary *result; id obj; result = [self normalizeResponse:_map]; if ((obj = [[_map objectEnumeratorForKey:@"myrights"] nextObject]) != nil) [result setObject:obj forKey:@"myrights"]; if ((obj = [[_map objectEnumeratorForKey:@"mailbox"] nextObject]) != nil) [result setObject:obj forKey:@"mailbox"]; return result; } @end /* NGImap4ResponseNormalizer */ SOPE/sope-mime/NGImap4/NGImap4MailboxInfo.h0000644000000000000000000000300715004363604017115 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of OpenGroupware.org. OGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. OGo 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with OGo; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGImap4MailboxInfo_H__ #define __NGImap4MailboxInfo_H__ #import /* NGImap4MailboxInfo Represents the info returned by an IMAP4 select. Use NGImap4Connection to retrieve the data. */ @class NSString, NSDate, NSArray, NSURL, NSDictionary; @interface NGImap4MailboxInfo : NSObject { NSDate *timestamp; NSURL *url; NSString *name; NSArray *allowedFlags; NSString *access; unsigned int recent; } - (id)initWithURL:(NSURL *)_url folderName:(NSString *)_name selectDictionary:(NSDictionary *)_dict; /* accessors */ - (NSDate *)timestamp; - (NSURL *)url; - (NSString *)name; - (NSArray *)allowedFlags; - (NSString *)access; - (unsigned int)recent; @end #endif /* __NGImap4MailboxInfo_H__ */ SOPE/sope-mime/NGImap4/NGImap4ServerGlobalID.h0000644000000000000000000000121515004363604017511 0ustar rootroot #ifndef __NGImap4_NGImap4ServerGlobalID_H__ #define __NGImap4_NGImap4ServerGlobalID_H__ #include @interface NGImap4ServerGlobalID : EOGlobalID < NSCopying > { NSString *hostName; NSString *login; int port; } + (id)imap4ServerGlobalIDForHostname:(NSString *)_host port:(int)_port login:(NSString *)_login; - (id)initWithHostname:(NSString *)_host port:(int)_port login:(NSString *)_login; /* accessors */ - (NSString *)hostName; - (NSString *)login; - (int)port; /* comparison */ - (BOOL)isEqualToImap4ServerGlobalID:(NGImap4ServerGlobalID *)_other; @end #endif /* __NGImap4_NGImap4ServerGlobalID_H__ */ SOPE/sope-mime/NGImap4/ChangeLog0000644000000000000000000013261115004363604015173 0ustar rootroot2011-10-17 Francis Lachapelle * NGImap4Connection.m (-addFlags:toAllMessagesInURL:): instead of fetching all the sequence numbers and storing the deleted flag on the returned list, we specify a range that covers all messages (1:*). 2011-07-28 Wolfgang Sourdeau * NGImap4Client.m (-fetchVanished:): new method to retrieve vanished uids. 2011-07-27 Wolfgang Sourdeau * NGImap4ResponseParser.m (_parseSortResponseIntoHashMap:): handle the "MODSEQ" element from the response, if present. 2011-07-25 Wolfgang Sourdeau * NGImap4Connection.m (-enableExtension:): new method to issue a "ENABLE [extension]" command. * NGImap4ResponseParser.m (_parseNumberUntaggedResponse:): added support for "MODSEQ" attribute. * NGImap4ResponseNormalizer.m (-normalizeFetchResponsePart:): added support for "MODSEQ" attribute. * EOSortOrdering+IMAPAdditions.m (-_setupAllowedIMAP4SortKeys): allow "MODSEQ" as sort keyword. * EOQualifier+IMAPAdditions.m (-[EOKeyValueQualifier appendToImap4SearchString:insertNot:]) added support for "MODSEQ". * NGImap4Client.m (-enable:): new method enabling IMAP extensions following rfc5161. 2011-06-01 Francis Lachapelle * NGImap4Client.m (-threadBySubject:charset:qualifier:): verify IMAP server capabilities with respect to threading. Return nil if threading is not supported. * NGImap4Connection.m (-fetchThreadedUIDsInURL:qualifier:sortOrdering:): new method that returns a threaded and sorted representation of an IMAP folder. 2010-08-09 Wolfgang Sourdeau * NGImap4Client.m (-append:toFolder:withFlags:): convert the string to an ISO 8859-1 instance rather than UTF-8, since the latter could fail with an ISO content. 2010-04-07 Wolfgang Sourdeau * NGImap4Client.m (-list:pattern:, -lsub:pattern:): use an empty prefix and put the used prefix in the "pattern" component of the LIST or LSUB command, as this work around bugs in bad server implementations. 2010-04-02 Wolfgang Sourdeau * NGSieveClient.m (-putScript:script:): (-setActiveScript:, -deleteScript:): do not append an ending "\r\n" since sendCommand:logText: does it for us. (-setActiveScript:): we accept an empty non-nil script name as argument in order to deactivate the currently active script. 2010-03-11 Wolfgang Sourdeau * NGImap4ResponseParser.m (_parseContentSieveResponse): we now use NSUTF8StringEncoding as explicit NSString encoding for sieve responses. (_parseDataSieveResponse): same as above. (_parseOkSieveResponse): added a _parseUntil(.."\n") clause to ensure that the current line has been completely parsed before going on with the rest. (_parseNoSieveResponse): same as above. 2010-03-03 Wolfgang Sourdeau * NGSieveClient.m (-putScript:script:): the byte count passed as parameter to the server must correspond to an UTF-8 encoded string. 2010-02-19 Wolfgang Sourdeau * NGImap4ResponseParser.m (_parseACLResponseIntoHashMap:): user ids enclosed in quotes are extracted from them, for servers not following the standards properly. 2010-02-18 Wolfgang Sourdeau * NGImap4ResponseParser.m (-parseResponseForTagId:exception:): the unsigned "l0" was never compared with "-1". Therefore we cast "-1" as an unsigned char to let the error check happen. 2010-01-28 Wolfgang Sourdeau * NGImap4Client.m (-processCommand:withTag:withNotification:): don't retry the command if it was a login command. 2010-01-25 Wolfgang Sourdeau * NGImap4Client.m (-append:toFolder:withFlags:): we use the count found in cntNew to avoid a crash with GNUstep's cStringLength. * NGImap4ResponseParser.m (-parseResponseForTagId:exception:): detect "-1" return code from _la and leave the loop with a proper execption when it occurs. 2010-01-15 Wolfgang Sourdeau * NGImap4Connection.m (-doesMailboxExistAtURL:): sometimes an entry is present in the subfolders cache. When it is the case, the method was returning at the end of the first iteration even though the mailbox was never found. We need to continue and then proceed to the "status" check whether the cache is populated or not. 2010-01-14 Wolfgang Sourdeau * NGImap4Connection.m (-doesMailboxExistAtURL:): mailbox paths can start with '/' on non-Apple platforms. (-flushFolderHierarchyCache): reassign a new dictionary to self->subfolders to avoid disappearing folders. 2010-01-05 Wolfgang Sourdeau * NGImap4ResponseParser.m (_parseUntaggedResponse): now accepts the "NAMESPACE" response and parse accordingly by making use of the appropriate new method. * NGImap4ResponseNormalizer.m (-normalizeNamespaceResponse): self-explicit new method. * NGImap4Connection.m (-subfolderForURL:, -allFoldersForURL:): differenciate both methods by having "subfolder..." use the "%" wild card and "allFolders" the "*" wildcard. (-cachedHierarchyResultsForURL): now accepts a url parameter so in order to maintain multiple caches depending on the queried namespace. (SOGoMailGetDirectChildren): if the array count is < 2, we must not return since certain implementations may not return the current folder. * NGImap4Client.m (-namespace): new method implementing the "NAMESPACE" command. (-lsub:pattern:): we now sanitize the "prefix" particle of the LSUB command. 2009-11-25 Wolfgang Sourdeau * NSString+Imap4.m (_encodeToModifiedUTF7): handle the case where the leftOver is 0 by "chance" after the first 2 cycles. This can happen when coding characters having a bitmask with 6 zeroes in a row. 2009-10-06 Wolfgang Sourdeau * NGImap4Client.m (-delete:): if the folder we want to delete is the same as self->selectedFolder, we unselect it first to ensure a "SELECT" happens if a new folder with the same name is created. * EOQualifier+IMAPAdditions.m (-imap4OperatorForDateKeyword:andComparisonSelector:): modified operator handler to handle "receive-date" search key as well as "date", prefixing the real filter with "sent" or not. 2009-09-22 Wolfgang Sourdeau * NGImap4Client.m (_sopeSORT:qualifier:encoding:): added support for sorting by message size. 2009-07-01 Wolfgang Sourdeau * NGImap4Connection.m (-initWithClient:password:): we need to copy the imap4Separator, otherwise it will be released when the connection is deallocated. 2009-06-15 Wolfgang Sourdeau * NSString+Imap4.m (-stringByEncodingImap4FolderName, -stringByDecodingImap4FolderName): reimplemented the original methods in a unicode-safe way, thereby simplifying the code at the same time. * NGImap4Functions.m (SaneFolderName): new function designed to sanitize folder names prior to using them in IMAP commands. 2008-10-23 Wolfgang Sourdeau * NGImap4Client.m ([NGImap -sort:qualifier:encoding:]): message without date that are sorted on servers which do not have the SORT capability are now given the current date as a work-around. 2008-09-22 Wolfgang Sourdeau * NGImap4Connection.m ([NGImap -doesMailboxExistAtURL:]): restore the previously selected folder state. 2008-09-19 Wolfgang Sourdeau * NGImap4Client.m ([NGImap -select:]): simplified method by removing the need for storing the previous folder before releasing it. This strangely seems to fix a crash with gnustep 1.14. 2008-09-01 Ludovic Marcotte * NGImap4ConnectionManager.m: implemented _garbageCollect. 2008-08-28 Wolfgang Sourdeau * NGImap4Client.m ([NGImap -unselect]): new method to send "UNSELECT" to the imap server. 2007-08-24 Wolfgang Sourdeau * NGImap4Connection.m: some fix for folders ending with a slash (OGo bug #1905) 2007-08-16 Wolfgang Sourdeau * NGImap4Client.m: added support for non-system IMAP4 flags (eg $Forwarded) (fixes OGo bug #1899) 2007-08-14 Helge Hess * NGImap4Connection.m: fixed some issue with gnustep-base and the first char of a subfolder name (fixes OGo bug #1893) 2007-08-01 Wolfgang Sourdeau * NGImap4ResponseParser.m: added support for bodystructure fetches (fixes OGo bug #1892) 2007-07-15 Helge Hess * NSString+Imap4.m: changed code to use -initWithData: as suggested in bug report (OGo bug #1885). Note that the methods still support Latin1 only and should be changed to decode/encode unichar buffers 2007-05-28 Helge Hess * NGImap4ResponseNormalizer.m: changed not to throw an exception in the situation described in OGo bug 1875 2007-02-12 Helge Hess * NGImap4Functions.m, NGSieveClient.m: fixed a gstep-base compilation warning 2006-08-03 Wolfgang Sourdeau * NGImap4Connection.m: check for \noinferiors flags when traversing subfolders 2005-12-13 Helge Hess * NGImap4ResponseParser.m: properly decode quoted-printable headers when the QP marker starts somewhere inside the header value 2005-07-27 Helge Hess * NGImap4Connection.m: fixed gcc 4.0 warnings 2005-07-26 Helge Hess * NGImap4Connection.m: fixed a Cocoa compatibility issue with -doesMailboxExistAtURL 2005-07-15 Helge Hess * NGImap4ResponseParser.m: fixed a bug in parsing mailbox names in ACL responses 2005-07-14 Helge Hess * NGImap4Connection.m: updated defaults to use NGImap4Connection* names, made the IMAP4 folder separator an ivar, consolidated the fetching of the mailbox hierarchy 2005-07-13 Helge Hess * NGImap4Connection.m: added a -description 2005-07-13 Marcus Mueller * NGImap4.xcodeproj: synced with GNUmakefile 2005-07-11 Helge Hess * added NGImap4Connection/NGImap4ConnectionManager classes, a simpler interface to the IMAP4 client library 2005-07-07 Helge Hess * NGImap4Client.m: added -storeFlags:forMSNs:addOrRemove: method to change flags for a set of MSNs (instead of ranges) 2005-04-24 Helge Hess * fixed gcc 4.0 warnings 2005-03-24 Helge Hess * EOQualifier+IMAPAdditions.m: fixed a warning 2005-03-05 Helge Hess * NGImap4Folder.m: properly create NSURL if the absolute name doesn't start with a slash * NGImap4Context.m: initialize NSURL with a path to avoid an issue on MacOSX 2005-03-03 Helge Hess * NGImap4FileManager.m: added debug logs which can be enabled using the 'NGImap4FileManagerDebugEnabled' default, improved handling of root folder in -fileExists method * NGImap4Context.m: improved -description * NGImap4Functions.m: added some debugging facilities 2005-02-14 Helge Hess * NGSieveClient.m: encode base64 with a large line break to fix OGo bug #1228 2005-02-12 Helge Hess * EOQualifier+IMAPAdditions.m: more reworks in qualifier generation, changed handling of spaces, fixed handling of OR qualifiers * EOQualifier+IMAPAdditions.m: allow contains: qualifier operator for key searches * NGImap4Client.m: moved EOSortOrdering => IMAP4 code to an own category/file * NGImap4Client.m: added -copyUids:toFolder: method to perform set copy operations without sequence numbers (uses UID COPY IMAP4 command) 2005-02-08 Helge Hess * NGImap4Client.m: added -selectedFolderName method to retrieve the folder which was selected last * NGImap4ResponseParser.m: properly parse from/reply-to as lists * NGImap4Envelope.m: properly use NSArray for 'from' and 'reply-to', both can be multi valued (only 'sender' is a single mailbox in RFC 2822, 3.6.2) - Note: might break API! 2005-01-31 Helge Hess * NGImap4Envelope.m, NGImap4EnvelopeAddress.m: added support for bodystructure dictionaries 2005-01-30 Helge Hess * NGImap4ResponseNormalizer.m: code cleanup * NGSieveClient.m: removed a superflous "{" in the script-put call 2005-01-30 Helge Hess * NGImap4Client.m: minor code cleanups 2005-01-04 Helge Hess * NGSieveClient.m: fixed a warning when compiling with Xcode 2004-12-14 Marcus Mueller * NGImap4.xcode: minor fixes and updated 2004-12-03 Helge Hess * NGSieveClient.m: fixed error processing on missing scripts 2004-11-28 Helge Hess * NGSieveClient.m: can init using a URL, prepared some parsing methods, open connection on demand when login:password: is called, added support for -listScripts and -getScript: * NGSieveClient.m: added a buffered stream for raw IO, added proper error handling in some methods, added support for 'NSData commands', properly convert commands to UTF-8 2004-11-19 Helge Hess * NGSieveClient.m, NGImap4Client.m: minor code cleanups 2004-11-16 Helge Hess * NGSieveClient.m: some code cleanups, needs fixes for UTF-8 scripts 2004-11-08 Helge Hess * NGImap4ResponseParser.m(_parseQuotedStringOrNIL): added support for parsing "data" strings (those which begin with {count}) 2004-10-30 Thierry Delhaise * NGImap4ResponseParser.m: fixed OGo bug #958 (consume didn't match SEARCH match in IMAP4 parser) 2004-10-28 Helge Hess * NGImap4Envelope.m: added constructor method: -initWithMessageID:subject:sender:replyTo:to:cc:bcc: 2004-10-27 Helge Hess * NGImap4EnvelopeAddress.m: added -initWithString: method (not properly implemented yet, should parse the string using the NGMailAddressParser) 2004-10-08 Helge Hess * NGImap4ResponseParser.m: added INTERNALDATE as a known, but unsupported fetch key (v4.3.189) 2004-10-04 Marcus Mueller * NGImap4.xcode: added new files to Xcode build 2004-10-02 Helge Hess * NGImap4ResponseParser.m: decode quoted printable in personal names of envelope addresses and in the subject, fixed a memory leak in the envelope parser (v4.3.187) * NGImap4ResponseParser.m: support data-style subjects in envelopes (v4.3.186) * NGImap4ResponseNormalizer.m: pass on envelope raw responses in normalized responses (v4.3.185) 2004-10-01 Helge Hess * NGImap4ResponseParser.m: added support for envelope responses, major code cleanups (v4.3.184) 2004-09-30 Helge Hess * v4.3.183 * NGImap4Folder.m: use new sort API * NGImap4Client.m: deprecated -sort:qualifier: in favor of -sort:qualifier:encoding:, code cleanups 2004-09-29 Helge Hess * NGImap4Client.m: improved -description (v4.3.181) 2004-09-21 Marcus Mueller * imCommon.h: Fixed duplicate interface declarations by renaming them. I believe this was an Xcode only issue. (v4.3.180) 2004-09-07 Helge Hess * NGImap4ResponseParser.m: added some sanity checks for unexpected parsing input, removes crashes as reported in OGo bug #883 (v4.3.179) 2004-08-29 Marcus Mueller * NGImap4.xcode: new Xcode project 2004-08-20 Helge Hess * fixed for SOPE 4.3 structure (v4.3.173) 2004-07-15 Helge Hess * v4.2.169 * NGImap4Client.m, NGImap4Context.m, NGImap4DataSource.m, NGImap4FileManager.m, NGImap4Message.m, NGImap4ResponseParser.m: fixed gcc 3.x warnings * NGImap4ResponseNormalizer.m: fixed some gcc 3.x warnings, fixed normalization (OGo bug #840), bug introduced in v4.2.166 * NGImap4Folder.m: major code cleanups, fixed some gcc 3.x warnings, added debug output if ImapDebugEnabled is on 2004-07-13 Helge Hess * NGImap4Client.m: fixed some compilation issue with older gcc's (v4.2.168) * NGImap4Client.m: minor improvements to exception handling (v4.2.167) * v4.2.166 * NGImap4Message.m(-generateBodyStructure): scan for the response containing the body structure if multiple responses were submitted by the IMAP server (eg Courier), this might fix OGo bug #800 * NGImap4ResponseNormalizer.m: various code cleanups, minor speed improvements in fetch-response normalization * NGImap4Message.m: added more logging to find OGo bug #800 (v4.2.165) 2004-06-21 Helge Hess * NGImap4FolderMailRegistry.m: fixed a warning with gstep-base (v4.2.164) 2004-06-20 Helge Hess * NGImap4/NGImap4Message.m: minor optimization (v4.2.163) 2004-06-14 Helge Hess * NGImap4Client.m, NGImap4ResponseParser.m, NSString+Imap4.m: fixed gcc 3.4 warnings (v4.2.162) 2004-05-16 Helge Hess * NGImap4Context.m, NGImap4FileManager.m, NGImap4Folder.m, NGImap4Message.m, NGImap4ServerRoot.m, NGSieveClient.m: replaced "==YES" comparisons (v4.2.158) 2004-04-02 Helge Hess * v4.2.154 * NGImap4Message.m: remember mail registry in an ivar (increased the class version), this should fix OGo bug #660 * NGImap4Folder.m: some code cleanups 2004-02-17 Helge Hess * v4.2.152 * EOQualifier+IMAPAdditions.m, NGImap4Client.m: minor cleanups * imCommon.h: only define sel_eq on NeXT or APPLE runtime, fixes OGo bug #582 2004-02-10 Helge Hess * NGImap4Client.m, NGImap4FolderMailRegistry.m, NGImap4Functions.m, NGImap4ResponseParser.m, NGSieveClient.m: fixed compilation warnings on OSX (v4.2.151) 2004-01-25 Helge Hess * NGImap4Folder.m: use new NGDataStream API to allow additional optimizations (open data parsing streams in read-only mode) (v4.2.149) 2004-01-24 Helge Hess * v4.2.148 * NGImap4Client.m: cleanups, moved "response normalization" methods to a separate NGImap4ResponseNormalizer object * NGImap4ResponseParser.m (_parseUntaggedResponse): optimized parsing of untagged responses, cache NSNumber class, improved autorelease behaviour (v4.2.147) * NGMimeRFC822DateHeaderFieldParser.m: replaced (expensive) usage of the NSCalendarDate parser with a hackish, but much faster hand written parser. Should give a good performance benefit on large mail folders (looks like ~50ms for 30 mails ) (v4.2.146) 2004-01-22 Helge Hess * v4.2.145 * NGImap4FolderMailRegistry.m: implemented new "flat-array" notification center for mail flag coordination. Quite fast with observer inserts/removes. Hopefully this doesn't break anything, but apparently it works just fine. * added NGImap4FolderFlags class to manage folder flags 2004-01-21 Helge Hess * v4.2.144 * EOQualifier+IMAPAdditions.m: fixed unseen qualifier processing * NGImap4Client.m, EOQualifier+IMAPAdditions.m: moved IMAP4 search string generation out of NGImap4Client.m to EOQualifier+IMAPAdditions.m 2004-01-20 Helge Hess * v4.2.143 * NGImap4Message.m: deprecated URL based factory methods - you should always use the context or folder "constructors", removed +messageWithUid:.. methods (used nowhere and messages should be constructed using their folder!) * NGImap4Folder.m: added -messageWithUid: factory method - you should always use that instead of allocating an NGImap4Message on your own, removed +imap4FolderWithContext: (used nowhere and folders should be constructed using their parent folder or context) * NGImap4Context.m: added URL based factory for messages and folders 2004-01-20 Helge Hess * NGImap4Message.m: added various attempts for optimizations (v4.2.142) 2004-01-19 Helge Hess * v4.2.141 * NGImap4Context.m: added globalID method, various cleanups * NGImap4Folder.m: added -globalID method, major cleanups * NGImap4Client.m: added -serverGlobalID method, moved password escaping code to NSString+Imap4.m * added global-id classes in NGImap4 (v4.2.140) 2004-01-16 Helge Hess * v4.2.139 * NGImap4Functions.m: started a new object to wrap all the old function junk * NGImap4Client.m, NGImap4Message.m: major cleanups * NGImap4DataSource.m: moved EOQualifier additions to separate source file, various cleanups * v4.2.138 * NGImap4ServerRoot.m: some cleanups, replaced NSZoneMalloc with calloc() * NGImap4Client.m: major cleanups, better handling of -lastException Tue Nov 11 15:04:18 2003 Jan Reichmann * NGImap4ResponseParser.m: add parsing of capability entries without value (v4.2.136) 2003-11-10 Helge Hess * NGImap4ResponseParser.m: explicitly marked the lastChar variable as being a signed char to avoid compiler errors (v4.2.135) Thu Nov 6 16:41:13 2003 Jan Reichmann * v4.2.134 * NGSieveClient: fixed a bug in normalizeResponse, return NSMutableDictionary * NGImap4ResponseParser.m: remove CYRUS_2_0 constant, don`t now what it should be :( Mon Nov 3 15:42:37 2003 Jan Reichmann * NGImap4Context: temporary set selected folder befor the select action to prevent notification confusions (v4.2.133) 2003-10-17 Helge Hess * NGSieveClient.m: small code cleanups Fri Jul 25 13:27:26 2003 Jan Reichmann * NGImap4DataSource.h: fixed #define Tue Jul 22 15:19:34 2003 Jan Reichmann * NGImap4ResponseParser.m: check for empty quota reponses (v4.2.128) 2003-07-18 Helge Hess * NGImap4Client.m: fixed some gstep-base issues, patch provided by Filip Van Raemdonck and cleaned up a bit (v4.2.127) Thu Jul 17 10:37:22 2003 Jan Reichmann * NGImap4ServerRoot: add a missing method (bulkFetchHeadersFor:inRange:withAllUnread:) (v4.2.126) Mon Jun 30 17:45:12 2003 Jan Reichmann * v4.2.125 * NGImap4Client: code cleanups * NGImap4Message: improve cache behavior (store the read-flag without fetching all flags) * NGImap4Folder: add a new method to fetch headers in range + set all read flags Fri Jun 27 18:08:49 2003 Jan Reichmann * NGImap4Message.m: improve flag handling (v4.2.124) * NGImap4Message.m: code cleanups (v4.2.123) Thu Jun 26 13:23:30 2003 Jan Reichmann * v.4.2.122 * NGImap4Message.m: add messageWithURL: methods * NGImap4Context.m: execute select-command before setting selectet folder * NGImap4Folder: add a struct do store failed select, status, getQuota responses, set selectet folder after successfully select response Fri Jun 20 18:51:24 2003 Jan Reichmann * v4.2.121 * NGImap4Client.m: cleanups * NGImap4ServerRoot, NGImap4Folder.m, NGImap4Functions: fetch status (new/unseen) of subfolders on demand only if Default: FetchNewUnseenMessagesInSubFoldersOnDemand = 'YES' * NGImap4ServerRoot, NGImap4Folder.m: improve folder-flag analysing, nonexistent folders will be ignored (Default: ShowNonExistentFolder), no 'list' request for folder with hasnochildren flag (Default: IgnoreHasNoChildrenFlag) (v4.2.120) * v4.2.119 * NGImap4Functions: cleanups * NGImap4Context.m: cleanups * NGImap4Folder.m: only reset subfolders if -resetSubFolders called (prev. behavior: -resetFolder called -resetSubFolders), cleanups Tue Jun 17 11:53:46 2003 Jan Reichmann * v4.2.118 * NGImap4Message+BodyStructure.h: check parsing of date failed * NGImap4Folder: cleanups Mo Jun 02 15:55:20 2003 Jan Reichmann * NGImap4Folder, NGImap4Functions: add notification for subfolder-resets (v4.2.112) 2003-05-28 Helge Hess * NGImap4Folder.m: fixed NSLogL=>NSLog removed a NSLog (v4.2.111) Tue May 27 17:39:20 2003 Jan Reichmann * NGImap4Folder.m: check for quota only if folder is selectable (v4.2.110) Tue May 20 18:03:12 2003 Jan Reichmann * NGImap4Context; add accessor to edit default values (v4.2.108) Wed May 14 10:57:51 2003 Jan Reichmann * v4.2.106 * NGImap4ResponseParser.m: use lowercase string to determine whether fetch body reponse is 'text' or 'message' (courier imap use lowercase letters for the body description) (bug 1611) * Info: move rfc, drafts and other information files to 'Info' Thu May 13 17:59:25 2003 Jan Reichmann * NGImap4Folder.m: add notification for folder reset, if more than one folder for the same folderpath exist (v4.2.105) (bug 1612) Mon May 5 17:59:25 2003 Jan Reichmann * NGImap4Folder.m: improve error log, fix a bug regarding multiple mail copy from and to the same folder (v4.2.103) Wed Apr 30 15:24:26 2003 Jan Reichmann * v4.2.102 * NGImap4ServerRoot: noinferiors depends on serverkind (bug 932) * NGImap4ResponseParser.m: improve parsing of server greeting * NGImap4Folder, NGImap4ServerRoot: take ShowOnlySubscribedIn* from context * NGImap4Context.m: set ShowOnlySubscribedIn* Defaults (depends on server) * NGImap4Client.m: detect washington imap server Wed Apr 30 12:34:38 2003 Jan Reichmann * v4.2.101 * NGImap4ServerRoot: fixed retain bug * NGImap4Folder.m: NSLog -> logWithFormat, fixed release (bug 1559), * NGImap4Context: accessors for server defaults * NGImap4Client.m: code cleanups, some logs depends LogDefault, try to get server name (cyrus, courier) - set some server-depending Defaults, fixed special folder subscribe/create behavior (bug 1540) Fri Apr 11 11:17:25 2003 Jan Reichmann * NGImap4Functions.m: add ImapLogEnabled' default bind some logs to 'LogImapEnabled' (v4.2.99) 2003-04-09 Helge Hess * v4.2.98 * NSString+Imap4.m: fixed a gcc signed/unsigned warning * NGSieveClient.m: fixed a warning * NGImap4FileManager.m: fixed some warnings * NGImap4Folder.m: fixed a warning * NGImap4Client.m: small cleanups * NGImap4ResponseParser.m: some smaller cleanups and small performance improvements (less autorelease, use NSStringClass) (v4.2.96) Mon Apr 7 20:02:29 2003 Jan Reichmann * v4.2.95 * NGImap4Message.m: check whether encoding was set -> set encoding during body-structure fetch * NGImap4Message+BodyStructure.h: if body-structure component is no rfc822 or multipart --> body url got 'part=1' (bug 1385) Fri Feb 28 18:32:53 2003 Jan Reichmann * NGImap4Functions.m: add support for Washington Imap Server, (delete folders in server root) (v4.2.93) Wed Feb 26 17:47:53 2003 Jan Reichmann * v4.2.92 * NGImap4ServerRoot.m: read also inbox folder if it is not subscribed * NGImap4Client.m: check whether no sequence contains 'ALERT', reconnect also if the server repsonse an unexpecte 'bye' sequence * (Changes for Washington Imap Server support) Wed Feb 26 14:26:30 2003 Jan Reichmann * NGImap4Client.m: remove NXConstStr in Excep. Handler (v4.2.91) Wed Feb 26 11:37:18 2003 Jan Reichmann * NGImap4Client.m: check whether so key exist, use DATE as default sort key (v4.2.89) Tue Feb 25 11:21:52 2003 Jan Reichmann * NGImap4Client.m: fixed a reconnect bug (try only one time, before return with exception) (bug 1108) (v4.2.88) Mon Feb 24 15:48:07 2003 Jan Reichmann * NGImap4Message.m: select folder befor fetch body structure (bug 1094) (v4.2.87) Fri Feb 14 16:16:47 2003 Jan Reichmann * NGImap4Context.m: code cleanups (v4.2.85) Fri Jan 31 17:05:55 2003 * NGImap4Context.m: add defaults for imap special folders, fix folder create bug (v4.2.83) Fri Jan 31 14:39:12 2003 * NGImap4Folder.m: fetch all messages if no sort failed or no sortordering was given (v4.2.82) Fri Jan 31 12:28:09 2003 * v4.2.81 * NGImap4Message.m: code cleanups * NGImap4Message+BodyStructure.h: fix parsing structure bug Wed Jan 29 22:12:08 2003 * NGImap4*: code cleanups (replace macros with method calls), catch all exceptions, now they are stored in [context lastException] remove connection retry (v4.2.80) Tue Jan 28 16:24:37 2003 * NGImap4Functions.m: fix courier imap bug (couldn`t delete subfoder which are selected) (v4.2.78) Tue Jan 28 15:54:21 2003 * NGImap4Client.m: remove unnecessary abort() (v4.2.77) Tue Jan 21 19:05:30 2003 * NGImap4Client.m: add sort encoding default (ImapSortEncoding default: UTF-8) (v4.2.71) Tue Jan 21 18:38:09 2003 * NGMimeMessageParser: increase version number cause changing of instance vars of super-class (v4.2.70) Fri Jan 17 13:49:17 2003 * NGImap4ResponseParser: fix variable placing (v4.2.66) Thu Jan 16 18:40:47 2003 * NGImap4ResponseParser.m: decode header values fur bodystructures (v4.2.65) Tue Jan 14 18:17:55 2003 * v4.2.64 * NGImap4Message+BodyStructure.h: lowercase content-transfer-encoding Tue Jan 14 12:24:44 2003 * v4.2.61 * NGImap4Functions.m: build exception after delete failed * NGImap4Folder.m: reset subfolders after rename * NGImap4Client.m: handle unexpectet 'bye' - response (occured with broken courier-imap server) Tue Jan 14 10:20:29 2003 * v4.2.60 * NGImap4Client.m: fix parsing of cyrus version bug (skyrix bug 845) Tue Jan 14 09:22:47 2003 * NGImap4Message+BodyStructure.h: fixed wong instance var Mon Jan 13 19:44:55 2003 * NGImap4Message.m, NGImap4Message+BodyStructure.h, NGImap4FileManager.m: use NGMime header field name contants (v4.2.59) Fri Jan 10 09:54:14 2003 * v4.2.58 * NGImap4Support.h: add -isOverQuota method to protocol * NGImap4ServerRoot.m: add missed methods from protocol * NGImap4ResponseParser.m: parse also quotaroot respones without given quota-root (skyrix bug 822) * NGImap4Folder.m: improve error handling (needed by quota errors) Thu Jan 9 14:31:12 2003 * v4.2.57 * NGImap4Context.m: add private method to set lastExceptions from folder * NGImap4Client.m: handle ALERT responses * NGImap4Folder: check for quota warning, check whether copy failed during move (SKYRiX Bug #777) * NGImap4ResponseParser.m: improve 'no' response parsing Wed Jan 8 16:26:00 2003 * v4.2.56 * NGImap4ResponseParser.m: fix quoted quota response parsing behavior * NGImap4Folder, NGImap4Client.m: use absolute names for quota response (bug 835) Tue Jan 7 16:47:36 2003 * v4.2.55 * NGImap4ServerRoot.m: add -usedSpace und -maxQuota methods (bug 821) * NGImap4Support.h: complete NGImap4Folder protocol (add -usedSpace, -maxQuota) Fri Dec 27 10:52:44 2002 Helge Hess * v4.2.53 * NSString+Imap4.m: fixed ordering of arguments to calloc() call (count,size) not (size,count) * NGSieveClient.m: removed some gcc 3.2 warnings * NGImap4ResponseParser.h: added -parseSieveResponse to interface declaration (removes a warning) Mon Dec 23 15:38:30 2002 Helge Hess * v4.2.52 * NGImap4Message.m: removed some unneeded code in -dealloc * NGImap4Message.h: NSMutableDictionary declaration was missing in the header file * NGImap4FileManager.m: -messageAtPath: is now typed to returned an NGImap4Message 2002-12-17 Helge Hess * NGImap4Client.m: replaced THROW with raise (4.2.51) Tue Dec 17 14:46:58 2002 * v4.2.50 * NGImap4ResponseParser.m: parse quota responses * NGImap4Folder.*: add maxQuota/usedQuota methods * NGImap4Context.*: add -canQuota method * NGImap4Client.*: add 'quota' command 2002-12-07 Helge Hess * NGImap4Folder.m: added -isComplete prototype to NGImap4Message Privates (removes a compilation warning) (v4.2.49) Tue Dec 10 19:12:45 2002 * v4.2.48 * NGImap4ResponseParser.m: throw exception "No response exception" if server is down (SKYRiX Bug #651) * NGImap4Folder.m, NGImap4ServerRoot: Default for display subscribed-folders (ShowOnlySubscribedInSubFolders and ShowOnlySubscribedInRoot) * NGImap4Client.m: release exceptions after description output now Tue Dec 10 12:47:08 2002 * v4.2.47 * NGImap4ResponseParser.m: fixing 'fetch body' response bug (check for empty bodies) (SX Bug #756) * NGImap4Message+BodyStructure.h: build messages only for rfc822 subtype, fixed header handling message/rfc822 bodies * NGImap4Folder.m: remove logs * NGImap4ServerRoot.m: add fake methods (SX Bug #756) Mon Dec 9 13:55:52 2002 * v4.2.46 * NGImap4Context.m: add capability support * NGImap4Client.*, NGImap4ResponseParser: add capability command Fri Dec 6 17:08:28 2002 * v4.2.45 * NGImap4Folder*: add some ss-sorting improvements, bulk-fetch messages in range * NGImap4Message.m: description do not initialize headers anymore, add -_setHeaders: private function for bulk-fetching Tue Dec 3 16:45:14 2002 * NGImap4ResponseParser.m: parse empty string if message does 'no longer exists'(v4.2.44) Mon Dec 2 19:22:13 2002 Jan Reichmann * v4.2.43 * NGImap4Context.m: add -setSelectedFolder for performance improvements * NGImap4Folder.m: (Bug #17379) clear msn->uid cache after delete, performance (remove double 'select' call) Mon Dec 2 11:18:51 2002 * NGImap4Folder.m: only reset subfolder if they are already loaded (v4.2.42) Fri Nov 29 12:27:25 2002 * v4.2.40 * NGImap4ResponseParser.m: check tagged responses before parsing it * code cleanups Wed Nov 27 16:42:07 2002 * NGImap4Context.m, NGImap4Folder: add msn-uid cache (v4.2.39) Mon Nov 25 16:29:40 2002 Jan Reichmann * NGImap4Folder.m: if no next mail, return nil (v4.2.38) * NGImap4Client.m: check whether sort keys are valid (v4.2.36) * NGImap4ResponseParser.m: fix 'idle to long' bug Fri Nov 22 15:04:18 2002 * NGImap4ResponseParser.m: fixed content parsing (v4.2.36) * NGImap4Message*: add support for body-structure content(v4.2.35) Fri Nov 22 11:13:40 2002 * NGImap4ResponseParser.m: add Imap4MMDataBoundary Default to modify MM-Data-Use boundary (v4.2.34) Thu Nov 21 20:02:48 2002 * NGImap4ResponseParser.m: add file mapped data for fetching imap data (to restore previous behavior -NoMemoryMappedDataForImapBlobs YES) (v4.2.33) Wed Nov 21 18:07:37 2002 * add fetch body structure with content-urls * add fetch content of single parts (v4.2.32) Wed Nov 20 18:07:37 2002 * GNUmakefile: remove tool-make 2002-11-20 Helge Hess * NGImap4Message.m: added ability to query headers using KVC (v4.2.31) * v4.2.30 * NGImap4FileManager.m: do not create if no URL is given, better error handling with URL initialization * NGImap4Context.m: do not create context if an empty URL is given Tue Nov 19 18:13:38 2002 * NGImap4*: add commands (thread, fetch body) Mon Nov 11 10:24:14 2002 Jan Reichmann * NGImap4Client.m: improve greetings parse behaviour 2002-11-10 Helge Hess * NGImap4Client, NGImap4FileManager: can init with URL (v4.2.27) 2002-09-30 Helge Hess * NGImap4Client.m: prepared for SSL support * NGImap4Context.m: do not alloc with zone (v4.2.25) Tue Aug 22 14:57:38 2002 Jan Reichmann * (from 4.1) use cyrus 2.0, sieve, fixes (v4.2.23) Tue Aug 20 14:57:38 2002 Jan Reichmann * NGImap4Folder.m: (BUG 17379) if there is no prev-message, take last message (v4.2.22) Tue Jul 23 10:17:23 2002 Jan Reichmann * NGImap4Folder.m: (BUG 17129) remove debug abort (v4.2.19) - 2002-07-17 v4.2.17 (hh) [extracted from CVS] Wed Jul 17 12:58:01 2002 Jan Reichmann * NGImap4Folder.m: added better logs (v4.2.18) * NGImap4Folder.m: (BUG 16784) if no sort ordering is given, sort on "date" field of the message Thu Jul 11 16:04:39 2002 Jan Reichmann * NGImap4Folder, NGImap4Client, NGImap4ResponseParser: add sortedMessagesInRange Method - 2002-07-10 v4.2.16 (hh) [extracted from CVS] 2002-07-09 Helge Hess * NGImap4DataSource.m: place -fetchObjects in an autorelease-pool (v4.2.15) * NGImap4Message.m: now supports file-info keys, cleaned up -description (v4.2.14) - 2002-07-08 v4.2.13 (hh) [extracted from CVS] - 2002-07-08 v4.2.12 (hh) [extracted from CVS] Thu Jun 13 19:36:33 2002 Jan Reichmann * NGImap4Context: add folderWithName:caseInsensitive: (v4.2.11) Tue Jun 11 16:17:06 2002 Jan Reichmann * NGImap4Client.m: (bug 11939) add quote support for special chars in passwd (v4.2.10) Mon Jun 10 18:58:55 2002 Jan Reichmann * NGImap4Context.m, NGImap4Folder.m: add support for case sensitve folder handling (v4.2.9) * NGImap4Context.m, NGImap4Folder.m: reduce logs (v4.2.8) Sun Jun 9 02:56:55 2002 Jan Reichmann * NGImap4Client.m: (bug 16482) double encoding bug (v4.2.7) * NGImap4ServerRoot.m: (bug 16050) show also not subscribed folders (v4.2.6) - 2002-06-07 v4.2.5 (jr) [extracted from CVS] - 2002-06-04 v4.2.4 (jr) [extracted from CVS] 2002-06-03 Helge Hess * fixed to compile with gstep-base - 2002-05-22 v4.2.3 (jr) [extracted from CVS] Wed Mar 6 13:29:28 CET 2002 Jan Reichmann * merge with SkyrixGreen Mon Jan 7 16:57:07 2002 Jan Reichmann * NGImap4ResponseParser.m: improved error messages Fri Dec 7 14:14:33 2001 Jan Reichmann * NGImap4Client.m ([NGImap -fetchFrom:to:parts:]): add profiling Tue Dec 4 19:14:43 2001 Jan Reichmann * NGImap4Client.m ([NGImap -fetchFrom:to:parts:]): passwd with spaces Wed Nov 28 18:17:06 2001 Gerrit Albrecht * NGImap4Context.m, NGImap4FileManager.m: Added knowledge about drafts folder. Wed Oct 24 13:18:29 2001 Helge Hess * NGImap4Client.m: moved Folder-Name encoding/decoding to NSString category - needs to be corrected to NSData !!! * updated to SKYRiXgreen version (lots of fixes & changes) Tue Oct 2 05:41:32 2001 Jan Reichmann * NGImap4Context.m: Fixed __RELEASE__ bug ;( Fri Aug 10 13:48:29 2001 Helge Hess * NGImap4FileManager.m: inherit from NGFileManager Fri Aug 10 07:28:10 2001 Martin Hoerning * NGImap4Client, NGImap4FileManager, NGImap4Context: RETAIN-BUGS fixed Fri Jun 22 15:46:23 2001 Jan Reichmann * NGImap4Client.m: fixed search uid bug Thu Jun 21 16:50:13 2001 Jan Reichmann * NGImap4FileManager.m: add -imapContext Wed May 16 17:59:00 2001 Jan Reichmann * NGImap4Client.m, NGImap4Context.m, NGImap4ResponseParser.m: washington imap server Tue May 15 18:10:33 2001 Jan Reichmann * NGImap4ResponseParser.m: ignore now empty fetchentries with no header length field Tue May 8 16:26:13 2001 Jan Reichmann * NGImap4FileManager.m: add edit possibility for syncMode Mon Apr 17 11:17:47 2001 Jan Reichmann * NGImap4Folder.m: fixed error log bug Mon Apr 2 13:47:47 2001 Jan Reichmann * NGImap4FileManager.m: fixed private interface Fri Mar 30 14:17:25 2001 Jan Reichmann * NGImap4Client.m: try only 10 times to reconnect before raising an exception * NGImap4Client.m: fixed error log Fri Mar 30 10:54:08 2001 Helge Hess * NGImap4DataSource.m: major cleanups Fri Mar 16 16:05:27 2001 Jan Reichmann * NGImap4Message.m: fixed parse message bug Wed Mar 14 13:16:24 2001 Jan Reichmann * NGImap4FileManager.m: add datasource at path Tue Feb 6 19:47:03 2001 Jan Reichmann * NGImap4Folder.m: fixed bug for wrong MSN Tue Feb 6 19:47:03 2001 Joerg Grimm * NGImap4Client.m: check open connection response without servername (Cyrus IMAP4 v) Wed Jan 3 13:14:43 2001 Jan Reichmann * NGImap4Client.m: fixed flag bug Tue Jan 2 16:58:46 2001 Jan Reichmann * NGImap4Client.m: hide password in log * NGImap4Client.m: sleep before reconnect Mon Dec 18 14:48:18 2000 Jan Reichmann * NGImap4Folder.m: fixed 'lookup only' folder bug Fri Dec 15 19:26:09 2000 Jan Reichmann * NGImap4Client.m, NGImap4Context.m: automatically subscribe to inbox * NGImap4Context.m: format text Mon Nov 13 14:51:13 2000 Jan Reichmann * Python/: insert python module * NGImapClient.m: enable append of messages with more than 15kB Fri Sep 29 15:15:29 2000 Jan Reichmann * NGImap4: add sync mode (synchronize selects for folder) Thu Sep 14 13:33:49 2000 Jan Reichmann * search.txt: use '=' instead of '==' * NGImap4Context.[hm]: insert - newMessages * NGImap4Client.m: remove compiler warning Wed Sep 13 14:47:23 2000 Jan Reichmann * NGImap4Context.m: at first ask inbox in method hasNewMessages Tue Sep 5 14:04:37 2000 Joerg Grimm * NGImap4Folder.m: log removed Fri Sep 1 13:15:22 2000 Jan Reichmann * NGImap4Client.m: remove logs Wed Aug 30 21:22:31 2000 Jan Reichmann * NGImap4Context.[hm], NGImap4Client.m: store server data Tue Aug 29 18:56:38 2000 Jan Reichmann * NGImap4Context.m, NGImap4Folder.h, NGImap4Folder.m,NGImap4Functions.m: actions for no-select folders Mon Aug 28 18:43:11 2000 Jan Reichmann * NGImap4Folder.m: fixed bug for read-only folder Tue Aug 8 11:21:16 2000 Helge Hess * NGImap4Message.m: added -globalID method * NGImap4Context.m: added -login method Thu Jul 27 14:48:26 2000 Jan Reichmann * NGImap4Folder.m: fixed bug (unseen was not updated) Fri Jun 23 10:32:00 2000 Jan Reichmann * NGImap4ResponseParser.m: remove category for NSData Wed Jun 7 16:07:03 2000 Jan Reichmann * NGImap4Folder.[hm], NGImap4ServerRoot.[hm]: maxResults for search Mon May 29 17:56:46 2000 Jan Reichmann * NGImap4Functions.m: remove recursive copy bug Sat May 27 18:27:48 2000 Jan Reichmann * NGImap4Message.m: add flagged methods Tue May 23 12:33:25 2000 Jan Reichmann * NGImap4Context.[hm]: improvements ( add -folderWithName) Fri May 19 11:52:25 2000 Jan Reichmann * NGImap4Client.m: replace 0 with 1 in range-commands Thu May 18 15:20:19 2000 Jan Reichmann * NGImap4*: enabled mailboxes with more than one rootfolder Tue May 16 12:35:46 2000 Jan Reichmann * NGImap4Client.m: fixed RC bug Mon May 15 16:26:19 2000 Jan Reichmann * NGImap4Context.m, NGImap4Folder.[hm]: evaluate noinferiors flag Wed May 10 19:30:37 2000 Jan Reichmann * NGImap4Folder.m: fixed RC-bug (raised during moveFolder) Wed May 3 22:15:10 2000 Jan Reichmann * NGImap4Folder.m: improvements Mon May 1 21:24:21 2000 Jan Reichmann * NGImap4Folder.m: fixed RC-bug Wed Apr 26 10:26:54 2000 Jan Reichmann * NGImap4Context.m: bugfix in hasNewMessages Thu Apr 13 16:19:56 2000 Jan Reichmann * NGImap4Message.m: insert isEqual: and hash methods Mon Apr 10 14:34:49 2000 Helge Hess * NGImap4Folder.m: added autorelease-pools, added immutable containers * NGImap4Client.m: added autorelease-pools * NGImap4Client.m(-normalizeFetchResponse:): created immutable, not-autoreleased NSDictionary entry objects * NGImap4Client.m: replaced abort() with NSCAssert Thu Apr 6 16:32:09 2000 Jan Reichmann * NGImap4 build lib-internal Trash/Sent Folder managment Tue Feb 29 19:18:09 2000 Helge Hess * MOF3 import Tue Feb 22 19:16:11 2000 Helge Hess * GNUmakefile (GNUSTEP_INSTALLATION_DIR): changed to GNUSTEP_LOCAL_ROOT Thu Jan 13 17:24:40 2000 Jan Reichmann * created ChangeLog SOPE/sope-mime/NGImap4/EOSortOrdering+IMAPAdditions.m0000644000000000000000000000601015004363604021016 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "imCommon.h" @interface NSObject(IMAPAdditions) - (NSString *)imap4SortString; @end @implementation NSString(IMAPAdditions) - (NSString *)imap4SortString { /* support preformatted sort strings */ return self; } @end /* NSString(IMAPAdditions) */ @implementation EOSortOrdering(IMAPAdditions) static NSArray *AllowedSortKeys = nil; - (void)_setupAllowedIMAP4SortKeys { if (AllowedSortKeys != nil) return; AllowedSortKeys = [[NSArray alloc] initWithObjects: @"ARRIVAL", @"CC", @"DATE", @"FROM", @"SIZE", @"SUBJECT", @"TO", @"MODSEQ", nil]; } - (NSString *)imap4SortString { SEL sel; NSString *lkey; lkey = [self key]; if (![lkey isNotEmpty]) return nil; /* check whether key is a valid sort string */ if (AllowedSortKeys == nil) [self _setupAllowedIMAP4SortKeys]; if (![AllowedSortKeys containsObject:[lkey uppercaseString]]) { NSLog(@"ERROR[%s] key %@ is not allowed here!", __PRETTY_FUNCTION__, lkey); return nil; } /* check selector */ sel = [self selector]; if (sel_isEqual(sel, EOCompareDescending) || sel_isEqual(sel, EOCompareCaseInsensitiveDescending)) { return [@"REVERSE " stringByAppendingString:lkey]; } // TODO: check other selectors whether they make sense instead of silent acc. return lkey; } @end /* EOSortOrdering(IMAPAdditions) */ @implementation NSArray(IMAPAdditions) - (NSString *)imap4SortStringForSortOrderings { /* turn EOSortOrdering into an IMAP4 value for "SORT()" eg: "DATE REVERSE SUBJECT" It also checks a set of allowed sort-keys (don't know why) */ NSMutableString *sortStr; unsigned i, count; if ((count = [self count]) == 0) return nil; sortStr = [NSMutableString stringWithCapacity:(count * 24)]; for (i = 0; i < count; i++) { EOSortOrdering *so; NSString *s; so = [self objectAtIndex:i]; if (![so isNotNull]) continue; if ((s = [so imap4SortString]) == nil) continue; if (i > 0) [sortStr appendString:@" "]; [sortStr appendString:s]; } return [sortStr isNotEmpty] ? sortStr : (NSMutableString *)nil; } @end /* NSArray(IMAPAdditions) */ SOPE/sope-mime/NGImap4/NGSieveClient.m0000644000000000000000000006477715004363604016257 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess Copyright (C) 2007-2011 Inverse inc. This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "NGSieveClient.h" #include "NGImap4Support.h" #include "NGImap4ResponseParser.h" #include "NSString+Imap4.h" #include "imCommon.h" #include #include #include @interface NGSieveClient(Private) - (NGHashMap *)processCommand:(id)_command; - (NGHashMap *)processCommand:(id)_command logText:(id)_txt; - (NGHashMap *)processCommand:(id)_command logText:(id)_txt reconnect:(BOOL)_reconnect; - (NSException *)sendCommand:(id)_command; - (NSException *)sendCommand:(id)_command logText:(id)_txt; - (NSException *)sendCommand:(id)_command logText:(id)_txt attempts:(int)_c; - (NSMutableDictionary *)normalizeResponse:(NGHashMap *)_map; - (NSMutableDictionary *)normalizeOpenConnectionResponse:(NGHashMap *)_map; - (NSDictionary *)login; /* parsing */ - (NSString *)readStringToCRLF; - (NSString *)readString; @end /* An implementation of an Imap4 client A folder name always looks like an absolute filename (/inbox/blah) NOTE: Sieve is just the filtering language ... This should be ACAP? http://asg.web.cmu.edu/rfc/rfc2244.html ---snip--- "IMPLEMENTATION" "Cyrus timsieved v2.1.15-IPv6-Debian-2.1.15-0woody.1.0" "SASL" "PLAIN" "SIEVE" "fileinto reject envelope vacation imapflags notify subaddress relational regex" "STARTTLS" OK ---snap--- */ @implementation NGSieveClient static int defaultSievePort = 2000; static NSNumber *YesNumber = nil; static NSNumber *NoNumber = nil; static BOOL ProfileImapEnabled = NO; static BOOL LOG_PASSWORD = NO; static BOOL debugImap4 = NO; static NSString *AuthMechanism = nil; + (void)initialize { static BOOL didInit = NO; NSUserDefaults *ud; if (didInit) return; didInit = YES; ud = [NSUserDefaults standardUserDefaults]; LOG_PASSWORD = [ud boolForKey:@"SieveLogPassword"]; ProfileImapEnabled = [ud boolForKey:@"ProfileImapEnabled"]; debugImap4 = [ud boolForKey:@"ImapDebugEnabled"]; AuthMechanism = [ud stringForKey:@"NGImap4AuthMechanism"]; [AuthMechanism retain]; YesNumber = [[NSNumber numberWithBool:YES] retain]; NoNumber = [[NSNumber numberWithBool:NO] retain]; } + (id)clientWithURL:(id)_url andAuthMech:(NSString *) imapAuthMech{ return [[(NGSieveClient *)[self alloc] initWithURL:_url andAuthMech: imapAuthMech] autorelease]; } + (id)clientWithAddress:(id)_address { NGSieveClient *client; client = [self alloc]; return [[client initWithAddress:_address] autorelease]; } + (id)clientWithHost:(id)_host { return [[[self alloc] initWithHost:_host] autorelease]; } - (id)initWithNSURL:(NSURL *)_url andAuthMech:(NSString *) imapAuthMech{ NGInternetSocketAddress *a; int port; if ((port = [[_url port] intValue]) == 0) port = defaultSievePort; a = [NGInternetSocketAddress addressWithPort:port onHost:[_url host]]; if ((self = [self initWithAddress:a])) { NSDictionary *queryComponents = [_url queryComponents]; NSString *value; self->login = [[_url user] copy]; self->password = [[_url password] copy]; value = [queryComponents valueForKey: @"tls"]; if (value && [value isEqualToString: @"YES"]) self->useTLS = YES; else self->useTLS = NO; tlsVerifyMode = TLSVerifyDefault; value = [queryComponents valueForKey: @"tlsVerifyMode"]; if (value) { if ([value isEqualToString: @"allowInsecureLocalhost"]) { tlsVerifyMode = TLSVerifyAllowInsecureLocalhost; } else if ([value isEqualToString: @"none"]) { tlsVerifyMode = TLSVerifyNone; } } } serverType = nil; capabilities = nil; if(imapAuthMech && [imapAuthMech length] > 0) AuthMechanism = imapAuthMech; return self; } - (id)initWithURL:(id)_url andAuthMech:(NSString *) imapAuthMech { if (_url == nil) { [self release]; return nil; } if (![_url isKindOfClass:[NSURL class]]) _url = [NSURL URLWithString:[_url stringValue]]; return [self initWithNSURL:_url andAuthMech: imapAuthMech]; } - (id)initWithHost:(id)_host { NGInternetSocketAddress *a; a = [NGInternetSocketAddress addressWithPort:defaultSievePort onHost:_host]; return [self initWithAddress:a]; } - (id)initWithAddress:(id)_address { // di if ((self = [super init])) { self->address = [_address retain]; self->debug = debugImap4; } return self; } - (void)dealloc { [self->lastException release]; [self->address release]; [self->io release]; [self->socket release]; [self->previous_socket release]; [self->parser release]; [self->authname release]; [self->login release]; [self->password release]; [self->serverType release]; [self->capabilities release]; [super dealloc]; } /* equality */ - (BOOL)isEqual:(id)_obj { if (_obj == self) return YES; if ([_obj isKindOfClass:[NGSieveClient class]]) return [self isEqualToSieveClient:_obj]; return NO; } - (BOOL)isEqualToSieveClient:(NGSieveClient *)_obj { if (_obj == self) return YES; if (_obj == nil) return NO; return [[_obj address] isEqual:self->address]; } /* accessors */ - (id)socket { return self->socket; } - (id)address { return self->address; } - (NSString * ) serverType { return self->serverType; } - (NSArray *) capabilities { return self->capabilities; } - (BOOL) hasCapability: (NSString *)_capabilityName { if (self->capabilities) { return [self->capabilities containsObject: _capabilityName]; } return NO; } /* exceptions */ - (void)setLastException:(NSException *)_ex { ASSIGN(self->lastException, _ex); } - (NSException *)lastException { return self->lastException; } - (void)resetLastException { [self->lastException release]; self->lastException = nil; } /* connection */ - (void)resetStreams { [self->socket release]; self->socket = nil; [self->io release]; self->io = nil; [self->parser release]; self->parser = nil; } - (NSDictionary *)openConnection { NSDictionary *res; struct timeval tv; double ti; ti = 0.0; if (ProfileImapEnabled) { gettimeofday(&tv, NULL); ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0); } [self resetStreams]; [self->previous_socket release]; self->previous_socket = nil; self->socket = [[NGActiveSocket socketConnectedToAddress:self->address] retain]; if (self->socket == nil) { [self logWithFormat:@"ERROR: could not connect: %@", self->address]; return nil; } self->io = [NGBufferedStream alloc]; // keep gcc happy self->io = [self->io initWithSource:(id)self->socket]; self->parser = [[NGImap4ResponseParser alloc] initWithStream:self->socket]; /* receive greeting from server without tag-id */ if (ProfileImapEnabled) { gettimeofday(&tv, NULL); ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0) - ti; fprintf(stderr, "[%s] : time needed: %4.4fs\n", __PRETTY_FUNCTION__, ti < 0.0 ? -1.0 : ti); } res = [self normalizeOpenConnectionResponse: [self->parser parseSieveResponse]]; ASSIGN(serverType, [res objectForKey: @"server"]); ASSIGN(capabilities, [[res objectForKey:@"capabilities"] componentsSeparatedByString: @" "]); // If we're using TLS, we start it here if (self->useTLS) { NSDictionary *d; d = [self normalizeResponse:[self processCommand: @"STARTTLS"]]; if ([[d valueForKey:@"result"] boolValue]) { id o; o = [[NGActiveSSLSocket alloc] initWithConnectedActiveSocket: (NGActiveSocket *)self->socket withVerifyMode: tlsVerifyMode]; if ([o startTLS]) { //NGBufferedStream *buffer; // We keep a reference to our previous instance of NGActiveSocket as // it's still being used. NGActiveSSLSocket's read/write methods are // being used but the rest is coming of directly from NGActiveSocket self->previous_socket = self->socket; self->socket = o; //[self->text release]; [self->parser release]; self->io = [(NGBufferedStream *)[NGBufferedStream alloc] initWithSource: self->socket]; //self->text = [(NGCTextStream *)[NGCTextStream alloc] initWithSource: buffer]; //[buffer release]; //buffer = nil; self->parser = [[NGImap4ResponseParser alloc] initWithStream: self->socket]; [self logWithFormat:@"TLS started successfully."]; /* as per rfc5804 section 2.2: * at this point, the server MUST re-issue the capability results * followed by an OK response. * The client MUST discard cached capability information * and replace it with the new information. */ res = [self normalizeOpenConnectionResponse: [self->parser parseSieveResponse]]; ASSIGN(serverType, [res objectForKey: @"server"]); ASSIGN(capabilities, [[res objectForKey:@"capabilities"] componentsSeparatedByString: @" "]); } else [self logWithFormat:@"Could not start TLS."]; } else [self logWithFormat:@"Could not start TLS."]; } return res; } - (NSNumber *)isConnected { /* Check whether stream is already open (could be closed due to a server timeout) */ // TODO: why does that return an object? if (self->socket == nil) return [NSNumber numberWithBool:NO]; return [NSNumber numberWithBool:[(NGActiveSocket *)self->socket isAlive]]; } - (void)closeConnection { [self->socket close]; [self->socket release]; self->socket = nil; [self->previous_socket close]; [self->previous_socket release]; self->previous_socket = nil; [self->parser release]; self->parser = nil; } - (NSDictionary *)login:(NSString *)_login password:(NSString *)_passwd { return [self login: _login authname: _login password: _passwd]; } - (NSDictionary *)login:(NSString *)_login authname:(NSString *)_authname password:(NSString *)_passwd { /* login with plaintext password authenticating */ if ((_login == nil) || (_passwd == nil)) return nil; [self->authname release]; self->authname = nil; [self->login release]; self->login = nil; [self->password release]; self->password = nil; self->authname = [_authname copy]; self->login = [_login copy]; self->password = [_passwd copy]; return [self login]; } - (void)reconnect { [self closeConnection]; [self openConnection]; [self login]; } - (NSDictionary *)login { NGHashMap *map = nil; NSData *auth; char *buffer; const char *utf8Username, *utf8Authname, *utf8Password; size_t buflen, lenUsername, lenAuthname, lenPassword; if (![self->socket isConnected]) { NSDictionary *con; if ((con = [self openConnection]) == nil) return nil; if (![[con objectForKey:@"result"] boolValue]) return con; } if([AuthMechanism isEqualToString: @"xoauth2"]) { NSString *oauth2Password, *oauth2Username; oauth2Username = [NSString stringWithFormat: @"user=%@", self->login]; oauth2Password = [NSString stringWithFormat: @"auth=Bearer %@", self->password]; utf8Username = [oauth2Username UTF8String]; utf8Password = [oauth2Password UTF8String]; } else { utf8Username = [self->login UTF8String]; utf8Password = [self->password UTF8String]; if (!utf8Password) utf8Password = 0; } if (self->authname) utf8Authname = [self->authname UTF8String]; else utf8Authname = [self->login UTF8String]; lenUsername = strlen (utf8Username); lenAuthname = strlen (utf8Authname); lenPassword = strlen (utf8Password); if([AuthMechanism isEqualToString: @"xoauth2"]) { buflen = lenUsername + lenPassword + 3; buffer = malloc (sizeof (char) * (buflen + 1)); sprintf (buffer, "%s%c%s%c%c", utf8Username, 1, utf8Password, 1, 1); } else { AuthMechanism = @"PLAIN"; buflen = lenUsername + lenAuthname + lenPassword + 2; buffer = malloc (sizeof (char) * (buflen + 1)); sprintf (buffer, "%s%c%s%c%s", utf8Username, 0, utf8Authname, 0, utf8Password); }; auth = [NSData dataWithBytesNoCopy:buffer length:buflen]; auth = [auth dataByEncodingBase64WithLineLength:4096 /* 'unlimited' */]; NSString *s; if ([auth length] < 1024) // Use the quoted format s = [NSString stringWithFormat:@"AUTHENTICATE \"%@\" \"%s\"", AuthMechanism, [auth bytes]]; else // Use the literal format s = [NSString stringWithFormat:@"AUTHENTICATE \"%@\" {%d+}\r\n%s", AuthMechanism, (int)[auth length], [auth bytes]]; if (LOG_PASSWORD) { map = [self processCommand:s logText:s reconnect:NO]; } else { NSString *logText; logText = [NSString stringWithFormat: @"AUTHENTICATE \"%@\" HIDDEN", AuthMechanism]; map = [self processCommand:s logText:logText reconnect:NO]; } if (map == nil) { [self logWithFormat:@"ERROR: got no result from command."]; return nil; } return [self normalizeResponse:map]; } /* logout from the connected host and close the connection */ - (NSDictionary *)logout { NGHashMap *map; map = [self processCommand:@"logout"]; // TODO: check for success! [self closeConnection]; return [self normalizeResponse:map]; } - (NSString *)getScript:(NSString *)_scriptName { NSException *ex; NSString *script, *s; s = [@"GETSCRIPT \"" stringByAppendingString:_scriptName]; s = [s stringByAppendingString:@"\""]; ex = [self sendCommand:s logText:s attempts:3]; if (ex != nil) { [self logWithFormat:@"ERROR: could not get script: %@", ex]; [self setLastException:ex]; return nil; } /* read script string */ if ((script = [[self readString] autorelease]) == nil) return nil; if ([script hasPrefix:@"O "] || [script hasPrefix:@"NO "]) { // TODO: not exactly correct, script could begin with this signature // Note: readString read 'NO ...', but the first char is consumed [self logWithFormat:@"ERROR: status line reports: '%@'", script]; return nil; } NSLog(@"str: %@", script); /* read response code */ if ((s = [self readStringToCRLF]) == nil) { [self logWithFormat:@"ERROR: could not parse status line."]; return nil; } if (![s isNotEmpty]) { // remainder of previous string [s release]; if ((s = [self readStringToCRLF]) == nil) { [self logWithFormat:@"ERROR: could not parse status line."]; return nil; } } if (![s hasPrefix:@"OK"]) { [self logWithFormat:@"ERROR: status line reports: '%@'", s]; [s release]; return nil; } [s release]; return script; } - (BOOL)isValidScriptName:(NSString *)_name { return [_name isNotEmpty]; } - (NSDictionary *)putScript:(NSString *)_name script:(NSString *)_script { // TODO: script should be send in UTF-8! NGHashMap *map; NSString *s; if (![self isValidScriptName:_name]) { [self logWithFormat:@"%s: missing script-name", __PRETTY_FUNCTION__]; return nil; } if (![_script isNotEmpty]) { [self logWithFormat:@"%s: missing script", __PRETTY_FUNCTION__]; return nil; } s = @"PUTSCRIPT \""; s = [s stringByAppendingString:_name]; s = [s stringByAppendingString:@"\" "]; s = [s stringByAppendingFormat:@"{%d+}\r\n%@", (int)[_script lengthOfBytesUsingEncoding: NSUTF8StringEncoding], _script]; map = [self processCommand:s]; return [self normalizeResponse:map]; } - (NSDictionary *)setActiveScript:(NSString *)_name { NGHashMap *map; if (!_name) { NSLog(@"%s: missing script-name", __PRETTY_FUNCTION__); return nil; } map = [self processCommand: [NSString stringWithFormat:@"SETACTIVE \"%@\"", _name]]; return [self normalizeResponse:map]; } - (NSDictionary *)deleteScript:(NSString *)_name { NGHashMap *map; NSString *s; if (![self isValidScriptName:_name]) { NSLog(@"%s: missing script-name", __PRETTY_FUNCTION__); return nil; } s = [NSString stringWithFormat:@"DELETESCRIPT \"%@\"", _name]; map = [self processCommand:s]; return [self normalizeResponse:map]; } - (NSDictionary *)listScripts { NSMutableDictionary *md; NSException *ex; NSString *line; ex = [self sendCommand:@"LISTSCRIPTS" logText:@"LISTSCRIPTS" attempts:3]; if (ex != nil) { [self logWithFormat:@"ERROR: could not list scripts: %@", ex]; [self setLastException:ex]; return nil; } /* read response */ md = [NSMutableDictionary dictionaryWithCapacity:16]; while ((line = [self readStringToCRLF]) != nil) { if ([line hasPrefix:@"OK"]) break; if ([line hasPrefix:@"NO"]) { md = nil; break; } if ([line hasPrefix:@"{"]) { [self logWithFormat:@"unsupported list response line: '%@'", line]; } else if ([line hasPrefix:@"\""]) { NSString *s; NSRange r; BOOL isActive; s = [line substringFromIndex:1]; r = [s rangeOfString:@"\""]; if (r.length == 0) { [self logWithFormat:@"missing closing quote in line: '%@'", line]; [line release]; line = nil; continue; } s = [s substringToIndex:r.location]; isActive = [line rangeOfString:@"ACTIVE"].length == 0 ? NO : YES; [md setObject:[NSNumber numberWithBool: isActive] forKey:s]; } else { [self logWithFormat:@"unexpected list response line (%d): '%@'", [line length], line]; } [line release]; line = nil; } [line release]; line = nil; return md; } - (NSMutableDictionary *)normalizeResponse:(NGHashMap *)_map { /* Filter for all responses result : NSNumber (response result) exists : NSNumber (number of exists mails in selectet folder recent : NSNumber (number of recent mails in selectet folder expunge : NSArray (message sequence number of expunged mails in selectet folder) */ id keys[3], values[3]; NSParameterAssert(_map != nil); keys[0] = @"RawResponse"; values[0] = _map; keys[1] = @"result"; values[1] = [[_map objectForKey:@"ok"] boolValue] ? YesNumber : NoNumber; return [NSMutableDictionary dictionaryWithObjects:values forKeys:keys count:2]; } - (NSMutableDictionary *)normalizeOpenConnectionResponse:(NGHashMap *)_map { /* filter for open connection */ NSMutableDictionary *result; NSString *tmp; result = [self normalizeResponse:_map]; if (![[[_map objectEnumeratorForKey:@"ok"] nextObject] boolValue]) return result; if ((tmp = [_map objectForKey:@"implementation"])) [result setObject:tmp forKey:@"server"]; if ((tmp = [_map objectForKey:@"sieve"])) [result setObject:tmp forKey:@"capabilities"]; return result; } /* Private Methods */ - (BOOL)handleProcessException:(NSException *)_exception repetitionCount:(int)_cnt { if (_cnt > 3) { [_exception raise]; return NO; } if ([_exception isKindOfClass:[NGIOException class]]) { [self logWithFormat: @"WARNING: got exception try to restore connection: %@", _exception]; return YES; } if ([_exception isKindOfClass:[NGImap4ParserException class]]) { [self logWithFormat: @"WARNING: Got Parser-Exception try to restore connection: %@", _exception]; return YES; } [_exception raise]; return NO; } - (void)waitPriorReconnectWithRepetitionCount:(int)_cnt { unsigned timeout; timeout = _cnt * 2; [self logWithFormat:@"reconnect to %@, sleeping %d seconds ...", self->address, timeout]; sleep(timeout); [self logWithFormat:@"reconnect ..."]; } - (NGHashMap *) processCommand: (id)_command logText: (id)_txt { return [self processCommand: _command logText: _txt reconnect: YES]; } - (NGHashMap *) processCommand: (id)_command logText: (id)_txt reconnect: (BOOL)_reconnect { NGHashMap *map = nil; BOOL repeatCommand = NO; int repeatCnt = 0; struct timeval tv; double ti = 0.0; if (ProfileImapEnabled) { gettimeofday(&tv, NULL); ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0); fprintf(stderr, "{"); } do { /* TODO: shouldn't that be a while loop? */ if (repeatCommand) { if (repeatCnt > 1) [self waitPriorReconnectWithRepetitionCount:repeatCnt]; repeatCnt++; if (_reconnect) [self reconnect]; repeatCommand = NO; } NS_DURING { NSException *ex; if ((ex = [self sendCommand:_command logText:_txt]) != nil) { repeatCommand = [self handleProcessException:ex repetitionCount:repeatCnt]; } else map = [self->parser parseSieveResponse]; } NS_HANDLER { repeatCommand = [self handleProcessException:localException repetitionCount:repeatCnt]; } NS_ENDHANDLER; } while (repeatCommand); if (ProfileImapEnabled) { gettimeofday(&tv, NULL); ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0) - ti; fprintf(stderr, "}[%s] : time needed: %4.4fs\n", __PRETTY_FUNCTION__, ti < 0.0 ? -1.0 : ti); } return map; } - (NGHashMap *)processCommand:(id)_command { return [self processCommand:_command logText:_command]; } - (NSException *)sendCommand:(id)_command logText:(id)_txt { NSString *command = nil; if ((command = _command) == nil) /* missing command */ return nil; // TODO: return exception? /* log */ if (self->debug) { if ([_txt isKindOfClass:[NSData class]]) { fprintf(stderr, "C: "); fwrite([_txt bytes], [_txt length], 1, stderr); fputc('\n', stderr); } else fprintf(stderr, "C: %s\n", [_txt cStringUsingEncoding:NSUTF8StringEncoding]); } /* write */ if (![_command isKindOfClass:[NSData class]]) _command = [command dataUsingEncoding:NSUTF8StringEncoding]; if (![self->io safeWriteData:_command]) return [self->io lastException]; if (![self->io writeBytes:"\r\n" count:2]) return [self->io lastException]; if (![self->io flush]) return [self->io lastException]; return nil; } - (NSException *)sendCommand:(id)_command { return [self sendCommand:_command logText:_command]; } - (NSException *)sendCommand:(id)_command logText:(id)_txt attempts:(int)_c { NSException *ex; BOOL tryAgain; int repeatCnt; for (tryAgain = YES, repeatCnt = 0, ex = nil; tryAgain; repeatCnt++) { if (repeatCnt > 0) { if (repeatCnt > 1) /* one repeat goes without delay */ [self waitPriorReconnectWithRepetitionCount:repeatCnt]; [self reconnect]; tryAgain = NO; } NS_DURING ex = [self sendCommand:_command logText:_txt]; NS_HANDLER ex = [localException retain]; NS_ENDHANDLER; if (ex == nil) /* everything is fine */ break; if (repeatCnt > _c) /* reached max attempts */ break; /* try again for certain exceptions */ tryAgain = [self handleProcessException:ex repetitionCount:repeatCnt]; } return ex; } /* low level */ - (int)readByte { unsigned char c; if (![self->io readBytes:&c count:1]) { [self setLastException:[self->io lastException]]; return -1; } return c; } - (NSString *)readLiteral { /* Assumes 1st char is consumed, returns a retained string. Parses: "{" number [ "+" ] "}" CRLF *OCTET */ unsigned char countBuf[16]; int i; unsigned byteCount; unsigned char *octets; /* read count */ for (i = 0; i < 14; i++) { int c; if ((c = [self readByte]) == -1) return nil; if (c == '}') break; countBuf[i] = c; } countBuf[i] = '\0'; byteCount = i > 0 ? atoi((char *)countBuf) : 0; /* read CRLF */ i = [self readByte]; if (i != '\n') { if (i == '\r' && i != -1) i = [self readByte]; if (i == -1) return nil; } /* read octet */ if (byteCount == 0) return @""; octets = malloc(byteCount + 4); if (![self->io safeReadBytes:octets count:byteCount]) { [self setLastException:[self->io lastException]]; return nil; } octets[byteCount] = '\0'; return [[NSString alloc] initWithUTF8String:(char *)octets]; } - (NSString *)readQuoted { /* assumes 1st char is consumed, returns a retained string Note: quoted strings are limited to 1KB! */ unsigned char buf[1032]; int i, c; i = 0; do { c = [self readByte]; buf[i] = c; i++; } while ((c != -1) && (c != '"')); buf[i] = '\0'; if (c == -1) return nil; return [[NSString alloc] initWithUTF8String:(char *)buf]; } - (NSString *)readStringToCRLF { unsigned char buf[1032]; int i, c; i = 0; do { c = [self readByte]; if (c == '\n' || c == '\r') break; buf[i] = c; i++; } while ((c != -1) && (c != '\r') && (c != '\n') && (i < 1024)); buf[i] = '\0'; if (c == -1) return nil; /* consume CRLF */ if (c == '\r') { if ((c = [self readByte]) != '\n') { if (c == -1) return nil; [self logWithFormat:@"WARNING(%s): expected LF after CR, got: '%c'", __PRETTY_FUNCTION__, c]; return nil; } } return [[NSString alloc] initWithUTF8String:(char *)buf]; } - (NSString *)readString { /* Note: returns a retained string */ int c1; if ((c1 = [self readByte]) == -1) return nil; if (c1 == '"') return [self readQuoted]; if (c1 == '{') return [self readLiteral]; // Note: this does not return the first char! return [self readStringToCRLF]; } - (NSString *)readSieveName { return [self readString]; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if (self->socket != nil) [ms appendFormat:@" socket=%@", [self socket]]; else [ms appendFormat:@" address=%@", self->address]; [ms appendString:@">"]; return ms; } @end /* NGSieveClient */ SOPE/sope-mime/NGImap4/NGImap4Support.m0000644000000000000000000000207615004363604016374 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4Support.h" #include "NGImap4Client.h" #include "imCommon.h" @implementation NGImap4Exception @end @implementation NGImap4ConnectionException @end @implementation NGImap4ResponseException @end @implementation NGImap4SearchException @end @implementation NGImap4ParserException @end SOPE/sope-mime/NGImap4/NGImap4-Info.plist0000644000000000000000000000134015004363604016560 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable NGImap4 CFBundleGetInfoString CFBundleIdentifier org.OpenGroupware.SOPE.mime.NGImap4 CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType FMWK CFBundleShortVersionString CFBundleSignature ???? CFBundleVersion 4.5 SOPE/sope-mime/NGImap4/NGImap4ResponseNormalizer.h0000644000000000000000000000427615004363604020560 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGImap4_NGImap4ResponseNormalizer_H__ #define __NGImap4_NGImap4ResponseNormalizer_H__ #import @class NSDictionary, NSMutableDictionary; @class NGHashMap; @class NGImap4Client; @interface NGImap4ResponseNormalizer : NSObject { NGImap4Client *client; // non-retained } - (id)initWithClient:(NGImap4Client *)_client; /* primary */ - (NSMutableDictionary *)normalizeResponse:(NGHashMap *)_map; /* specific */ - (NSDictionary *)normalizeFetchResponse:(NGHashMap *)_map; - (NSDictionary *)normalizeOpenConnectionResponse:(NGHashMap *)_map; - (NSDictionary *)normalizeListResponse:(NGHashMap *)_map; - (NSDictionary *)normalizeListStatusResponse:(NGHashMap *)_map; - (NSDictionary *)normalizeSelectResponse:(NGHashMap *)_map; - (NSDictionary *)normalizeStatusResponse:(NGHashMap *)_map; - (NSDictionary *)normalizeSearchResponse:(NGHashMap *)_map; - (NSDictionary *)normalizeSortResponse:(NGHashMap *)_map; - (NSDictionary *)normalizeThreadResponse:(NGHashMap *)_map; - (NSDictionary *)normalizeCapabilityResponse:(NGHashMap *)_map; - (NSDictionary *)normalizeNamespaceResponse:(NGHashMap *)_map; - (NSDictionary *)normalizeQuotaResponse:(NGHashMap *)_map; /* ACL */ - (NSDictionary *)normalizeGetACLResponse:(NGHashMap *)_map; - (NSDictionary *)normalizeListRightsResponse:(NGHashMap *)_map; - (NSDictionary *)normalizeMyRightsResponse:(NGHashMap *)_map; @end #endif /* __NGImap4_NGImap4ResponseNormalizer_H__ */ SOPE/sope-mime/NGImap4/SxCore-NGImap4Flow.graffle0000644000000000000000000031552515004363604020210 0ustar rootroot CanvasColor a 1 w 1 ColumnAlign 0 ColumnSpacing 3.600000e+01 GraphDocumentVersion 2 GraphicsList Class LineGraphic Head ID 2312 ID 2369 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 rootFolder} LabelVisible YES Offset 0.000000e+00 Position 5.712345e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {698.143, 216} {702, 270} {612, 360} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2314 Bounds {{593, 501}, {170, 15}} Class ShapedGraphic FitText YES ID 2368 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 by helge.hess@opengroupware.org} Class LineGraphic Head ID 2312 ID 2367 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 currentFolder} LabelVisible YES Offset 0.000000e+00 Position 3.028804e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {686.571, 216} {621, 270} {604.636, 360} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2314 Class LineGraphic Head ID 2306 ID 2366 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 imapContext} LabelVisible YES Offset 0.000000e+00 Position 3.361621e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {639, 207} {549, 207} {450, 207} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2314 Class LineGraphic Head ID 2318 ID 2365 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 oldUnseenMessages} LabelVisible YES Offset 0.000000e+00 Position 6.675532e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {374.25, 486} {333, 441} {182.571, 387} Style stroke HeadArrow FilledDoubleArrow LineType 1 TailArrow 0 Tail ID 2361 Class LineGraphic Head ID 2318 ID 2364 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 messages} LabelVisible YES Offset 0.000000e+00 Position 4.175532e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {348, 486} {279, 468} {169.65, 387} Style stroke HeadArrow FilledDoubleArrow LineType 1 TailArrow 0 Tail ID 2361 Class LineGraphic Head ID 2312 ID 2363 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 folder} LabelVisible YES Offset 0.000000e+00 Position 4.270993e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {403.714, 486} {531, 432} {592.714, 378} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2361 Class LineGraphic Head ID 2312 ID 2362 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 subfolders} LabelVisible YES Offset 0.000000e+00 Position 4.958656e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {627, 378} {675, 396} {684, 360} {647.902, 364.011} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2312 Bounds {{324, 486}, {117, 18}} Class ShapedGraphic ID 2361 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4FileManager.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NGImap4DataSource} Class LineGraphic Head ID 2319 ID 2360 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 parser} LabelVisible YES Offset 0.000000e+00 Position 6.553997e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {354.157, 108} {437.776, 63} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2326 Class LineGraphic Head ID 2319 ID 2359 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 parser} LabelVisible YES Offset 0.000000e+00 Position 5.183397e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {594, 52.5681} {522, 53.3071} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2358 Bounds {{594, 45}, {81, 18}} Class ShapedGraphic ID 2358 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Client.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NGSieveClient} Class LineGraphic Head ID 2356 ID 2357 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 bodyStructureContent} LabelVisible YES Offset 0.000000e+00 Position 6.346480e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {162, 387} {198, 459} {150.75, 486} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2318 Bounds {{99, 486}, {72, 18}} Class ShapedGraphic ID 2356 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape RoundedRectangle Style fill Color a 1 b 0.5 g 1 r 1 Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NSDictionary} Bounds {{9, 432}, {63, 18}} Class ShapedGraphic ID 2355 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape RoundRect Style fill Color a 1 b 0.5 g 1 r 1 Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NSURL} Class LineGraphic Head ID 2312 ID 2354 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 folder} LabelVisible YES Offset 0.000000e+00 Position 1.303191e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {213.076, 386.55} {450, 423} {577.5, 378} Style stroke HeadArrow Arrow LineType 1 TailArrow 0 Tail ID 2318 Class LineGraphic Head ID 2352 ID 2353 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 headers} LabelVisible YES Offset 0.000000e+00 Position 6.187268e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {141.094, 369} {61.0156, 324} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2318 Bounds {{9, 306}, {72, 18}} Class ShapedGraphic ID 2352 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape RoundedRectangle Style fill Color a 1 b 0.5 g 1 r 1 Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NGHashMap} Class LineGraphic Head ID 2306 ID 2351 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 context} LabelVisible YES Offset 0.000000e+00 Position 5.607856e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {160.8, 369} {207, 243} {361.812, 214.852} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2318 Class LineGraphic Head ID 2349 ID 2350 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 rawData} LabelVisible YES Offset 0.000000e+00 Position 4.547872e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {114.75, 387} {72, 396} {51.75, 369} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2318 Bounds {{9, 351}, {72, 18}} Class ShapedGraphic ID 2349 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape RoundedRectangle Style fill Color a 1 b 0.5 g 1 r 1 Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NSData} Class LineGraphic Head ID 2346 ID 2348 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 bodyStructure} LabelVisible YES Offset 0.000000e+00 Position 8.856383e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {154.269, 387} {138.212, 432} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2318 Class LineGraphic Head ID 2345 ID 2347 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 message} LabelVisible YES Offset 0.000000e+00 Position 6.409575e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {152.975, 369} {130.496, 324} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2318 Bounds {{99, 432}, {72, 18}} Class ShapedGraphic ID 2346 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape RoundedRectangle Style fill Color a 1 b 0.5 g 1 r 1 Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NGMimePart} Bounds {{90, 306}, {72, 18}} Class ShapedGraphic ID 2345 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape RoundedRectangle Style fill Color a 1 b 0.5 g 1 r 1 Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NGMimePart} Class LineGraphic Head ID 2311 ID 2344 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 parentFolder} LabelVisible YES Offset 0.000000e+00 Position 8.111702e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {558, 371.647} {450, 378} {412.5, 333} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2312 Class LineGraphic Head ID 2306 ID 2343 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 context} LabelVisible YES Offset 0.000000e+00 Position 4.654255e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {601.2, 360} {576, 234} {449.035, 213.953} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2312 Class LineGraphic Head ID 2341 ID 2342 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 url} LabelVisible YES Offset 0.000000e+00 Position 5.496911e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {613.249, 378} {696.139, 450} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2312 Bounds {{675, 450}, {63, 18}} Class ShapedGraphic ID 2341 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape RoundRect Style fill Color a 1 b 0.5 g 1 r 1 Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NSURL} Class LineGraphic Head ID 2306 ID 2340 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 context} LabelVisible YES Offset 0.000000e+00 Position 3.962766e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {288, 342} {288, 270} {388.286, 216} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2310 Class LineGraphic Head ID 2312 ID 2339 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 subfolders} LabelVisible YES Offset 0.000000e+00 Position 1.356383e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {312, 360} {432, 405} {561.436, 377.75} Style stroke HeadArrow FilledDoubleArrow LineType 1 TailArrow 0 Tail ID 2310 Class LineGraphic Head ID 2337 ID 2338 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 address} LabelVisible YES Offset 0.000000e+00 Position 6.711531e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {336.899, 108} {333.9, 63} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2326 Bounds {{297, 36}, {72, 27}} Class ShapedGraphic ID 2337 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape RoundRect Style fill Color a 1 b 0.5 g 1 r 1 Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NGSocket\ Address} Class LineGraphic Head ID 2306 ID 2336 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 context} LabelVisible YES Offset 0.000000e+00 Position 5.311450e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {336.24, 126} {331.2, 162} {390.24, 198} Style stroke HeadArrow Arrow LineType 1 TailArrow 0 Tail ID 2326 Class LineGraphic Head ID 2307 ID 2335 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 responseReceiver} LabelVisible YES Offset 0.000000e+00 Position 4.381792e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {320.4, 126} {252, 162} {252, 189} Style stroke HeadArrow FilledDoubleArrow LineType 1 TailArrow 0 Tail ID 2326 Class LineGraphic Head ID 2332 ID 2334 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 text} LabelVisible YES Offset 0.000000e+00 Position 6.478347e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {305.906, 108} {201.257, 78.5482} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2326 Class LineGraphic Head ID 2330 ID 2333 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 source} LabelVisible YES Offset 0.000000e+00 Position 4.899368e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {162, 81} {162, 126} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2332 Bounds {{117, 54}, {90, 27}} Class ShapedGraphic ID 2332 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape RoundRect Style fill Color a 1 b 0.5 g 1 r 1 Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NGExtended\ TextStream} Class LineGraphic Head ID 2330 ID 2331 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 socket} LabelVisible YES Offset 0.000000e+00 Position 5.183075e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {297.102, 122.01} {197.362, 134.922} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2326 Bounds {{126, 126}, {72, 27}} Class ShapedGraphic ID 2330 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape RoundRect Style fill Color a 1 b 0.5 g 1 r 1 Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NGActive\ Socket} Class LineGraphic Head ID 2328 ID 2329 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 lastException} LabelVisible YES Offset 0.000000e+00 Position 7.845744e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {414, 198} {513, 99} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2306 Bounds {{477, 81}, {90, 18}} Class ShapedGraphic ID 2328 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape RoundRect Style fill Color a 1 b 0.5 g 1 r 1 Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NSException} Class LineGraphic Head ID 2326 ID 2327 Points {398.261, 198} {344.251, 126} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2306 Bounds {{297, 108}, {81, 18}} Class ShapedGraphic ID 2326 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Client.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NGImap4Client} Class LineGraphic Head ID 2310 ID 2325 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 serverRoot} LabelVisible YES Offset 0.000000e+00 Position 2.739362e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {397.685, 216} {295.312, 342} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2306 Class LineGraphic Head ID 2312 ID 2324 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 trashFolder\ sentFolder\ draftsFolder\ inboxFolder} LabelVisible YES Offset 0.000000e+00 Position 3.803191e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {423, 216} {549, 279} {597.6, 360} Style stroke HeadArrow Arrow LineType 1 TailArrow 0 Tail ID 2306 Class LineGraphic Head ID 2311 ID 2323 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 selectedFolder} LabelVisible YES Offset 0.000000e+00 Position 2.632979e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {412, 216} {468, 288} {420.75, 315} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2306 Class LineGraphic Head ID 2311 ID 2322 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 folderForRefresh} LabelVisible YES Offset 0.000000e+00 Position 7.526596e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {405, 216} {405, 315} Style stroke HeadArrow FilledDoubleArrow LineType 1 TailArrow 0 Tail ID 2306 Class LineGraphic Head ID 2320 ID 2321 Labels Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 connectionDictionary} LabelVisible YES Offset 0.000000e+00 Position 7.367021e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {422.053, 198} {541.421, 135} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2306 Bounds {{522, 108}, {90, 27}} Class ShapedGraphic ID 2320 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape RoundRect Style fill Color a 1 b 0.5 g 1 r 1 Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 Connection\ Dictionary} Bounds {{387, 45}, {135, 18}} Class ShapedGraphic ID 2319 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4ResponseParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NGImap4ResponseParser} Bounds {{99, 369}, {117, 18}} Class ShapedGraphic ID 2318 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Message.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NGImap4Message} Bounds {{675, 135}, {81, 18}} Class ShapedGraphic ID 2317 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape Rectangle Style fill Color a 1 b 0.5 g 1 r 1 stroke Color a 1 b 0 g 0 r 1 Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs20 \cf0 NGFileManager} Bounds {{675, 162}, {81, 18}} Class ShapedGraphic ID 2316 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape RoundedRectangle Style fill Color a 1 b 0.5 g 1 r 1 Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NGFileManager} Class LineGraphic Head ID 2316 ID 2315 Points {715.5, 153} {715.5, 162} Style stroke Color a 1 b 0 g 0 r 1 HeadArrow 0 TailArrow FilledBall Tail ID 2317 Bounds {{639, 198}, {117, 18}} Class ShapedGraphic ID 2314 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4FileManager.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NGImap4FileManager} Class LineGraphic Head ID 2314 ID 2313 Points {711, 180} {702, 198} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 2316 Bounds {{558, 360}, {90, 18}} Class ShapedGraphic ID 2312 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Folder.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NGImap4Folder} Bounds {{360, 315}, {90, 18}} Class ShapedGraphic ID 2311 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Support.h Shape Rectangle Style stroke Color a 1 b 0 g 0 r 1 Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs20 \cf0 NGImap4Folder} Bounds {{234, 342}, {108, 18}} Class ShapedGraphic ID 2310 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4ServerRoot.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NGImap4ServerRoot} Class LineGraphic Head ID 2312 ID 2309 Points {442.344, 333} {562.846, 360.002} Style stroke Color a 1 b 0 g 0 r 1 HeadArrow 0 TailArrow FilledBall Tail ID 2311 Class LineGraphic Head ID 2310 ID 2308 Points {375.979, 333} {331.99, 342} Style stroke Color a 1 b 0 g 0 r 1 HeadArrow 0 TailArrow FilledBall Tail ID 2311 Bounds {{180, 189}, {144, 18}} Class ShapedGraphic ID 2307 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Support.h Shape Rectangle Style stroke Color a 1 b 0 g 0 r 1 Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs20 \cf0 NGImap4ResponseReceiver} Bounds {{360, 198}, {90, 18}} Class ShapedGraphic ID 2306 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Context.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs20 \cf0 NGImap4Context} Class LineGraphic Head ID 2306 ID 2305 Points {324, 201.717} {360, 204.065} Style stroke Color a 1 b 0 g 0 r 1 HeadArrow 0 TailArrow FilledBall Tail ID 2307 Bounds {{8.75, 10}, {117, 36}} Class ShapedGraphic FitText YES ID 2304 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-BoldOblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\b\fs48 \cf0 NGImap4} Class LineGraphic Head ID 2355 ID 2303 Labels FixedWidth 2.300000e+01 Label Align 0 Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs20 \cf0 url} LabelVisible YES Offset 0.000000e+00 Position 7.302684e-01 Label Align 0 Offset 0.000000e+00 Position 1.000000e-01 Label Align 0 Offset 0.000000e+00 Position 9.000000e-01 Points {141.25, 387} {57.2917, 432} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 2318 GridInfo HPages 1 ImageCounter 1 IsPalette NO Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo AutoAdjust YES MagneticFieldCenter {0, 0} MagnetsEnabled YES PageBreakColor a 1 w 0.666667 PageBreaks YES PageSetup BAt0eXBlZHN0cmVhbYED6IQBQISEhAtOU1ByaW50SW5mbwGEhAhOU09iamVjdACFkoSE hBNOU011dGFibGVEaWN0aW9uYXJ5AISEDE5TRGljdGlvbmFyeQCUhAFpFJKEhIQITlNT dHJpbmcBlIQBKxBOU0pvYkRpc3Bvc2l0aW9uhpKEmZkPTlNQcmludFNwb29sSm9ihpKE mZkLTlNQYXBlclNpemWGkoSEhAdOU1ZhbHVlAJSEASqEhAx7X05TU2l6ZT1mZn2cgQNK gQJThpKEmZkZTlNQcmludFJldmVyc2VPcmllbnRhdGlvboaShISECE5TTnVtYmVyAJ2b hIQBc54AhpKEmZkUTlNWZXJ0aWNhbFBhZ2luYXRpb26GkoShm6KeAIaShJmZFE5TVmVy dGljYWxseUNlbnRlcmVkhpKEoZuingGGkoSZmQ5OU1BNUGFnZUZvcm1hdIaShISEBk5T RGF0YQCUl4ElUIQHWzk1NTJjXTw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVU Ri04Ij8+CjwhRE9DVFlQRSBwbGlzdCBQVUJMSUMgIi0vL0FwcGxlIENvbXB1dGVyLy9E VEQgUExJU1QgMS4wLy9FTiIgImh0dHA6Ly93d3cuYXBwbGUuY29tL0RURHMvUHJvcGVy dHlMaXN0LTEuMC5kdGQiPgo8cGxpc3QgdmVyc2lvbj0iMS4wIj4KPGRpY3Q+Cgk8a2V5 PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LkZvcm1hdHRpbmdQcmludGVyPC9rZXk+ Cgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5 PgoJCTxzdHJpbmc+Y29tLmFwcGxlLnByaW50aW5nbWFuYWdlcjwvc3RyaW5nPgoJCTxr ZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk+ CgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5Gb3Jt YXR0aW5nUHJpbnRlcjwva2V5PgoJCQkJPHN0cmluZz5ocDIyMDBkdG48L3N0cmluZz4K CQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jbGllbnQ8L2tleT4KCQkJCTxz dHJpbmc+Y29tLmFwcGxlLnByaW50aW5nbWFuYWdlcjwvc3RyaW5nPgoJCQkJPGtleT5j b20uYXBwbGUucHJpbnQudGlja2V0Lm1vZERhdGU8L2tleT4KCQkJCTxkYXRlPjIwMDQt MDEtMTVUMTU6NTQ6MzNaPC9kYXRlPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlj a2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI+MDwvaW50ZWdlcj4KCQkJPC9k aWN0PgoJCTwvYXJyYXk+Cgk8L2RpY3Q+Cgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdl Rm9ybWF0LlBNSG9yaXpvbnRhbFJlczwva2V5PgoJPGRpY3Q+CgkJPGtleT5jb20uYXBw bGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5w cmludGluZ21hbmFnZXI8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNr ZXQuaXRlbUFycmF5PC9rZXk+CgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk+Y29t LmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1Ib3Jpem9udGFsUmVzPC9rZXk+CgkJCQk8 cmVhbD43LjIwMDAwMDAwMDAwMDAwMGUrMDE8L3JlYWw+CgkJCQk8a2V5PmNvbS5hcHBs ZS5wcmludC50aWNrZXQuY2xpZW50PC9rZXk+CgkJCQk8c3RyaW5nPmNvbS5hcHBsZS5w cmludGluZ21hbmFnZXI8L3N0cmluZz4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRp Y2tldC5tb2REYXRlPC9rZXk+CgkJCQk8ZGF0ZT4yMDA0LTAxLTE1VDE0OjQ3OjQzWjwv ZGF0ZT4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tl eT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI+CgkJCTwvZGljdD4KCQk8L2FycmF5PgoJ PC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTU9yaWVudGF0 aW9uPC9rZXk+Cgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3Jl YXRvcjwva2V5PgoJCTxzdHJpbmc+Y29tLmFwcGxlLnByaW50aW5nbWFuYWdlcjwvc3Ry aW5nPgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4K CQk8YXJyYXk+CgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZv cm1hdC5QTU9yaWVudGF0aW9uPC9rZXk+CgkJCQk8aW50ZWdlcj4yPC9pbnRlZ2VyPgoJ CQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNsaWVudDwva2V5PgoJCQkJPHN0 cmluZz5jb20uYXBwbGUucHJpbnRpbmdtYW5hZ2VyPC9zdHJpbmc+CgkJCQk8a2V5PmNv bS5hcHBsZS5wcmludC50aWNrZXQubW9kRGF0ZTwva2V5PgoJCQkJPGRhdGU+MjAwNC0w MS0xNVQxNTo1NDozM1o8L2RhdGU+CgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNr ZXQuc3RhdGVGbGFnPC9rZXk+CgkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQk8L2Rp Y3Q+CgkJPC9hcnJheT4KCTwvZGljdD4KCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhZ2VG b3JtYXQuUE1TY2FsaW5nPC9rZXk+Cgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmlu dC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc+Y29tLmFwcGxlLnByaW50aW5n bWFuYWdlcjwvc3RyaW5nPgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVt QXJyYXk8L2tleT4KCQk8YXJyYXk+CgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUu cHJpbnQuUGFnZUZvcm1hdC5QTVNjYWxpbmc8L2tleT4KCQkJCTxyZWFsPjEuMDAwMDAw MDAwMDAwMDAwZSswMDwvcmVhbD4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tl dC5jbGllbnQ8L2tleT4KCQkJCTxzdHJpbmc+Y29tLmFwcGxlLnByaW50aW5nbWFuYWdl cjwvc3RyaW5nPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lm1vZERhdGU8 L2tleT4KCQkJCTxkYXRlPjIwMDQtMDEtMTVUMTU6NTQ6MzNaPC9kYXRlPgoJCQkJPGtl eT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVn ZXI+MDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk+Cgk8L2RpY3Q+Cgk8a2V5 PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxSZXM8L2tleT4KCTxk aWN0PgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk+CgkJ PHN0cmluZz5jb20uYXBwbGUucHJpbnRpbmdtYW5hZ2VyPC9zdHJpbmc+CgkJPGtleT5j b20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCTxhcnJheT4KCQkJ PGRpY3Q+CgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGlj YWxSZXM8L2tleT4KCQkJCTxyZWFsPjcuMjAwMDAwMDAwMDAwMDAwZSswMTwvcmVhbD4K CQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jbGllbnQ8L2tleT4KCQkJCTxz dHJpbmc+Y29tLmFwcGxlLnByaW50aW5nbWFuYWdlcjwvc3RyaW5nPgoJCQkJPGtleT5j b20uYXBwbGUucHJpbnQudGlja2V0Lm1vZERhdGU8L2tleT4KCQkJCTxkYXRlPjIwMDQt MDEtMTVUMTQ6NDc6NDNaPC9kYXRlPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlj a2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI+MDwvaW50ZWdlcj4KCQkJPC9k aWN0PgoJCTwvYXJyYXk+Cgk8L2RpY3Q+Cgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdl Rm9ybWF0LlBNVmVydGljYWxTY2FsaW5nPC9rZXk+Cgk8ZGljdD4KCQk8a2V5PmNvbS5h cHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc+Y29tLmFwcGxl LnByaW50aW5nbWFuYWdlcjwvc3RyaW5nPgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRp Y2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk+CgkJCTxkaWN0PgoJCQkJPGtleT5j b20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTVZlcnRpY2FsU2NhbGluZzwva2V5PgoJ CQkJPHJlYWw+MS4wMDAwMDAwMDAwMDAwMDBlKzAwPC9yZWFsPgoJCQkJPGtleT5jb20u YXBwbGUucHJpbnQudGlja2V0LmNsaWVudDwva2V5PgoJCQkJPHN0cmluZz5jb20uYXBw bGUucHJpbnRpbmdtYW5hZ2VyPC9zdHJpbmc+CgkJCQk8a2V5PmNvbS5hcHBsZS5wcmlu dC50aWNrZXQubW9kRGF0ZTwva2V5PgoJCQkJPGRhdGU+MjAwNC0wMS0xNVQxNTo1NDoz M1o8L2RhdGU+CgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuc3RhdGVGbGFn PC9rZXk+CgkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQk8L2RpY3Q+CgkJPC9hcnJh eT4KCTwvZGljdD4KCTxrZXk+Y29tLmFwcGxlLnByaW50LnN1YlRpY2tldC5wYXBlcl9p bmZvX3RpY2tldDwva2V5PgoJPGRpY3Q+CgkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFn ZUZvcm1hdC5QTUFkanVzdGVkUGFnZVJlY3Q8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5j b20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20u YXBwbGUucHJpbnRpbmdtYW5hZ2VyPC9zdHJpbmc+CgkJCTxrZXk+Y29tLmFwcGxlLnBy aW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q+CgkJ CQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTUFkanVzdGVkUGFnZVJl Y3Q8L2tleT4KCQkJCQk8YXJyYXk+CgkJCQkJCTxyZWFsPjAuMDAwMDAwMDAwMDAwMDAw ZSswMDwvcmVhbD4KCQkJCQkJPHJlYWw+MC4wMDAwMDAwMDAwMDAwMDBlKzAwPC9yZWFs PgoJCQkJCQk8cmVhbD41LjcwOTYwMDIxOTcyNjU2MmUrMDI8L3JlYWw+CgkJCQkJCTxy ZWFsPjguMTc0NDAwMDI0NDE0MDYyZSswMjwvcmVhbD4KCQkJCQk8L2FycmF5PgoJCQkJ CTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jbGllbnQ8L2tleT4KCQkJCQk8c3Ry aW5nPmNvbS5hcHBsZS5wcmludGluZ21hbmFnZXI8L3N0cmluZz4KCQkJCQk8a2V5PmNv bS5hcHBsZS5wcmludC50aWNrZXQubW9kRGF0ZTwva2V5PgoJCQkJCTxkYXRlPjIwMDQt MDEtMTVUMTU6NTQ6MzNaPC9kYXRlPgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRp Y2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJ PC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmlu dC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQk8ZGljdD4KCQkJ PGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmlu Zz5jb20uYXBwbGUucHJpbnRpbmdtYW5hZ2VyPC9zdHJpbmc+CgkJCTxrZXk+Y29tLmFw cGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRp Y3Q+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTUFkanVzdGVk UGFwZXJSZWN0PC9rZXk+CgkJCQkJPGFycmF5PgoJCQkJCQk8cmVhbD4tMS4yMDM5OTc4 MDI3MzQzNzVlKzAxPC9yZWFsPgoJCQkJCQk8cmVhbD4tMS4yNTU5OTk3NTU4NTkzNzVl KzAxPC9yZWFsPgoJCQkJCQk8cmVhbD41LjgyOTYwMDIxOTcyNjU2MmUrMDI8L3JlYWw+ CgkJCQkJCTxyZWFsPjguMjk0NDAwMDI0NDE0MDYyZSswMjwvcmVhbD4KCQkJCQk8L2Fy cmF5PgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jbGllbnQ8L2tleT4K CQkJCQk8c3RyaW5nPmNvbS5hcHBsZS5wcmludGluZ21hbmFnZXI8L3N0cmluZz4KCQkJ CQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQubW9kRGF0ZTwva2V5PgoJCQkJCTxk YXRlPjIwMDQtMDEtMTVUMTU6NTQ6MzNaPC9kYXRlPgoJCQkJCTxrZXk+Y29tLmFwcGxl LnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRl Z2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5h cHBsZS5wcmludC5QYXBlckluZm8uUE1Db25zdHJhaW5lZFBhcGVyPC9rZXk+CgkJPGRp Y3Q+CgkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk+CgkJ CTxzdHJpbmc+Q1VQU19DUEw8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQu dGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk+CgkJCQk8ZGljdD4KCQkJCQk8 a2V5PmNvbS5hcHBsZS5wcmludC5QYXBlckluZm8uUE1Db25zdHJhaW5lZFBhcGVyPC9r ZXk+CgkJCQkJPGZhbHNlLz4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQu Y2xpZW50PC9rZXk+CgkJCQkJPHN0cmluZz5DVVBTX0NQTDwvc3RyaW5nPgoJCQkJCTxr ZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5tb2REYXRlPC9rZXk+CgkJCQkJPGRhdGU+ MjAwNC0wMS0xNVQxNTo1NDoyNFo8L2RhdGU+CgkJCQkJPGtleT5jb20uYXBwbGUucHJp bnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjE8L2ludGVnZXI+ CgkJCQk8L2RpY3Q+CgkJCTwvYXJyYXk+CgkJPC9kaWN0PgoJCTxrZXk+Y29tLmFwcGxl LnByaW50LlBhcGVySW5mby5QTVBhcGVyTmFtZTwva2V5PgoJCTxkaWN0PgoJCQk8a2V5 PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPkNV UFNfQ1BMPC9zdHJpbmc+CgkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVt QXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q+CgkJCQkJPGtleT5jb20uYXBw bGUucHJpbnQuUGFwZXJJbmZvLlBNUGFwZXJOYW1lPC9rZXk+CgkJCQkJPHN0cmluZz5p c28tYTQ8L3N0cmluZz4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY2xp ZW50PC9rZXk+CgkJCQkJPHN0cmluZz5DVVBTX0NQTDwvc3RyaW5nPgoJCQkJCTxrZXk+ Y29tLmFwcGxlLnByaW50LnRpY2tldC5tb2REYXRlPC9rZXk+CgkJCQkJPGRhdGU+MjAw NC0wMS0xNVQxNTo1NDoyNFo8L2RhdGU+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQu dGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjE8L2ludGVnZXI+CgkJ CQk8L2RpY3Q+CgkJCTwvYXJyYXk+CgkJPC9kaWN0PgoJCTxrZXk+Y29tLmFwcGxlLnBy aW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCTxkaWN0PgoJ CQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3Ry aW5nPkNVUFNfQ1BMPC9zdHJpbmc+CgkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tl dC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q+CgkJCQkJPGtleT5j b20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNVW5hZGp1c3RlZFBhZ2VSZWN0PC9rZXk+ CgkJCQkJPGFycmF5PgoJCQkJCQk8cmVhbD4wLjAwMDAwMDAwMDAwMDAwMGUrMDA8L3Jl YWw+CgkJCQkJCTxyZWFsPjAuMDAwMDAwMDAwMDAwMDAwZSswMDwvcmVhbD4KCQkJCQkJ PHJlYWw+OC4xNzQ0MDAwMjQ0MTQwNjJlKzAyPC9yZWFsPgoJCQkJCQk8cmVhbD41Ljcw OTYwMDIxOTcyNjU2MmUrMDI8L3JlYWw+CgkJCQkJPC9hcnJheT4KCQkJCQk8a2V5PmNv bS5hcHBsZS5wcmludC50aWNrZXQuY2xpZW50PC9rZXk+CgkJCQkJPHN0cmluZz5DVVBT X0NQTDwvc3RyaW5nPgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5tb2RE YXRlPC9rZXk+CgkJCQkJPGRhdGU+MjAwNC0wMS0xNVQxNTo1NDoyNFo8L2RhdGU+CgkJ CQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJ CTxpbnRlZ2VyPjE8L2ludGVnZXI+CgkJCQk8L2RpY3Q+CgkJCTwvYXJyYXk+CgkJPC9k aWN0PgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQ YXBlclJlY3Q8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlj a2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5DVVBTX0NQTDwvc3RyaW5nPgoJCQk8 a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk+CgkJCTxhcnJh eT4KCQkJCTxkaWN0PgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhcGVySW5mby5Q TVVuYWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQkJCQk8YXJyYXk+CgkJCQkJCTxyZWFs Pi0xLjI1NTk5OTc1NTg1OTM3NWUrMDE8L3JlYWw+CgkJCQkJCTxyZWFsPi0xLjIwMDAw MDAwMDAwMDAwMGUrMDE8L3JlYWw+CgkJCQkJCTxyZWFsPjguMjk0NDAwMDI0NDE0MDYy ZSswMjwvcmVhbD4KCQkJCQkJPHJlYWw+NS44MzAwMDAwMDAwMDAwMDBlKzAyPC9yZWFs PgoJCQkJCTwvYXJyYXk+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNs aWVudDwva2V5PgoJCQkJCTxzdHJpbmc+Q1VQU19DUEw8L3N0cmluZz4KCQkJCQk8a2V5 PmNvbS5hcHBsZS5wcmludC50aWNrZXQubW9kRGF0ZTwva2V5PgoJCQkJCTxkYXRlPjIw MDQtMDEtMTVUMTU6NTQ6MjRaPC9kYXRlPgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50 LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4xPC9pbnRlZ2VyPgoJ CQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5w cmludC5QYXBlckluZm8ucHBkLlBNUGFwZXJOYW1lPC9rZXk+CgkJPGRpY3Q+CgkJCTxr ZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk+CgkJCTxzdHJpbmc+ Q1VQU19DUEw8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0 ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk+CgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5h cHBsZS5wcmludC5QYXBlckluZm8ucHBkLlBNUGFwZXJOYW1lPC9rZXk+CgkJCQkJPHN0 cmluZz5BNDwvc3RyaW5nPgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5j bGllbnQ8L2tleT4KCQkJCQk8c3RyaW5nPkNVUFNfQ1BMPC9zdHJpbmc+CgkJCQkJPGtl eT5jb20uYXBwbGUucHJpbnQudGlja2V0Lm1vZERhdGU8L2tleT4KCQkJCQk8ZGF0ZT4y MDA0LTAxLTE1VDE1OjU0OjI0WjwvZGF0ZT4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmlu dC50aWNrZXQuc3RhdGVGbGFnPC9rZXk+CgkJCQkJPGludGVnZXI+MTwvaW50ZWdlcj4K CQkJCTwvZGljdD4KCQkJPC9hcnJheT4KCQk8L2RpY3Q+CgkJPGtleT5jb20uYXBwbGUu cHJpbnQuUHJpbnRTZXR0aW5ncy5QTVBhcGVyQWRkZWRUb1N1Ym1lbnU8L2tleT4KCQk8 ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4K CQkJPHN0cmluZz5jb20uYXBwbGUucHJpbnRpbmdtYW5hZ2VyPC9zdHJpbmc+CgkJCTxr ZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5 PgoJCQkJPGRpY3Q+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUHJpbnRTZXR0aW5n cy5QTVBhcGVyQWRkZWRUb1N1Ym1lbnU8L2tleT4KCQkJCQk8dHJ1ZS8+CgkJCQkJPGtl eT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNsaWVudDwva2V5PgoJCQkJCTxzdHJpbmc+ Y29tLmFwcGxlLnByaW50aW5nbWFuYWdlcjwvc3RyaW5nPgoJCQkJCTxrZXk+Y29tLmFw cGxlLnByaW50LnRpY2tldC5tb2REYXRlPC9rZXk+CgkJCQkJPGRhdGU+MjAwNC0wMS0x NVQxNTo1NDoyOFo8L2RhdGU+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0 LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI+CgkJCQk8L2Rp Y3Q+CgkJCTwvYXJyYXk+CgkJPC9kaWN0PgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRp Y2tldC5BUElWZXJzaW9uPC9rZXk+CgkJPHN0cmluZz4wMC4yMDwvc3RyaW5nPgoJCTxr ZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5wcml2YXRlTG9jazwva2V5PgoJCTxmYWxz ZS8+CgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnR5cGU8L2tleT4KCQk8c3Ry aW5nPmNvbS5hcHBsZS5wcmludC5QYXBlckluZm9UaWNrZXQ8L3N0cmluZz4KCTwvZGlj dD4KCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5BUElWZXJzaW9uPC9rZXk+Cgk8 c3RyaW5nPjAwLjIwPC9zdHJpbmc+Cgk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQu cHJpdmF0ZUxvY2s8L2tleT4KCTxmYWxzZS8+Cgk8a2V5PmNvbS5hcHBsZS5wcmludC50 aWNrZXQudHlwZTwva2V5PgoJPHN0cmluZz5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1h dFRpY2tldDwvc3RyaW5nPgo8L2RpY3Q+CjwvcGxpc3Q+CoaShJmZD05TUHJpbnRBbGxQ YWdlc4aSoJKEmZkLTlNQYXBlck5hbWWGkoSZmQJBNIaShJmZFU5TSG9yaXpvbmFsUGFn aW5hdGlvboaShKGbop4AhpKEmZkWTlNIb3Jpem9udGFsbHlDZW50ZXJlZIaSppKEmZkJ TlNQcmludGVyhpKEhIQJTlNQcmludGVyAJSShJmZCWhwMjIwMGR0boaGkoSZmQhOU0Nv cGllc4aShKGbhIQBU6IBhpKEmZkPTlNTY2FsaW5nRmFjdG9yhpKEoZuEhAFmowGGkoSZ mQ1OU1JpZ2h0TWFyZ2luhpKEoZu5oySGkoSZmQ5OU0JvdHRvbU1hcmdpboaShKGbuaMk hpKEmZkMTlNMZWZ0TWFyZ2luhpKEoZu5oySGkoSZmQtOU1RvcE1hcmdpboaShKGbuaMk hpKEmZkKTlNMYXN0UGFnZYaShKGbhJeXgn////+GkoSZmQtOU0ZpcnN0UGFnZYaShKGb tqIBhpKEmZkNTlNPcmllbnRhdGlvboaShKGbop4BhoaG RowAlign 0 RowSpacing 3.600000e+01 VPages 1 WindowInfo Frame {{-4, 56}, {913, 794}} VisibleRegion {{-64, -97}, {898, 717}} Zoom 1 SOPE/sope-mime/NGImap4/COPYING0000644000000000000000000006130315004363604014453 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-mime/NGImap4/README0000644000000000000000000000613415004363604014301 0ustar rootrootNGImap4 Library =============== NSUserDefaults ============== Default | Type | Example Value ============================================================= ImapDebugEnabled BOOL NO ProfileImapEnabled BOOL NO ShowNonExistentFolder BOOL NO FetchNewUnseenMessagesInSubFoldersOnDemand BOOL NO ImapLogEnabled ImapPreventConnectionExceptions NGImapMaxConnectionCount ImapDebugQualifierGeneration ImapSortEncoding ImapSubscribedCouldFailed ShowOnlySubscribedInSubFolders Notifications ============= NGImap4DataSource - postDataSourceChangedNotification - observes: - LSWImapMailWasDeleted (resets DS) - LSWImapMailFolderWasDeleted (resets DS + folder) - LSWImapMailFlagsChanged (post DS changed notification) NGImap4Message - Update: this is now coordinated using a specialized notification mechanism attached to the folder - used to broadcast changes to messages with the same uid? - not reliable across accounts?! - posts: _addFlagNotificationName + _removeFlagNotificationName NGImap4MessageAddFlag_ + folder + uid NGImap4MessageRemoveFlag_ + folder + uid - observes: the above notifications (object is nil) NGImap4Folder - used to broadcast changes to folders with the same path? - not reliable across accounts?! - -resetFolder posts: "NGImap4FolderReset_" + [self absoluteName] - -resetSubFolders posts: "NGImap4SubFolderReset_" + [self absoluteName] - observes: the above notifications on its own folder name (object is nil) Parsing/Fetching ================ a) NGImap4Client issues fetch command and parses "raw" response b) NGImap4ResponseNormalizer "normalizes" the "raw" response to a dict (?) c) NGImap4Folder issues _buildMessagesFromFetch: - 'fetch' dict key contains array of 'normalized raw' entries - uses NGMimeMessageParser and NGDataStream to parse 'raw' header Notes ===== - folder hierarchies are cached and synchronized using a somewhat broken notification system - you can trigger a reload of the subfolders by calling -resetSubFolders, eg on the context's -serverRoot or -inboxFolder - TODO: find out whether this is a deep operation - resetSpecialFolders might also help, this 'nils' the default folders Class-Hierachy ============== NSObject NGImap4Client NGImap4Context NGImap4Folder NGImap4Message NGImap4ResponseParser NGImap4FolderFlags NGImap4FolderMailRegistry NSException NGImap4Exception NGImap4ConnectionException NGImap4ParserException NGImap4ResponseException NGImap4SearchException EODataSource NGImap4DataSource NGFileManager NGImap4FileManager Categories ========== Protocols ========= NGImap4ResponseReceiver Log Topics ========== -- Helge Hess (helge.hess@opengroupware.org) created, MDlink online service center, 1998-10-22 updated 2002-07-09 updated 2004-01-15 SOPE/sope-mime/NGImap4/NGImap4EnvelopeAddress.h0000644000000000000000000000335315004363604017775 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGImap4_NGImap4EnvelopeAddress_H__ #define __NGImap4_NGImap4EnvelopeAddress_H__ #import /* NGImap4EnvelopeAddress Wraps the raw mail address in the envelope as parsed from an IMAP4 fetch response. */ @class NSString, NSDictionary; @interface NGImap4EnvelopeAddress : NSObject < NSCopying > { @public NSString *personalName; NSString *sourceRoute; NSString *mailbox; NSString *host; } - (id)initWithPersonalName:(NSString *)_pname sourceRoute:(NSString *)_route mailbox:(NSString *)_mbox host:(NSString *)_host; - (id)initWithString:(NSString *)_str; - (id)initWithBodyStructureInfo:(NSDictionary *)_info; /* accessors */ - (NSString *)personalName; - (NSString *)sourceRoute; - (NSString *)mailbox; - (NSString *)host; /* derived accessors */ - (NSString *)baseEMail; /* returns just: mailbox@host */ - (NSString *)email; /* returns: personalName */ @end #endif /* __NGImap4_NGImap4EnvelopeAddress_H__ */ SOPE/sope-mime/NGImap4/imTimeMacros.h0000644000000000000000000000351515004363604016163 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if 0 #include #define TIME_START(_timeDescription) \ { \ struct timeval tv; \ double ti; \ char *timeDescription; \ unsigned int vm, vm1; \ \ *(&vm) = 0; \ *(&ti) = 0; \ {\ NSAutoreleasePool *p__1; \ p__1 = [NSAutoreleasePool new]; \ vm = [[NSProcessInfo processInfo] virtualMemorySize]; \ [p__1 release];\ }\ timeDescription = _timeDescription; \ gettimeofday(&tv, NULL); \ ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0 ); \ fprintf(stderr, "{"); \ #define TIME_END gettimeofday(&tv, NULL); \ gettimeofday(&tv, NULL); \ { \ NSAutoreleasePool *p__1 = [NSAutoreleasePool new]; \ vm1 = [[NSProcessInfo processInfo] virtualMemorySize]; \ [p__1 release]; \ }; \ ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0) - ti; \ fprintf(stderr,\ "}%s: <%s> : time needed: %4.4fs memory wasted %d absolut"\ " %d\n", __PRETTY_FUNCTION__, timeDescription, \ ti < 0.0 ? -1.0 : ti, vm1 - vm, vm1); \ } #else #define TIME_START(_timeDescription) #define TIME_END #endif SOPE/sope-mime/NGImap4/NGImap4MessageGlobalID.m0000644000000000000000000000457115004363604017644 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4MessageGlobalID.h" #include "imCommon.h" @implementation NGImap4MessageGlobalID + (id)imap4MessageGlobalIDWithFolderGlobalID:(EOGlobalID *)_gid andUid:(unsigned int)_uid { NGImap4MessageGlobalID *gid; gid = [[self alloc] initWithFolderGlobalID:_gid andUid:_uid]; return [gid autorelease]; } - (id)initWithFolderGlobalID:(EOGlobalID *)_gid andUid:(unsigned int)_uid { if ((self = [super init])) { self->folderGlobalID = [_gid retain]; self->uid = _uid; } return self; } - (id)init { return [self initWithFolderGlobalID:nil andUid:0]; } - (void)dealloc { [self->folderGlobalID release]; [super dealloc]; } /* accessors */ - (EOGlobalID *)folderGlobalID { return self->folderGlobalID; } - (unsigned int)uid { return self->uid; } /* comparison */ - (unsigned)hash { return self->uid; } - (BOOL)isEqualToImap4MessageGlobalID:(NGImap4MessageGlobalID *)_other { if (_other == nil) return NO; if (self == _other) return YES; if (self->uid != _other->uid) return NO; return (self->folderGlobalID == _other->folderGlobalID) ? YES : [self->folderGlobalID isEqual:_other->folderGlobalID]; } - (BOOL)isEqual:(id)_otherObject { if (_otherObject == self) return YES; if (![_otherObject isKindOfClass:[self class]]) return NO; return [self isEqualToImap4MessageGlobalID:_otherObject]; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { return [self retain]; } /* compatibility to some older stuff */ - (NSString *)entityName { return @"NGImap4Message"; } // TODO: emulate EOKeyGlobalID @end /* NGImap4MessageGlobalID */ SOPE/sope-mime/NGImap4/NGImap4DataSource.m0000644000000000000000000001643515004363604016756 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4DataSource.h" #include #include "imCommon.h" @interface NGImap4DataSource(PrivateMethodes) - (NSArray *)fetchMessages; @end @interface EOQualifier(IMAPAdditions) - (BOOL)isImap4UnseenQualifier; @end @implementation NGImap4DataSource static BOOL profileDS = NO; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; if ((profileDS = [ud boolForKey:@"ProfileImap4DataSource"])) NSLog(@"NGImap4DataSource: Profiling enabled!"); } - (NSNotificationCenter *)notificationCenter { static NSNotificationCenter *nc = nil; if (nc == nil) nc = [[NSNotificationCenter defaultCenter] retain]; return nc; } - (id)init { if ((self = [super init])) { NSNotificationCenter *nc = [self notificationCenter]; [nc addObserver:self selector:@selector(mailsWereDeleted:) name:@"LSWImapMailWasDeleted" object:nil]; [nc addObserver:self selector:@selector(folderWasMoved:) name:@"LSWImapMailFolderWasDeleted" object:nil]; [nc addObserver:self selector:@selector(flagsWereChanged:) name:@"LSWImapMailFlagsChanged" object:nil]; } return self; } - (id)initWithFolder:(NGImap4Folder *)_folder { if ((self = [self init])) { [self setFolder:_folder]; } return self; } - (void)dealloc { [[self notificationCenter] removeObserver:self]; [self->folder release]; [self->fspec release]; [self->messages release]; [self->oldUnseenMessages release]; [super dealloc]; } /* operations */ - (void)folderWasMoved:(id)_obj { [self->folder release]; self->folder = nil; [self->messages release]; self->messages = nil; [self->oldUnseenMessages release]; self->oldUnseenMessages = nil; } - (void)mailsWereDeleted:(id)_obj { [self->messages release]; self->messages = nil; [self->oldUnseenMessages release]; self->oldUnseenMessages = nil; } - (void)flagsWereChanged:(id)_obj { [self postDataSourceChangedNotification]; } - (NSArray *)fetchObjects { NSAutoreleasePool *pool; NSArray *tmp; if (self->messages) { if (profileDS) [self logWithFormat:@"fetchObjects: already fetched."]; return self->messages; } pool = [[NSAutoreleasePool alloc] init]; { if (profileDS) [self logWithFormat:@"fetchObjects: fetch ..."]; tmp = (self->folder != nil) ? [self fetchMessages] : (NSArray *)[NSArray array]; if (profileDS) [self logWithFormat:@"fetchObjects: done ..."]; ASSIGN(self->messages, tmp); } [pool release]; if (profileDS) [self logWithFormat:@"fetchObjects: pool released."]; return self->messages; } - (void)clear { if (profileDS) [self logWithFormat:@"clear: do ..."]; [self->messages release]; self->messages = nil; if (profileDS) [self logWithFormat:@"clear: done."]; } - (void)setFolder:(NGImap4Folder *)_folder { ASSIGN(self->folder, _folder); [self->messages release]; self->messages = nil; [self->oldUnseenMessages release]; self->oldUnseenMessages = nil; [self postDataSourceChangedNotification]; } - (NGImap4Folder *)folder { return self->folder; } - (void)setFetchSpecification:(EOFetchSpecification *)_fetchSpec { if ([_fetchSpec isEqual:self->fspec]) return; ASSIGN(self->fspec, _fetchSpec); [self->messages release]; self->messages = nil; [self postDataSourceChangedNotification]; } - (EOFetchSpecification *)fetchSpecification { return self->fspec; } - (int)oldExists { return self->oldExists; } - (int)oldUnseen { return self->oldUnseen; } /* private methodes */ - (NSException *)handleImapException:(NSException *)_exception { if ([_exception isKindOfClass:[NGImap4ResponseException class]]) { NSDictionary *record; NSString *str; record = [[_exception userInfo] objectForKey:@"RawResponse"]; record = [record objectForKey:@"ResponseResult"]; str = [record objectForKey:@"description"]; fprintf(stderr, "%s", [str cString]); } else if ([_exception isKindOfClass:[NGIOException class]]) { fprintf(stderr, "%s", [[_exception reason] cString]); } else if ([_exception isKindOfClass:[NGImap4Exception class]]) { fprintf(stderr, "%s", [[_exception description] cString]); } else { fprintf(stderr, "\n"); return _exception; } fprintf(stderr, "\n"); return nil; } - (NSArray *)_processUnseen:(NSArray *)result { if (profileDS) [self logWithFormat:@"process unseen ..."]; if (self->oldUnseenMessages) { // this implies, the folder hasn't changed NSMutableSet *set = nil; set = [[NSMutableSet alloc] initWithArray:result]; [set addObjectsFromArray:self->oldUnseenMessages]; result = [[[set allObjects] retain] autorelease]; [set release]; } [self->oldUnseenMessages release]; self->oldUnseenMessages = nil; ASSIGN(self->oldUnseenMessages, result); if (profileDS) [self logWithFormat:@"process unseen: done."]; return result; } - (NSArray *)_sortMessages:(NSArray *)result { NSArray *sortOrderings; if ((sortOrderings = [[self fetchSpecification] sortOrderings]) == nil) return result; if (profileDS) [self logWithFormat:@"sort messages ..."]; result = [result sortedArrayUsingKeyOrderArray:sortOrderings]; if (profileDS) [self logWithFormat:@"sort messages: done."]; return result; } - (NSArray *)fetchMessages { EOQualifier *qualifier; NSArray *result = nil; if (profileDS) [self logWithFormat:@"fetchMessages: fetch ..."]; qualifier = [[self fetchSpecification] qualifier]; NS_DURING { if (![qualifier isImap4UnseenQualifier]) { [self->oldUnseenMessages release]; self->oldUnseenMessages = nil; } if (profileDS) [self logWithFormat:@"fetchMessages: exists&unseen ..."]; self->oldExists = [self->folder exists]; self->oldUnseen = [self->folder unseen]; if (profileDS) [self logWithFormat:@"fetchMessages: messages ..."]; result = (qualifier == nil) ? [self->folder messages] : [self->folder messagesForQualifier:qualifier]; if (profileDS) [self logWithFormat:@"fetchMessages: messages done ..."]; } NS_HANDLER { [[self handleImapException:localException] raise]; result = [NSArray array]; } NS_ENDHANDLER; if (profileDS) [self logWithFormat:@"fetchMessages: ex handler done ..."]; if ([qualifier isImap4UnseenQualifier]) result = [self _processUnseen:result]; result = [self _sortMessages:result]; if (profileDS) [self logWithFormat:@"fetchMessages: done."]; return result; } @end /* NGImap4DataSource */ SOPE/sope-mime/NGImap4/NGImap4.m0000644000000000000000000000236715004363604015002 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // 6313727 #include "NGImap4.h" #include "NGImap4Client.h" #include "NGImap4ResponseParser.h" #include "NGImap4Folder.h" #include "NGImap4Message.h" #include "NGImap4Context.h" #import @implementation NGImap4 - (void)_staticLinkClasses { [NGImap4Client class]; [NGImap4ResponseParser class]; [NGImap4Folder class]; [NGImap4Message class]; [NGImap4Context class]; } - (void)_staticLinkModules { [NGImap4 class]; } @end SOPE/sope-mime/NGImap4/NGImap4MessageGlobalID.h0000644000000000000000000000267415004363604017641 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGImap4_NGImap4MessageGlobalID_H__ #define __NGImap4_NGImap4MessageGlobalID_H__ #include @interface NGImap4MessageGlobalID : EOGlobalID < NSCopying > { EOGlobalID *folderGlobalID; unsigned int uid; } + (id)imap4MessageGlobalIDWithFolderGlobalID:(EOGlobalID *)_gid andUid:(unsigned int)_uid; - (id)initWithFolderGlobalID:(EOGlobalID *)_gid andUid:(unsigned int)_uid; /* accessors */ - (EOGlobalID *)folderGlobalID; - (unsigned int)uid; /* comparison */ - (unsigned)hash; - (BOOL)isEqualToImap4MessageGlobalID:(NGImap4MessageGlobalID *)_other; - (BOOL)isEqual:(id)_otherObject; @end #endif /* __NGImap4_NGImap4MessageGlobalID_H__ */ SOPE/sope-mime/NGImap4/NGImap4FolderMailRegistry.h0000644000000000000000000000274515004363604020465 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGImap4_NGImap4FolderMailRegistry_H__ #define __NGImap4_NGImap4FolderMailRegistry_H__ #import @class NSString; @class NGImap4Message; /* NGImap4FolderMailRegistry Note: the registry does not retain the mails. */ @interface NGImap4FolderMailRegistry : NSObject { unsigned int capacity; unsigned int len; id *observers; } /* operations */ - (void)registerObject:(NGImap4Message *)_mail; - (void)forgetObject:(NGImap4Message *)_mail; /* notifications */ - (void)postFlagAdded:(NSString *)_flag inMessage:(NGImap4Message *)_msg; - (void)postFlagRemoved:(NSString *)_flag inMessage:(NGImap4Message *)_msg; @end #endif /* __NGImap4_NGImap4FolderMailRegistry_H__ */ SOPE/sope-mime/NGImap4/NGImap4Folder.h0000644000000000000000000001206215004363604016122 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __Networking_NGImap4_NGImap4Folder_H__ #define __Networking_NGImap4_NGImap4Folder_H__ #import #import #import #define USE_MESSAGE_CACHE 0 @class NSArray, NSString, NSMutableArray, NSNumber; @class EOGlobalID, EOQualifier; @class NGHashMap; @class NGImap4Context, NGImap4Message, NGImap4FolderMailRegistry; @class NGImap4FolderFlags; @interface NGImap4Folder : NSObject { @private NGImap4FolderFlags *flags; NSString *name; NSURL *url; EOGlobalID *globalID; NGImap4Context *context; NSArray *subFolders; NSArray *msn2UidCache; id parentFolder; // not retained NSNumber *isReadOnly; NSArray *messageFlags; int exists; int recent; int unseen; BOOL selectSyncState; int maxQuota; int usedSpace; int overQuota; struct { BOOL select:1; BOOL status:1; BOOL quota:1; } failedFlags; NGImap4FolderMailRegistry *mailRegistry; #if USE_MESSAGE_CACHE int cacheIdx; NSMutableArray *messages; NSMutableArray *qualifierCache; NSMutableArray *messagesCache; #endif } - (id)initWithContext:(NGImap4Context *)_context name:(NSString *)_name flags:(NSArray *)_flags parentFolder:(id)_folder; - (BOOL)isEqual:(id)_obj; - (BOOL)isEqualToImap4Folder:(NGImap4Folder *)_folder; /* accessors */ - (NGImap4Context *)context; - (NSException *)lastException; - (void)resetLastException; - (id)parentFolder; - (NSString *)name; - (NSString *)absoluteName; - (NSArray *)flags; - (NSData *)blobForUid:(unsigned)_mUid part:(NSString *)_part; - (NSArray *)fetchSortedMessages:(NSArray *)_so; - (void)bulkFetchHeadersFor:(NSArray *)_array inRange:(NSRange)_aRange; - (void)bulkFetchHeadersFor:(NSArray *)_array inRange:(NSRange)_aRange withAllUnread:(BOOL)_allUnread; - (NSArray *)fetchSortedMessages:(NSRange)_aRange sortOrderings:(NSArray *)_so; - (NSArray *)messageFlags; - (NSArray *)messages; - (NSArray *)messagesForQualifier:(EOQualifier *)_qualifier; - (NSArray *)messagesForQualifier:(EOQualifier *)_qualifier maxCount:(int)_cnt; - (NSArray *)subFolders; - (NGImap4Folder *)subFolderWithName:(NSString *)_name caseInsensitive:(BOOL)_caseIns; - (NGImap4Message *)messageForUid:(unsigned)_mUid sortOrderings:(NSArray *)_so onlyUnread:(BOOL)_unread nextMessage:(BOOL)_next; - (BOOL)isReadOnly; - (int)exists; - (int)recent; - (int)unseen; - (BOOL)noselect; - (BOOL)noinferiors; - (BOOL)nonexistent; - (BOOL)haschildren; - (BOOL)hasnochildren; - (BOOL)marked; - (BOOL)unmarked; /* this folder or its subfolders */ - (BOOL)hasNewMessagesSearchRecursiv:(BOOL)_recursiv; - (BOOL)hasUnseenMessagesSearchRecursiv:(BOOL)_recursiv; - (BOOL)hasNewMessagesSearchRecursiv:(BOOL)_rec fetchOnDemand:(BOOL)_fetch; - (BOOL)hasUnseenMessagesSearchRecursiv:(BOOL)_rec fetchOnDemand:(BOOL)_fetch; /* Notifications */ - (void)processResponse:(NSDictionary *)_dict; /* Actions */ - (BOOL)status; - (BOOL)select; /* if imm == YES syncState will be ignored */ - (BOOL)selectImmediately:(BOOL)_imm; - (void)expunge; - (BOOL)addFlag:(NSString *)_flag toMessages:(NSArray *)_messages; - (BOOL)removeFlag:(NSString *)_flag fromMessages:(NSArray *)_messages; - (BOOL)renameTo:(NSString *)_name; /* returns quota in kBytes */ - (int)usedSpace; - (int)maxQuota; - (BOOL)isOverQuota; /* evaluate ALERT sequences during select */ - (BOOL)deleteMessages:(NSArray *)_messages; - (BOOL)deleteAllMessages; - (BOOL)moveMessages:(NSArray *)_messages toFolder:(NGImap4Folder *)_folder; - (BOOL)copyMessages:(NSArray *)_messages toFolder:(NGImap4Folder *)_folder; - (BOOL)appendMessage:(NSData *)_msg; - (BOOL)deleteSubFolder:(NGImap4Folder *)_folder; - (BOOL)createSubFolderWithName:(NSString *)_name; - (BOOL)copySubFolder:(NGImap4Folder *)_f to:(NGImap4Folder *)_folder; - (BOOL)moveSubFolder:(NGImap4Folder *)_f to:(NGImap4Folder *)_folder; - (BOOL)isInTrash; - (void)resetFolder; - (void)resetSubFolders; - (void)resetStatus; - (void)resetSync; - (NSURL *)url; - (EOGlobalID *)serverGlobalID; - (EOGlobalID *)globalID; /* message factory */ - (id)messageWithUid:(unsigned int)_uid; /* message registry */ - (NGImap4FolderMailRegistry *)mailRegistry; @end #endif /* __Networking_NGImap4_NGImap4Folder_H__ */ SOPE/sope-mime/NGImap4/NGImap4Message.m0000644000000000000000000004565715004363604016320 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4Message.h" #include "NGImap4Folder.h" #include "NGImap4Context.h" #include "NGImap4Functions.h" #include "NGImap4Client.h" #include "NGImap4MessageGlobalID.h" #include "NGImap4FolderMailRegistry.h" #include #include "imCommon.h" #include "NGImap4Message+BodyStructure.h" @class NSNotification; @interface NGImap4Message(Internals) - (void)initializeMessage; - (void)fetchMessage; - (void)parseMessage; - (void)generateBodyStructure; - (NSString *)_addFlagNotificationName; - (NSString *)_removeFlagNotificationName; - (void)_removeFlag:(NSNotification *)_obj; - (void)_addFlag:(NSNotification *)_obj; - (void)setIsRead:(BOOL)_isRead; @end /* NGImap4Message(Internals) */ #define USE_OWN_GLOBAL_ID 1 @implementation NGImap4Message static Class NumClass = Nil; static NSNumber *YesNumber = nil; static NSNumber *NoNumber = nil; static NGMimeHeaderNames *Fields = NULL; static NSArray *CoreMsgAttrNames = nil; static NSArray *bodyNameArray = nil; static NSArray *rfc822NameArray = nil; static BOOL debugFlags = NO; static BOOL ImapDebugEnabled = NO; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; static BOOL didInit = NO; if (didInit) return; didInit = YES; NumClass = [NSNumber class]; YesNumber = [[NumClass numberWithBool:YES] retain]; NoNumber = [[NumClass numberWithBool:NO] retain]; Fields = (NGMimeHeaderNames *)[NGMimePartParser headerFieldNames]; CoreMsgAttrNames = [[NSArray alloc] initWithObjects:@"rfc822.header", @"rfc822.size", @"flags", nil]; bodyNameArray = [[NSArray alloc] initWithObjects:@"body", nil]; rfc822NameArray = [[NSArray alloc] initWithObjects:@"rfc822", nil]; ImapDebugEnabled = [ud boolForKey:@"ImapDebugEnabled"]; } - (id)initWithUid:(unsigned)_uid folder:(NGImap4Folder *)_folder context:(NGImap4Context *)_ctx { return [self initWithUid:_uid headers:nil size:-1 flags:nil folder:_folder context:_ctx]; } - (id)initWithUid:(unsigned)_uid headers:(NGHashMap *)_headers size:(unsigned)_size flags:(NSArray *)_flags folder:(NGImap4Folder *)_folder context:(NGImap4Context *)_ctx { if ((self = [super init])) { self->uid = _uid; self->size = _size; self->folder = _folder; self->headers = [_headers retain]; self->flags = [_flags retain]; self->context = [_ctx retain]; self->isRead = -1; if (self->folder) { // Note: we can safely retain the registry since it doesn't retain the // mails self->mailRegistry = [[self->folder mailRegistry] retain]; [self->mailRegistry registerObject:self]; } else [self logWithFormat:@"WARNING(-init): not attached to a folder!"]; } return self; } - (void)dealloc { if (self->mailRegistry) { [self->mailRegistry forgetObject:self]; [self->mailRegistry release]; } else [self logWithFormat:@"WARNING(-dealloc): not attached to a registry!"]; [self->headers release]; [self->flags release]; [self->context release]; [self->rawData release]; [self->message release]; [self->bodyStructure release]; [self->url release]; [self->bodyStructureContent release]; [self->globalID release]; [self->removeFlagNotificationName release]; [self->addFlagNotificationName release]; self->folder = nil; [super dealloc]; } /* internal methods */ - (void)_setHeaders:(NGHashMap *)_headers size:(unsigned)_size flags:(NSArray *)_flags { ASSIGN(self->headers, _headers); ASSIGN(self->flags, _flags); self->size = _size; } - (BOOL)isComplete { return (self->headers != nil) && (self->flags != nil); } /* accessors */ - (NSException *)lastException { return [self->context lastException]; } - (void)resetLastException { [self->context resetLastException]; } - (unsigned)uid { return self->uid; } - (NGHashMap *)headers { if (self->headers == nil) [self initializeMessage]; return self->headers; } - (int)size { if (self->size == -1) [self initializeMessage]; return self->size; } - (NSArray *)flags { if (self->flags == nil) [self initializeMessage]; return self->flags; } - (NSData *)rawData { if (self->rawData == nil) [self fetchMessage]; return self->rawData; } - (NSData *)contentsOfPart:(NSString *)_part { NSData *result; if (_part == nil) _part = @""; /* apparently caches the data for a part ID like "1.2.3" */ if (self->bodyStructureContent == nil) { self->bodyStructureContent = [[NSMutableDictionary alloc] initWithCapacity:8]; } if ((result = [self->bodyStructureContent objectForKey:_part]) == nil) { if ((result = [self->folder blobForUid:self->uid part:_part]) != nil) [self->bodyStructureContent setObject:result forKey:_part]; } return result; } - (id)bodyStructure { if (self->bodyStructure == nil) [self generateBodyStructure]; return self->bodyStructure; } - (id)message { if (self->message == nil) [self parseMessage]; return self->message; } - (NGImap4Folder *)folder { return self->folder; } - (NGImap4Context *)context { return self->context; } - (BOOL)isRead { if ((self->flags == nil) && (self->isRead != -1)) return (self->isRead == 1) ? YES : NO; return [[self flags] containsObject:@"seen"]; } - (void)markRead { if (![self isRead]) [self addFlag:@"seen"]; [self removeFlag:@"recent"]; } - (void)markUnread { if ([self isRead]) [self removeFlag:@"seen"]; } - (BOOL)isFlagged { return [[self flags] containsObject:@"flagged"]; } - (void)markFlagged { if (![self isFlagged]) [self addFlag:@"flagged"]; } - (void)markUnFlagged { if ([self isFlagged]) { [self removeFlag:@"flagged"]; } } - (BOOL)isAnswered { return [[self flags] containsObject:@"answered"]; } - (void)markAnswered { if (![self isAnswered]) [self addFlag:@"answered"]; } - (void)markNotAnswered { if ([self isAnswered]) [self removeFlag:@"answered"]; } - (void)addFlag:(NSString *)_flag { NSDictionary *res; if (_flag == nil) return; if (self->mailRegistry) [self->mailRegistry postFlagAdded:_flag inMessage:self]; else [self logWithFormat:@"WARNING(-addFlag:): no folder attached to message!"]; if (![[self->folder messageFlags] containsObject:_flag]) return; if (![self->context registerAsSelectedFolder:self->folder]) return; res = [[self->context client] storeUid:self->uid add:YesNumber flags:[NSArray arrayWithObject:_flag]]; if (!_checkResult(self->context, res, __PRETTY_FUNCTION__)) return; [self->folder resetStatus]; } - (void)removeFlag:(NSString *)_flag { NSDictionary *res; if (_flag == nil) return; if (self->mailRegistry) [self->mailRegistry postFlagRemoved:_flag inMessage:self]; else [self logWithFormat:@"WARNING(-remFlag:): no folder attached to message!"]; if (![[self->folder messageFlags] containsObject:_flag]) return; if (![self->context registerAsSelectedFolder:self->folder]) return; res = [[self->context client] storeUid:self->uid add:NoNumber flags:[NSArray arrayWithObject:_flag]]; if (!_checkResult(self->context, res, __PRETTY_FUNCTION__)) return; [self->folder resetStatus]; } /* equality */ - (BOOL)isEqual:(id)_obj { if (_obj == self) return YES; if ([_obj isKindOfClass:[NGImap4Message class]]) return [self isEqualToNGImap4Message:_obj]; return NO; } - (BOOL)isEqualToNGImap4Message:(NGImap4Message *)_messages { if ([_messages uid] != self->uid) return NO; if (![[_messages context] isEqual:self->context]) return NO; if (![[_messages folder] isEqual:self->folder]) return NO; return YES; } - (NSUInteger)hash { return self->uid; } - (EOGlobalID *)globalID { #if USE_OWN_GLOBAL_ID EOGlobalID *fgid; if (self->globalID) return self->globalID; if ((fgid = [[self folder] globalID]) == nil) { [self logWithFormat:@"WARNING(-globalID): got no globalID for folder: %@", [self folder]]; } self->globalID = [[NGImap4MessageGlobalID alloc] initWithFolderGlobalID:fgid andUid:[self uid]]; return self->globalID; #else id keys[4]; if (self->globalID) return self->globalID; // TODO: this needs to be invalidated, if a folder is moved! keys[0] = [NumClass numberWithUnsignedInt:[self uid]]; keys[1] = [[self folder] absoluteName]; keys[2] = [[self context] host]; keys[3] = [[self context] login]; globalID = [[EOKeyGlobalID globalIDWithEntityName:@"NGImap4Message" keys:keys keyCount:4 zone:NULL] retain]; return globalID; #endif } /* key-value coding */ - (id)valueForKey:(NSString *)_key { // TODO: might want to add some more caching unsigned len; id v = nil; if ((len = [_key length]) == 0) return nil; if ([_key characterAtIndex:0] == 'N') { if (len < 9) ; else if ([_key isEqualToString:@"NSFileIdentifier"]) v = [[self headers] objectForKey:Fields->messageID]; else if ([_key isEqualToString:NSFileSize]) v = [NumClass numberWithInt:[self size]]; else if ([_key isEqualToString:NSFileModificationDate]) v = [[self headers] objectForKey:Fields->date]; else if ([_key isEqualToString:NSFileType]) v = NSFileTypeRegular; else if ([_key isEqualToString:NSFileOwnerAccountName]) v = [self->context login]; else if ([_key isEqualToString:@"NGFileSubject"]) v = [[self headers] objectForKey:Fields->subject]; else if ([_key isEqualToString:@"NSFileSubject"]) v = [[self headers] objectForKey:Fields->subject]; else if ([_key isEqualToString:@"NGFilePath"]) v = [NSString stringWithFormat:@"%@/%d", [self->folder absoluteName], [self uid]]; else if ([_key isEqualToString:@"url"]) v = [self url]; if (v) return v; } if ((v = [[self headers] objectForKey:_key])) return v; return [super valueForKey:_key]; } /* description */ - (NSString *)description { NSMutableString *ms; id tmp; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; [ms appendFormat:@" uid=%d size=%d", self->uid, self->size]; if (self->headers != nil) { tmp = [[self headers] objectForKey:@"subject"]; if ([tmp isNotEmpty]) [ms appendFormat:@" subject='%@'", tmp]; else [ms appendString:@" no-subject"]; } else { [ms appendString:@" [header not fetched]"]; } tmp = [self->folder absoluteName]; if (tmp) [ms appendFormat:@" folder='%@'", tmp]; if (self->flags) { tmp = [self flags]; if ([tmp isNotEmpty]) [ms appendFormat:@"flags: (%@)", [tmp componentsJoinedByString:@", "]]; else [ms appendString:@"no-flags"]; } else [ms appendString:@" [flags not fetched]"]; [ms appendString:@">"]; return ms; } - (NSURL *)url { NSURL *base; NSString *path, *s; char buf[64]; if (self->url) return self->url; base = [self->folder url]; sprintf(buf, "%d", [self uid]); s = [[NSString alloc] initWithCString:buf]; path = [[base path] stringByAppendingPathComponent:s]; [s release]; self->url = [[NSURL alloc] initWithScheme:[base scheme] host:[base host] path:path]; return self->url; } /* Internals */ - (void)initializeMessage { NSDictionary *dict; NSDictionary *fetch; NSAutoreleasePool *pool; pool = [[NSAutoreleasePool alloc] init]; if (![self->context registerAsSelectedFolder:self->folder]) return; [self resetLastException]; dict = [[self->context client] fetchUid:self->uid parts:CoreMsgAttrNames]; if (!_checkResult(self->context, dict, __PRETTY_FUNCTION__)) return; fetch = [[[dict objectForKey:@"fetch"] objectEnumerator] nextObject]; if (fetch == nil) { NSLog(@"WARNING[%s] : couldn`t fetch message with id %d", __PRETTY_FUNCTION__, self->uid); return; } { id h, f, s; NGMimeMessageParser *parser; NGDataStream *stream; h = [fetch objectForKey:@"header"]; f = [fetch objectForKey:@"flags"]; s = [fetch objectForKey:@"size"]; if ((h == nil) || (f == nil) || (s == nil)) { NSLog(@"WARNING[%s]: got no header, flags, size for %@", __PRETTY_FUNCTION__, fetch); return; } parser = [[[NGMimeMessageParser alloc] init] autorelease]; stream = [[[NGDataStream alloc] initWithData:h] autorelease]; [parser prepareForParsingFromStream:stream]; ASSIGN(self->headers, [parser parseHeader]); self->size = [s intValue]; if (([f containsObject:@"recent"]) && ([f containsObject:@"seen"])) { f = [[f mutableCopy] autorelease]; [f removeObject:@"recent"]; } ASSIGNCOPY(self->flags, f); } [pool release]; pool = nil; } - (void)fetchMessage { NSDictionary *dict, *fetch; if (![self->context registerAsSelectedFolder:self->folder]) return; [self resetLastException]; dict = [[self->context client] fetchUid:self->uid parts:rfc822NameArray]; if (!_checkResult(self->context, dict, __PRETTY_FUNCTION__)) return; fetch = [[[dict objectForKey:@"fetch"] objectEnumerator] nextObject]; if (fetch == nil) { NSLog(@"WARNING[%s]: couldn`t fetch message with id %d", __PRETTY_FUNCTION__, self->uid); return; } ASSIGN(self->rawData, [fetch objectForKey:@"message"]); } - (void)_processBodyStructureEncoding:(NSDictionary *)bStruct { NGHashMap *orgH; NGMutableHashMap *h; orgH = [self headers]; if ([[orgH objectForKey:@"encoding"] isNotEmpty]) return; h = [[self headers] mutableCopy]; [h setObject:[[bStruct objectForKey:@"encoding"] lowercaseString] forKey:@"content-transfer-encoding"]; ASSIGNCOPY(self->headers, h); [h release]; } - (void)generateBodyStructure { NSDictionary *dict, *bStruct; NSArray *fetchResponses; [self->bodyStructure release]; self->bodyStructure = nil; [self resetLastException]; if (![self->context registerAsSelectedFolder:self->folder]) return; dict = [[self->context client] fetchUid:self->uid parts:bodyNameArray]; if (!(_checkResult(self->context, dict, __PRETTY_FUNCTION__))) return; /* TODO: the following seems to fail with Courier, see OGo bug #800: ---snip--- C[0x8b4e754]: 27 uid fetch 635 (body) S[0x8c8b4e4]: * 627 FETCH (UID 635 BODY ("text" "plain" ("charset" "iso-8859-1" "format" "flowed") NIL NIL "8bit" 2474 51)) S[0x8c8b4e4]: * 627 FETCH (FLAGS (\Seen)) S[0x8c8b4e4]: 27 OK FETCH completed. Jun 26 18:38:15 OpenGroupware [30904]: <0x08A73DCC[NGImap4Message]> WARNING[-[NGImap4Message generateBodyStructure]]: could not fetch body of message with id 635 */ fetchResponses = [dict objectForKey:@"fetch"]; if ([fetchResponses count] == 1) { /* like with Cyrus, "old" behaviour */ bStruct = [(NSDictionary *)[fetchResponses lastObject] objectForKey:@"body"]; } else if (![fetchResponses isNotEmpty]) { /* no results */ bStruct = nil; } else { /* need to scan for the 'body' response, Courier 'behaviour' */ NSEnumerator *e; NSDictionary *response; bStruct = nil; e = [fetchResponses objectEnumerator]; while ((response = [e nextObject])) { if ((bStruct = [response objectForKey:@"body"]) != nil) break; } } if (bStruct == nil) { [self logWithFormat: @"WARNING[%s]: could not fetch body of message with id %d.", __PRETTY_FUNCTION__, self->uid]; if (ImapDebugEnabled) { [self logWithFormat:@" raw: %@", dict]; [self logWithFormat:@" fetch: %@", [dict objectForKey:@"fetch"]]; [self logWithFormat:@" last: %@", [[dict objectForKey:@"fetch"] lastObject]]; } return; } /* set encoding */ if ([[bStruct objectForKey:@"encoding"] isNotEmpty]) [self _processBodyStructureEncoding:bStruct]; self->bodyStructure = [[NGMimeMessage alloc] initWithHeader:[self headers]]; [self->bodyStructure setBody: _buildMimeMessageBody(self, [self url], bStruct, self->bodyStructure)]; } - (void)parseMessage { NGMimeMessageParser *parser; parser = [[NGMimeMessageParser alloc] init]; ASSIGN(self->message, [parser parsePartFromData:[self rawData]]); [parser release]; } /* flag notifications */ - (NSString *)_addFlagNotificationName { if (self->addFlagNotificationName) return self->addFlagNotificationName; self->addFlagNotificationName = [[NSString alloc] initWithFormat:@"NGImap4MessageAddFlag_%@_%d", [[self folder] absoluteName], self->uid]; return self->addFlagNotificationName; } - (NSString *)_removeFlagNotificationName { if (self->removeFlagNotificationName) return self->removeFlagNotificationName; self->removeFlagNotificationName = [[NSString alloc] initWithFormat:@"NGImap4MessageRemoveFlag_%@_%d", [[self folder] absoluteName], self->uid]; return self->removeFlagNotificationName; } - (void)_removeFlag:(NSNotification *)_notification { NSMutableArray *tmp; NSString *flag; flag = [[_notification userInfo] objectForKey:@"flag"]; if (debugFlags) [self logWithFormat:@"_del flag: %@", flag]; if (![self->flags containsObject:flag]) { if (debugFlags) [self logWithFormat:@" not set."]; return; } tmp = [self->flags mutableCopy]; [tmp removeObject:flag]; ASSIGNCOPY(self->flags, tmp); [tmp release]; } - (void)_addFlag:(NSNotification *)_notification { NSArray *tmp; NSString *flag; flag = [[_notification userInfo] objectForKey:@"flag"]; if (debugFlags) [self logWithFormat:@"_add flag: %@", flag]; if ([self->flags containsObject:flag]) { if (debugFlags) [self logWithFormat:@" already set."]; return; } tmp = self->flags; self->flags = [[self->flags arrayByAddingObject:flag] copy]; [tmp release]; } - (void)setIsRead:(BOOL)_isRead { self->isRead = (_isRead)?1:0; } @end /* NGImap4Message */ SOPE/sope-mime/NGImap4/NGImap4ConnectionManager.m0000644000000000000000000001675515004363604020323 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of OpenGroupware.org. OGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. OGo 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with OGo; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4ConnectionManager.h" #include "NGImap4Connection.h" #include "NGImap4Client.h" #include "imCommon.h" @implementation NGImap4ConnectionManager static BOOL debugOn = NO; static BOOL debugCache = NO; static BOOL poolingOff = NO; static NSTimeInterval PoolScanInterval = 5 * 60 /* every five minutes */; static NSString *AuthMechanism = nil; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; debugOn = [ud boolForKey:@"NGImap4EnableIMAP4Debug"]; debugCache = [ud boolForKey:@"NGImap4EnableIMAP4CacheDebug"]; poolingOff = [ud boolForKey:@"NGImap4DisableIMAP4Pooling"]; AuthMechanism = [ud stringForKey:@"NGImap4AuthMechanism"]; [AuthMechanism retain]; if ([ud objectForKey:@"NGImap4PoolingCleanupInterval"]) PoolScanInterval = [[ud objectForKey:@"NGImap4PoolingCleanupInterval"] doubleValue]; //if (debugOn) NSLog(@"Note: NGImap4EnableIMAP4Debug is enabled!"); //if (poolingOff) NSLog(@"WARNING: IMAP4 connection pooling is disabled!"); } + (id)defaultConnectionManager:(NSString *) imapAuthMech { static NGImap4ConnectionManager *manager = nil; // THREAD static NGImap4ConnectionManager *managerXoauth = nil; // THREAD //In case of diffrent auth type for domains, instantiate the proper imap object. if(imapAuthMech && [imapAuthMech length] > 0) { if([imapAuthMech isEqualToString: @"xoauth2"]) { if(managerXoauth == nil) { managerXoauth = [[self alloc] init]; AuthMechanism = imapAuthMech; } return managerXoauth; } if([imapAuthMech isEqualToString: @"plain"]) { if(manager == nil) { manager = [[self alloc] init]; AuthMechanism = imapAuthMech; } return manager; } } else if (manager == nil) manager = [[self alloc] init]; return manager; } - (id)init { if ((self = [super init])) { if (!poolingOff) { self->urlToEntry = [[NSMutableDictionary alloc] initWithCapacity:256]; self->gcTimer = [[NSTimer scheduledTimerWithTimeInterval: PoolScanInterval target:self selector:@selector(_garbageCollect:) userInfo:nil repeats:YES] retain]; } } return self; } - (void)dealloc { [self->gcTimer invalidate]; [self->urlToEntry release]; [self->gcTimer release]; [super dealloc]; } /* cache */ - (id)cacheKeyForURL:(NSURL *)_url { // protocol, user, host, port return [NSString stringWithFormat:@"%@://%@@%@:%@", [_url scheme], [_url user], [_url host], [_url port]]; } - (NGImap4Connection *)entryForURL:(NSURL *)_url { if (_url == nil) return nil; return [self->urlToEntry objectForKey:[self cacheKeyForURL:_url]]; } - (void)cacheEntry:(NGImap4Connection *)_entry forURL:(NSURL *)_url { if (_entry == nil) _entry = (id)[NSNull null]; [self->urlToEntry setObject:_entry forKey:[self cacheKeyForURL:_url]]; } - (void)_garbageCollect:(NSTimer *)_timer { // TODO: scan for old IMAP4 channels NGImap4Connection *entry; NSDate *now; NSArray *a; int i; a = [self->urlToEntry allKeys]; now = [NSDate date]; for (i = 0; i < [a count]; i++) { entry = [self->urlToEntry objectForKey: [a objectAtIndex: i]]; if ([now timeIntervalSinceDate: [entry creationTime]] > PoolScanInterval) { [[entry client] logout]; [self->urlToEntry removeObjectForKey: [a objectAtIndex: i]]; } } [self debugWithFormat:@"should collect IMAP4 channels (%d active)", [self->urlToEntry count]]; } - (NGImap4Connection *)connectionForURL:(NSURL *)_url password:(NSString *)_p { /* Three cases: a) not yet connected => create new entry and connect b) connected, correct password => return cached entry c) connected, different password => try to recreate entry */ NGImap4Connection *entry; NGImap4Client *client; if (poolingOff) { client = [self imap4ClientForURL:_url password:_p]; entry = [[NGImap4Connection alloc] initWithClient:client password:_p]; return [entry autorelease]; } else { /* check cache */ if ((entry = [self entryForURL:_url]) != nil) { if ([entry isValidPassword:_p]) { if (debugCache) [self logWithFormat:@"valid password, reusing cache entry ..."]; return entry; } /* different password, password could have changed! */ if (debugCache) [self logWithFormat:@"different password than cached entry: %@", _url]; entry = nil; } else [self debugWithFormat:@"no connection cached yet for url: %@", _url]; /* try to login */ client = [entry isValidPassword:_p] ? [entry client] : [self imap4ClientForURL:_url password:_p]; if (client == nil) return nil; /* sideeffect of -imap4ClientForURL:password: is to create a cache entry */ return [self entryForURL:_url]; } } /* client object */ - (NGImap4Client *)imap4ClientForURL:(NSURL *)_url password:(NSString *)_pwd { // TODO: move to some global IMAP4 connection pool manager NGImap4Connection *entry; NGImap4Client *client; NSDictionary *result; if (_url == nil) return nil; /* check connection pool */ if ((entry = [self entryForURL:_url]) != nil) { if ([entry isValidPassword:_pwd]) { [self debugWithFormat:@"reused IMAP4 connection for URL: %@", _url]; return [entry client]; } /* different password, password could have changed! */ entry = nil; } /* setup connection and attempt login */ if ((client = [NGImap4Client clientWithURL:_url]) == nil) return nil; if (AuthMechanism) result = [client authenticate:[_url user] password:_pwd mechanism:AuthMechanism]; else result = [client login:[_url user] password:_pwd]; if (![[result valueForKey:@"result"] boolValue]) { [self errorWithFormat: @"IMAP4 login failed:\n" @" host=%@, user=%@, pwd=%s\n" @" url=%@\n base=%@\n base-class=%@)\n" @" = %@", [_url host], [_url user], [_pwd length] > 0 ? "yes" : "no", [_url absoluteString], [_url baseURL], NSStringFromClass([[_url baseURL] class]), client]; return nil; } [self debugWithFormat:@"created new IMAP4 connection for URL: %@", _url]; /* cache connection in pool */ entry = [[NGImap4Connection alloc] initWithClient:client password:_pwd]; [self cacheEntry:entry forURL:_url]; [entry release]; entry = nil; return client; } - (void)flushCachesForURL:(NSURL *)_url { NGImap4Connection *entry; if ((entry = [self entryForURL:_url]) == nil) /* nothing cached */ return; [entry flushFolderHierarchyCache]; [entry flushMailCaches]; } /* debugging */ - (BOOL)isDebuggingEnabled { return debugOn; } @end /* NGImap4ConnectionManager */ SOPE/sope-mime/NGImap4/NGImap4ResponseParser.h0000644000000000000000000000311115004363604017655 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __OGo_NGImap4_NGImap4ResponseParser_H__ #define __OGo_NGImap4_NGImap4ResponseParser_H__ #import #import #include #include @class NSString, NSException, NSMutableString; @class NGHashMap, NGByteBuffer; @interface NGImap4ResponseParser : NSObject { NGByteBuffer *buffer; BOOL debug; NSMutableString *lineDebug; int (*la)(id, SEL, unsigned); NSMutableString *serverResponseDebug; } + (id)parserWithStream:(id)_stream; - (id)initWithStream:(id)_stream; /* parsing */ - (NGHashMap *)parseResponseForTagId:(int)_tag exception:(NSException **)e_; - (NGHashMap *)parseSieveResponse; @end #endif /* __OGo_NGImap4_NGImap4ResponseParser_H__ */ SOPE/sope-mime/NGImap4/NSString+Imap4.m0000644000000000000000000001602515004363604016254 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #include #include "imCommon.h" @implementation NSString(Imap4) static unsigned int _encodeToModifiedUTF7(unichar *_char, unsigned char *result_, unsigned int *cntRes_); static unsigned int _decodeOfModifiedUTF7(unsigned char *_source, unichar *result_, unsigned int *cntRes_ ); - (NSString *)stringByEncodingImap4FolderName { unichar *buf = NULL; unsigned char *res = NULL; unsigned int len = 0; unsigned int cnt = 0; unsigned int cntRes = 0; NSString *result = nil; /* do real work only if we're not already 7bit safe */ if ([self is7bitSafe]) return [[self copy] autorelease]; len = [self length]; buf = NSZoneMalloc(NULL, (len + 1) * sizeof(unichar)); [self getCharacters: buf]; buf[len] = 0; /* 1 * '&', 3 for the max bytes / char, 1 * '-' */ res = NSZoneMalloc(NULL, ((len * 5) + 1) * sizeof(char)); while (cnt < len) { unichar c = buf[cnt]; if (((c > 31) && (c < 38)) || ((c > 38) && (c < 127))) { res[cntRes++] = c; } else { if (c == '&') { res[cntRes++] = '&'; res[cntRes++] = '-'; } else { res[cntRes++] = '&'; cnt += _encodeToModifiedUTF7(buf + cnt, res + cntRes, &cntRes); res[cntRes++] = '-'; } } cnt++; } if (buf != NULL) NSZoneFree(NULL, buf); res[cntRes] = 0; result = [NSString stringWithCString: (char *) res encoding: NSISOLatin1StringEncoding]; return result; } - (NSString *)stringByDecodingImap4FolderName { unsigned char *buf; unichar *res; unsigned int len; unsigned int cnt = 0; unsigned int cntRes = 0; NSString *result = nil; // NSData *data; if ((len = [self lengthOfBytesUsingEncoding: NSISOLatin1StringEncoding]) == 0) return @""; buf = NSZoneMalloc(NULL, (len + 1) * sizeof(unsigned char)); if ([self getCString:(char *)buf maxLength: len + 1 encoding: NSISOLatin1StringEncoding] == NO) { NSZoneFree(NULL, buf); return @""; } buf[len] = '\0'; res = NSZoneMalloc(NULL, (len + 1) * sizeof(unichar)); while (cnt < len) { /* &- */ unsigned char c; c = buf[cnt]; if (c == '&') { if (buf[cnt + 1] == '-') { res[cntRes++] = '&'; cnt += 2; } else { cnt += _decodeOfModifiedUTF7(buf + cnt + 1, res + cntRes, &cntRes) + 1; } } else { res[cntRes++] = c; cnt++; } } if (buf != NULL) NSZoneFree(NULL, buf); res[cntRes] = 0; result = [NSString stringWithCharacters: res length: cntRes]; if (res != NULL) NSZoneFree(NULL, res); return result; } /* check metamail output for correctness */ static unsigned char basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; static char index_64[128] = { -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, 63,-1,-1,-1, 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 }; #define char64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) static unsigned int _encodeToModifiedUTF7(unichar *_char, unsigned char *result_, unsigned int *cntRes_) { unsigned int processedSrc, processedDest, cycle; unichar c; char leftover; BOOL hasLeftOver; processedSrc = 0; processedDest = 0; cycle = 0; leftover = 0; hasLeftOver = NO; c = *_char; while (c > 126 || (c > 0 && c < 32)) { if (cycle == 0) { *(result_ + processedDest) = basis_64[(c >> 10) & 0x3f]; *(result_ + processedDest + 1) = basis_64[(c >> 4) & 0x3f]; leftover = (c << 2); hasLeftOver = YES; processedDest += 2; cycle = 1; } else if (cycle == 1) { *(result_ + processedDest) = basis_64[(leftover | (c >> 14)) & 0x3f]; *(result_ + processedDest + 1) = basis_64[(c >> 8) & 0x3f]; *(result_ + processedDest + 2) = basis_64[(c >> 2) & 0x3f]; leftover = (c << 4); hasLeftOver = YES; processedDest += 3; cycle = 2; } else if (cycle == 2) { *(result_ + processedDest) = basis_64[(leftover | (c >> 12)) & 0x3f]; *(result_ + processedDest + 1) = basis_64[(c >> 6) & 0x3f]; *(result_ + processedDest + 2) = basis_64[c & 0x3f]; leftover = 0; hasLeftOver = NO; processedDest += 3; cycle = 0; } processedSrc++; c = *(_char + processedSrc); } if (hasLeftOver) { *(result_ + processedDest) = basis_64[leftover & 0x3f]; processedDest++; } processedSrc--; *cntRes_ += processedDest; return processedSrc; } static unsigned int _decodeOfModifiedUTF7(unsigned char *_source, unichar *result_, unsigned int *cntRes_) { unsigned int processedSrc, processedDest; unsigned char c, decoded; unichar currentRes; int shift; processedSrc = 0; processedDest = 0; shift = 10; currentRes = 0; c = *_source; while (c != 0 && c != '-') { decoded = index_64[c]; if (shift < 0) { currentRes |= (decoded >> (shift * -1)); *(result_ + processedDest) = currentRes; processedDest++; shift += 16; currentRes = (decoded << shift); } else { currentRes |= (decoded << shift); if (shift == 0) { *(result_ + processedDest) = currentRes; processedDest++; currentRes = 0; shift = 16; } } shift -= 6; processedSrc++; c = *(_source + processedSrc); } if (shift != 10) { *(result_ + processedDest) = currentRes; } if (c == '-') processedSrc++; *cntRes_ += processedDest; return processedSrc; } - (BOOL) is7bitSafe { int i, len; // We search for a non-ASCII character. len = [self length]; for (i = 0; i < len; i++) { if ([self characterAtIndex: i] > 0x007E) { return NO; } } return YES; } @end /* NSString(Imap4) */ SOPE/sope-mime/NGImap4/NGImap4FolderFlags.h0000644000000000000000000000310715004363604017077 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGImap4_NGImap4FolderFlags_H__ #define __NGImap4_NGImap4FolderFlags_H__ #import @class NSArray; @interface NGImap4FolderFlags : NSObject { NSArray *flags; // TODO: document struct { BOOL nonexistent:1; /* Cyrus set this flag, if the folder exist in cache only */ BOOL noselect:1; BOOL haschildren:1; BOOL hasnochildren:1; BOOL noinferiors:1; BOOL marked:1; BOOL unmarked:1; } listFlags; } - (id)initWithFlagArray:(NSArray *)_array; /* accessors */ - (NSArray *)flagArray; - (BOOL)doNotSelectFolder; - (BOOL)doesNotSupportSubfolders; - (BOOL)doesNotExist; - (BOOL)hasSubfolders; - (BOOL)hasNoSubfolders; - (BOOL)isMarked; - (BOOL)isUnmarked; /* operations */ - (void)allowFolderSelect; @end #endif /* __NGImap4_NGImap4FolderFlags_H__ */ SOPE/sope-mime/NGImap4/NGImap4MailboxInfo.m0000644000000000000000000000526415004363604017131 0ustar rootroot/* Copyright (C) 2005 SKYRIX Software AG This file is part of OpenGroupware.org. OGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. OGo 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with OGo; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4MailboxInfo.h" #include "imCommon.h" @implementation NGImap4MailboxInfo - (id)initWithURL:(NSURL *)_url folderName:(NSString *)_name selectDictionary:(NSDictionary *)_dict { if (_dict == nil || (_url == nil && _name == nil)) { [self release]; return nil; } if ((self = [super init])) { self->timestamp = [[NSDate alloc] init]; self->url = [_url copy]; self->name = [_name copy]; self->allowedFlags = [[_dict objectForKey:@"flags"] copy]; self->access = [[_dict objectForKey:@"access"] copy]; self->recent = [[_dict objectForKey:@"recent"] unsignedIntValue]; } return self; } - (id)init { return [self initWithURL:nil folderName: nil selectDictionary:nil]; } - (void)dealloc { [self->timestamp release]; [self->url release]; [self->name release]; [self->allowedFlags release]; [self->access release]; [super dealloc]; } /* accessors */ - (NSDate *)timestamp { return self->timestamp; } - (NSURL *)url { return self->url; } - (NSString *)name { return self->name; } - (NSArray *)allowedFlags { return self->allowedFlags; } - (NSString *)access { return self->access; } - (unsigned int)recent { return self->recent; } /* description */ - (void)appendAttributesToDescription:(NSMutableString *)_ms { if (self->name) [_ms appendFormat:@" name=%@", self->name]; if (self->access) [_ms appendFormat:@" access=%@", self->access]; if (self->recent != 0) [_ms appendFormat:@" recent=%d", self->recent]; [_ms appendFormat:@" flags=%@", [[self allowedFlags] componentsJoinedByString:@","]]; } - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:64]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; [self appendAttributesToDescription:ms]; [ms appendString:@">"]; return ms; } @end /* NGImap4MailboxInfo */ SOPE/sope-mime/NGImap4/NGImap4FileManager.m0000644000000000000000000004437615004363604017103 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4FileManager.h" #include #include #include #include #include "imCommon.h" #include @interface NGImap4FileManager(Privates) - (BOOL)loginWithUser:(NSString *)_user password:(NSString *)_pwd host:(NSString *)_host; - (id)_lookupFolderAtPath:(NSArray *)_paths; - (id)_lookupFolderAtPathString:(NSString *)_path; - (EOQualifier *)_qualifierForFileName:(NSString *)_filename; @end @implementation NGImap4FileManager static BOOL debugOn = NO; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; if ((debugOn = [ud boolForKey:@"NGImap4FileManagerDebugEnabled"])) NSLog(@"NGImap4FileManager debugging is enabled."); } - (id)initWithUser:(NSString *)_user password:(NSString *)_pwd host:(NSString *)_host { if ((self = [super init])) { if (![self loginWithUser:_user password:_pwd host:_host]) { [self logWithFormat:@"could not login user '%@' host '%@'.", _user, _host]; [self release]; return nil; } } return self; } - (id)init { return [self initWithUser:nil password:nil host:nil]; } - (id)initWithURL:(NSURL *)_url { if (_url == nil) { [self release]; return nil; } if ((self = [super init])) { self->imapContext = [NGImap4Context alloc]; /* keep gcc happy */ if ((self->imapContext = [self->imapContext initWithURL:_url]) == nil){ [self logWithFormat:@"ERROR: got no IMAP4 context for url %@ ...",_url]; [self release]; return nil; } [self->imapContext enterSyncMode]; if (![self->imapContext openConnection]) { [self logWithFormat:@"ERROR: could not open IMAP4 connection ..."]; [self release]; return nil; } if ((self->rootFolder = [[self->imapContext serverRoot] retain]) == nil) { [self logWithFormat:@"ERROR: did not find root folder ..."]; [self release]; return nil; } if ((self->currentFolder=[[self->imapContext inboxFolder] retain])==nil) { [self logWithFormat:@"ERROR: did not find inbox folder ..."]; [self release]; return nil; } if (![[_url path] isEqualToString:@"/"]) { if (![self changeCurrentDirectoryPath:[_url path]]) { [self logWithFormat:@"ERROR: couldn't change to URL path: %@", _url]; [self release]; return nil; } } } return self; } - (id)imapContext { return self->imapContext; } - (void)dealloc { [self->currentFolder release]; [self->imapContext release]; [self->rootFolder release]; [super dealloc]; } /* operations */ - (BOOL)loginWithUser:(NSString *)_user password:(NSString *)_pwd host:(NSString *)_host { NSDictionary *conDict; [self->imapContext release]; self->imapContext = nil; [self->rootFolder release]; self->rootFolder = nil; [self->currentFolder release]; self->currentFolder = nil; conDict = [NSDictionary dictionaryWithObjectsAndKeys: _user ? _user : (NSString *)@"anonymous", @"login", _pwd ? _pwd : (NSString *)@"", @"passwd", _host ? _host : (NSString *)@"localhost", @"host", nil]; self->imapContext = [[NGImap4Context alloc] initWithConnectionDictionary:conDict]; [self->imapContext enterSyncMode]; if (![self->imapContext openConnection]) return NO; if ((self->rootFolder = [[self->imapContext serverRoot] retain]) == nil) return NO; if ((self->currentFolder = [[self->imapContext inboxFolder] retain]) == nil) return NO; return YES; } /* internals */ - (id)_lookupFolderAtPath:(NSArray *)_paths { id folder; NSEnumerator *e; NSString *path; folder = self->currentFolder; e = [_paths objectEnumerator]; while ((path = [e nextObject]) && (folder != nil)) { if ([path isEqualToString:@"."]) continue; if ([path isEqualToString:@""]) continue; if ([path isEqualToString:@".."]) { folder = [folder parentFolder]; continue; } if ([path isEqualToString:@"/"]) { folder = self->rootFolder; continue; } folder = [folder subFolderWithName:path caseInsensitive:NO]; } return folder; } - (id)_lookupFolderAtPathString:(NSString *)_path { return [self _lookupFolderAtPath:[_path pathComponents]]; } - (EOQualifier *)_qualifierForFileName:(NSString *)_filename { return [EOQualifier qualifierWithQualifierFormat:@"uid=%@", _filename]; } /* directory ops */ - (BOOL)createDirectoryAtPath:(NSString *)_path attributes:(NSDictionary *)_attributes { id folder; NSString *filename; if (![_path isAbsolutePath]) _path = [[self currentDirectoryPath] stringByAppendingPathComponent:_path]; filename = [_path lastPathComponent]; _path = [_path stringByDeletingLastPathComponent]; if ((folder = [self _lookupFolderAtPathString:_path]) == nil) return NO; return [folder createSubFolderWithName:filename]; } - (BOOL)changeCurrentDirectoryPath:(NSString *)_path { id folder; if (![_path isNotEmpty]) return NO; if (![_path isAbsolutePath]) _path = [[self currentDirectoryPath] stringByAppendingPathComponent:_path]; if ((folder = [self _lookupFolderAtPathString:_path]) == nil) return NO; ASSIGN(self->currentFolder, (id)folder); return YES; } - (NSString *)currentDirectoryPath { if ([self->currentFolder isEqual:[self->currentFolder parentFolder]] || [self->currentFolder parentFolder] == nil) return @"/"; else return [self->currentFolder absoluteName]; } - (NGImap4Folder *)currentFolder { return self->currentFolder; } /* operations */ - (NSArray *)directoryContentsAtPath:(NSString *)_path { return [self directoryContentsAtPath:_path directories:YES files:YES]; } - (NSArray *)directoriesAtPath:(NSString *)_path { return [self directoryContentsAtPath:_path directories:YES files:NO]; } - (NSArray *)filesAtPath:(NSString *)_path { return [self directoryContentsAtPath:_path directories:NO files:YES]; } - (NSArray *)directoryContentsAtPath:(NSString *)_path directories:(BOOL)_dirs files:(BOOL)_files { id folder; NSMutableArray *results; NSEnumerator *e; NGImap4Folder *tmp; NGImap4Message *msg; if (![_path isAbsolutePath]) _path = [[self currentDirectoryPath] stringByAppendingPathComponent:_path]; if ((folder = [self _lookupFolderAtPath:[_path pathComponents]]) == nil) { /* folder does not exist */ if (debugOn) [self debugWithFormat:@"did not find folder."]; return nil; } results = [NSMutableArray arrayWithCapacity:64]; /* add folders */ if (_dirs) { if (debugOn) [self debugWithFormat:@" add subfolders: %@", [folder subFolders]]; e = [[folder subFolders] objectEnumerator]; while ((tmp = [e nextObject]) != nil) [results addObject:[tmp name]]; } /* add messages */ if (_files) { e = [[folder messages] objectEnumerator]; while ((msg = [e nextObject])) [results addObject:[NSString stringWithFormat:@"%d", [msg uid]]]; } if (debugOn) [self debugWithFormat:@" dir contents: %@", results]; return results; } - (NGImap4Message *)messageAtPath:(NSString *)_path { id folder; NSString *filename; EOQualifier *q; NSArray *msgs; NGImap4Message *msg; if (![_path isAbsolutePath]) _path = [[self currentDirectoryPath] stringByAppendingPathComponent:_path]; filename = [_path lastPathComponent]; _path = [_path stringByDeletingLastPathComponent]; if ((folder = [self _lookupFolderAtPath:[_path pathComponents]]) == nil) return nil; q = [self _qualifierForFileName:filename]; //NSLog(@"qualifier: %@", q); msgs = [folder messagesForQualifier:q maxCount:2]; if (![msgs isNotEmpty]) { /* no such message .. */ return nil; } if ([msgs count] > 1) { NSLog(@"multiple messages for uid %@", filename); return nil; } msg = [msgs objectAtIndex:0]; return msg; } - (NSData *)contentsAtPath:(NSString *)_path { return [self contentsAtPath:_path part:@""]; } - (NSData *)contentsAtPath:(NSString *)_path part:(NSString *)_part { id folder; NSString *fileName; if (![_path isAbsolutePath]) _path = [[self currentDirectoryPath] stringByAppendingPathComponent:_path]; fileName = [_path lastPathComponent]; _path = [_path stringByDeletingLastPathComponent]; if ((folder = [self _lookupFolderAtPath:[_path pathComponents]]) == nil) return nil; if (![folder respondsToSelector:@selector(blobForUid:part:)]) return nil; return [(NGImap4Folder *)folder blobForUid:[fileName unsignedIntValue] part:_part]; } - (BOOL)fileExistsAtPath:(NSString *)_path { BOOL isDir; return [self fileExistsAtPath:_path isDirectory:&isDir]; } - (BOOL)fileExistsAtPath:(NSString *)_path isDirectory:(BOOL *)_isDir { id folder; NSArray *paths; NSString *fileName; if (![_path isAbsolutePath]) _path = [[self currentDirectoryPath] stringByAppendingPathComponent:_path]; if ([_path isEqualToString:@"/"]) { if (_isDir) *_isDir = YES; return self->rootFolder != nil ? YES : NO; } fileName = [_path lastPathComponent]; _path = [_path stringByDeletingLastPathComponent]; paths = [_path pathComponents]; folder = [self _lookupFolderAtPath:paths]; if (debugOn) { [self debugWithFormat: @"base '%@' file '%@' paths: %@, file %@, folder %@", _path, fileName, paths, fileName, folder]; } if (folder == nil) return NO; if ([fileName isEqualToString:@"."]) { *_isDir = YES; return YES; } if ([fileName isEqualToString:@".."]) { *_isDir = YES; return YES; } // TODO: what is the caseInsensitive good for? if (debugOn) [self debugWithFormat:@" lookup '%@' in %@", fileName, folder]; if ([folder subFolderWithName:fileName caseInsensitive:NO] != nil) { *_isDir = YES; return YES; } *_isDir = NO; /* check for message 'file' */ { EOQualifier *q; NSArray *msgs; q = [self _qualifierForFileName:fileName]; msgs = [folder messagesForQualifier:q maxCount:2]; if ([msgs isNotEmpty]) return YES; } return NO; } - (BOOL)isReadableFileAtPath:(NSString *)_path { return [self fileExistsAtPath:_path]; } - (BOOL)isWritableFileAtPath:(NSString *)_path { return [self fileExistsAtPath:_path]; } - (BOOL)isExecutableFileAtPath:(NSString *)_path { return NO; } - (BOOL)isDeletableFileAtPath:(NSString *)_path { return [self fileExistsAtPath:_path]; } /* attributes */ - (NSDictionary *)_fileAttributesOfFolder:(id)_folder { NSMutableDictionary *attrs; id tmp; attrs = [NSMutableDictionary dictionaryWithCapacity:12]; if ((tmp = [_folder absoluteName])) [attrs setObject:tmp forKey:NSFilePath]; if ((tmp = [_folder name])) [attrs setObject:tmp forKey:NSFileName]; if ((tmp = [[_folder parentFolder] absoluteName])) [attrs setObject:tmp forKey:NSParentPath]; [attrs setObject:[self->imapContext login] forKey:NSFileOwnerAccountName]; [attrs setObject:NSFileTypeDirectory forKey:NSFileType]; return attrs; } - (NSDictionary *)_fileAttributesOfMessage:(NGImap4Message *)_msg inFolder:(NGImap4Folder *)_folder { NSMutableDictionary *attrs; NSString *fileName, *filePath; NSDictionary *headers; id tmp; static NGMimeHeaderNames *Fields = NULL; if (!Fields) Fields = (NGMimeHeaderNames *)[NGMimePartParser headerFieldNames]; headers = (id)[_msg headers]; //NSLog(@"headers: %@", headers); fileName = [NSString stringWithFormat:@"%i", [_msg uid]]; filePath = [[_folder absoluteName] stringByAppendingPathComponent:fileName]; attrs = [NSMutableDictionary dictionaryWithCapacity:12]; if (filePath) [attrs setObject:filePath forKey:NSFilePath]; if (fileName) [attrs setObject:fileName forKey:NSFileName]; if ((tmp = [_folder absoluteName])) [attrs setObject:tmp forKey:NSParentPath]; if ((tmp = [headers objectForKey:@"date"])) { /* should parse date ? */ NSCalendarDate *date; if ([tmp isKindOfClass:[NSDate class]]) date = tmp; else { NGMimeRFC822DateHeaderFieldParser *parser; parser = [[NGMimeRFC822DateHeaderFieldParser alloc] init]; date = [parser parseValue: [tmp dataUsingEncoding:[NSString defaultCStringEncoding]] ofHeaderField:@"date"]; [parser release]; } if (date == nil) NSLog(@"could not parse date: %@", tmp); [attrs setObject:(date != nil ? date : (NSCalendarDate *)tmp) forKey:NSFileModificationDate]; } if ((tmp = [headers objectForKey:Fields->from])) [attrs setObject:tmp forKey:@"NGImapFrom"]; if ((tmp = [headers objectForKey:Fields->xMailer])) [attrs setObject:tmp forKey:@"NGImapMailer"]; if ((tmp = [headers objectForKey:Fields->organization])) [attrs setObject:tmp forKey:@"NGImapOrganization"]; if ((tmp = [headers objectForKey:Fields->to])) [attrs setObject:tmp forKey:@"NGImapReceiver"]; if ((tmp = [headers objectForKey:Fields->subject])) [attrs setObject:tmp forKey:@"NGImapSubject"]; if ((tmp = [headers objectForKey:Fields->contentType])) [attrs setObject:tmp forKey:@"NGImapContentType"]; [attrs setObject:[self->imapContext login] forKey:NSFileOwnerAccountName]; [attrs setObject:[NSNumber numberWithInt:[_msg size]] forKey:NSFileSize]; if ((tmp = [headers objectForKey:Fields->messageID])) [attrs setObject:tmp forKey:@"NSFileIdentifier"]; else { [attrs setObject:[NSNumber numberWithInt:[_msg uid]] forKey:@"NSFileIdentifier"]; } [attrs setObject:NSFileTypeRegular forKey:NSFileType]; return attrs; } - (NSDictionary *)fileAttributesAtPath:(NSString *)_path traverseLink:(BOOL)flag { NSString *fileName; id folder, sfolder; if (![_path isAbsolutePath]) _path = [[self currentDirectoryPath] stringByAppendingPathComponent:_path]; fileName = [_path lastPathComponent]; _path = [_path stringByDeletingLastPathComponent]; if ((folder = [self _lookupFolderAtPath:[_path pathComponents]]) == nil) return nil; /* check for folder */ if ([fileName isEqualToString:@"."]) return [self _fileAttributesOfFolder:folder]; if ([fileName isEqualToString:@".."]) return [self _fileAttributesOfFolder:[folder parentFolder]]; if ((sfolder = [folder subFolderWithName:fileName caseInsensitive:NO])) return [self _fileAttributesOfFolder:sfolder]; /* check for messages */ if (![folder isKindOfClass:[NGImap4Folder class]]) return nil; { EOQualifier *q; NSArray *msgs; q = [self _qualifierForFileName:fileName]; msgs = [folder messagesForQualifier:q maxCount:2]; if (![msgs isNotEmpty]) { /* msg does not exist */ //NSLog(@"did not find msg for qualifier %@ in folder %@", q, folder); return nil; } return [self _fileAttributesOfMessage:[msgs objectAtIndex:0] inFolder:(NGImap4Folder *)folder]; } } - (NSDictionary *)fileSystemAttributesAtPath:(NSString *)_path { NSMutableDictionary *dict; id tmp; dict = [NSMutableDictionary dictionaryWithCapacity:12]; if ((tmp = [self->imapContext host])) [dict setObject:tmp forKey:@"host"]; if ((tmp = [self->imapContext login])) [dict setObject:tmp forKey:@"login"]; if ((tmp = [self->imapContext serverName])) [dict setObject:tmp forKey:@"serverName"]; if ((tmp = [self->imapContext serverKind])) [dict setObject:tmp forKey:@"serverKind"]; if ((tmp = [self->imapContext serverVersion])) [dict setObject:tmp forKey:@"serverVersion"]; if ((tmp = [self->imapContext serverTag])) [dict setObject:tmp forKey:@"serverTag"]; if ((tmp = [[self->imapContext trashFolder] absoluteName])) [dict setObject:tmp forKey:@"trashFolderPath"]; if ((tmp = [[self->imapContext sentFolder] absoluteName])) [dict setObject:tmp forKey:@"sentFolderPath"]; if ((tmp = [[self->imapContext draftsFolder] absoluteName])) [dict setObject:tmp forKey:@"draftsFolderPath"]; if ((tmp = [[self->imapContext inboxFolder] absoluteName])) [dict setObject:tmp forKey:@"inboxFolderPath"]; if ((tmp = [[self->imapContext serverRoot] absoluteName])) [dict setObject:tmp forKey:@"rootFolderPath"]; return dict; } - (EODataSource *)dataSourceAtPath:(NSString *)_path { id f; if ((f = [self _lookupFolderAtPath:[_path pathComponents]]) == nil) return nil; // TODO: check whether 'f' is really an NGImap4Folder? return [[[NGImap4DataSource alloc] initWithFolder:(NGImap4Folder *)f] autorelease]; } - (BOOL)syncMode { return [self->imapContext isInSyncMode]; } - (void)setSyncMode:(BOOL)_bool { if (_bool) [self->imapContext enterSyncMode]; else [self->imapContext leaveSyncMode]; } /* debugging */ - (BOOL)isDebuggingEnabled { return debugOn; } /* description */ - (void)appendAttributesToDescription:(NSMutableString *)ms { [ms appendFormat:@" ctx=%@", self->imapContext]; [ms appendFormat:@" root=%@", self->rootFolder]; [ms appendFormat:@" wd=%@", self->currentFolder]; } - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:64]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; [self appendAttributesToDescription:ms]; [ms appendString:@">"]; return ms; } @end /* NGImap4FileManager */ SOPE/sope-mime/NGImap4/NGImap4Message+BodyStructure.h0000644000000000000000000002207515004363604021112 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGImap4Message_BodyStructure_H__ #define __NGImap4Message_BodyStructure_H__ @interface NSCalendarDate(RFC822Dates) + (NSCalendarDate *)calendarDateWithRfc822DateString:(NSString *)_str; @end /* NSString(RFC822Dates) */ @interface NGImap4Message(BodyStructure) static id _buildMultipartMessage(id self, NSURL *_baseUrl, NSDictionary *_dict, id_part); static id _buildMessage(id self, NSURL *_baseUrl, NSDictionary *_dict); static id _buildPart(id self, NSURL *_baseUrl, NSDictionary *_dict); static id _buildMimeBodyPart(id self, NSDictionary *_dict); static id _buildMimeMessageBody(id self, NSURL *_baseUrl, NSDictionary *_dict, id_part); @end /* NGImap4Message(BodyStructure) */ @implementation NGImap4Message(BodyStructure) static id _buildMultipartMessage(id self, NSURL *_baseUrl, NSDictionary *_dict, id_part) { NGMimeMultipartBody *body; NSEnumerator *enumerator; NSDictionary *part; int cnt; body = [[NGMimeMultipartBody alloc] initWithPart:_part]; enumerator = [[_dict objectForKey:@"parts"] objectEnumerator]; cnt = 1; while ((part = [enumerator nextObject])) { NSURL *url; { NSString *baseStr; baseStr = [_baseUrl absoluteString]; if ([baseStr hasSuffix:@"="]) url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%d", baseStr, cnt]]; else url = [NSURL URLWithString:[NSString stringWithFormat:@"%@.%d", baseStr, cnt]]; } [body addBodyPart:_buildPart(self, url, part)]; cnt++; } return [body autorelease]; } static id _buildMessage(id self, NSURL *_baseUrl, NSDictionary *_dict) { NGMutableHashMap *map; NGMimeMessage *message; NSString *value; static NGMimeHeaderNames *Fields = NULL; if (!Fields) Fields = (NGMimeHeaderNames *)[NGMimePartParser headerFieldNames]; map = [NGMutableHashMap hashMapWithCapacity:4]; if ([(value = [_dict objectForKey:@"subject"]) isNotNull]) [map setObject:value forKey:Fields->subject]; if ([(value = [_dict objectForKey:@"messageId"]) isNotNull]) [map setObject:value forKey:Fields->messageID]; if ([(value = [_dict objectForKey:@"in-reply-to"]) isNotNull]) [map setObject:value forKey:@"in-reply-to"]; if ([(value = [_dict objectForKey:Fields->contentLength]) isNotNull]) [map setObject:value forKey:Fields->contentLength]; if ([(value = [_dict objectForKey:@"date"]) isNotNull]) { NSCalendarDate *d; if ((d = [NSCalendarDate calendarDateWithRfc822DateString:value])) [map setObject:d forKey:Fields->date]; } { NSEnumerator *enumerator; id obj; static NSArray *Array = nil; if (Array == nil) { Array = [[NSArray alloc] initWithObjects: Fields->from, @"sender", Fields->replyTo, Fields->to, Fields->cc, @"bcc", nil]; } enumerator = [Array objectEnumerator]; while ((obj = [enumerator nextObject])) { NSArray *addrs; if ((addrs = [_dict objectForKey:obj])) { NSEnumerator *addrEnum; NSDictionary *addr; NSMutableString *str; addrEnum = [addrs objectEnumerator]; str = nil; while ((addr = [addrEnum nextObject]) != nil) { NSString *personalName, *mailboxName, *hostName; if (str == nil) str = [NSMutableString stringWithCapacity:32]; else [str appendString:@", "]; personalName = [addr objectForKey:@"personalName"]; mailboxName = [addr objectForKey:@"mailboxName"]; hostName = [addr objectForKey:@"hostName"]; if ([personalName isNotEmpty]) { [str appendString:@"\""]; [str appendString:personalName]; [str appendString:@"\" <"]; [str appendString:mailboxName]; [str appendString:@"@"]; [str appendString:hostName]; [str appendString:@">"]; } else { [str appendString:mailboxName]; [str appendString:@"@"]; [str appendString:hostName]; } } if (str != nil) [map setObject:str forKey:obj]; } } } { id part, tmp, body; part = _buildPart(self, _baseUrl, [_dict objectForKey:@"body"]); [map setObject:[part contentType] forKey:Fields->contentType]; if (![[map valueForKey:Fields->contentTransferEncoding] length]) { if ((tmp = [[part valuesOfHeaderFieldWithName: Fields->contentTransferEncoding] nextObject])) { [map setObject:tmp forKey:Fields->contentTransferEncoding]; } } if (![[map valueForKey:Fields->contentLength] intValue]) { if ((tmp = [[part valuesOfHeaderFieldWithName:Fields->contentLength] nextObject])) { [map setObject:tmp forKey:Fields->contentLength]; } } message = [NGMimeMessage messageWithHeader:map]; if ([(body = [part body]) isKindOfClass:[NSURL class]]) { NSString *baseStr; baseStr = [body absoluteString]; if ([baseStr hasPrefix:@"="]) { body = [NSURL URLWithString:[NSString stringWithFormat:@"%@1", baseStr]]; } else body = [NSURL URLWithString:[NSString stringWithFormat:@"%@.1", baseStr]]; } [message setBody:body]; } return message; } static id _buildPart(id self, NSURL *_baseUrl, NSDictionary *_dict) { NSString *type, *subType; NGMimeBodyPart *part; NSURL *url; url = _baseUrl; type = [[_dict objectForKey:@"type"] lowercaseString]; subType = [[_dict objectForKey:@"subtype"] lowercaseString]; part = _buildMimeBodyPart(self, _dict); if ([type isEqualToString:@"multipart"]) { [part setBody:_buildMultipartMessage(self, url, _dict, part)]; } else if ([type isEqualToString:@"message"] && [subType isEqualToString:@"rfc822"]) { [part setBody:_buildMessage(self, url, _dict)]; } else { [part setBody:url]; } return part; } static id _buildMimeBodyPart(id self, NSDictionary *_dict) { NGMutableHashMap *dict; NSString *value; NGMimeType *type; static NGMimeHeaderNames *Fields = NULL; if (!Fields) Fields = (NGMimeHeaderNames *)[NGMimePartParser headerFieldNames]; dict = [NGMutableHashMap hashMapWithCapacity:8]; type = [NGMimeType mimeType:[[_dict objectForKey:@"type"] lowercaseString] subType:[[_dict objectForKey:@"subtype"] lowercaseString] parameters:[_dict objectForKey:@"parameterList"]]; [dict setObject:type forKey:Fields->contentType]; if ([(value = [_dict objectForKey:@"bodyId"]) isNotEmpty]) [dict setObject:value forKey:Fields->messageID]; if ([(value = [_dict objectForKey:@"size"]) isNotEmpty]) [dict setObject:value forKey:Fields->contentLength]; if ([(value = [_dict objectForKey:@"encoding"]) isNotEmpty]) { [dict setObject:[value lowercaseString] forKey:Fields->contentTransferEncoding]; } return [NGMimeBodyPart bodyPartWithHeader:dict]; } static id _buildMimeMessageBody(id self, NSURL *_baseUrl, NSDictionary *_dict, id_part) { NSString *type, *subType; NSURL *url; id result; type = [[_dict objectForKey:@"type"] lowercaseString]; subType = [[_dict objectForKey:@"subtype"] lowercaseString]; url = [NSURL URLWithString:[[_baseUrl absoluteString] stringByAppendingString:@"?part="]]; if ([type isEqualToString:@"multipart"]) { result = _buildMultipartMessage(self, url, _dict, _part); } else { if ([type isEqualToString:@"message"] && [subType isEqualToString:@"rfc822"]) { result = _buildMessage(self, url, _dict); } else { result = [NSURL URLWithString:[[_baseUrl absoluteString] stringByAppendingString:@"?part=1"]]; } } return result; } @end /* NGImap4Message(BodyStructure) */ #endif /* __NGImap4Message_BodyStructure_H__ */ SOPE/sope-mime/NGImap4/NGImap4ServerRoot.m0000644000000000000000000002224715004363604017034 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4ServerRoot.h" #include "NGImap4Context.h" #include "NGImap4Client.h" #include "NGImap4Message.h" #include "NGImap4Functions.h" #include "NGImap4Folder.h" #include "imCommon.h" @interface NGImap4ServerRoot(Private) - (void)initializeSubFolders; @end @implementation NGImap4ServerRoot static int ShowNonExistentFolder = -1; static int FetchNewUnseenMessagesInSubFoldersOnDemand = -1; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; // TODO: document the meaning! ShowNonExistentFolder = [ud boolForKey:@"ShowNonExistentFolder"] ? 1 : 0; FetchNewUnseenMessagesInSubFoldersOnDemand = [ud boolForKey:@"FetchNewUnseenMessagesInSubFoldersOnDemand"] ? 1 : 0; } + (id)serverRootWithContext:(NGImap4Context *)_context { return [[[self alloc] initServerRootWithContext:_context] autorelease]; } - (id)init { [self release]; [self doesNotRecognizeSelector:_cmd]; return nil; } - (id)initServerRootWithContext:(NGImap4Context *)_context { if ((self = [super init])) { self->context = [_context retain]; self->name = [[_context host] copy]; self->subFolders = nil; self->noinferiors = ([[_context serverKind] isEqualToString:@"courier"]) ? YES : NO; } return self; } - (void)dealloc { [self->context resetSpecialFolders]; [self->context release]; [self->name release]; [self->subFolders makeObjectsPerformSelector:@selector(clearParentFolder)]; [self->subFolders release]; [super dealloc]; } - (NSException *)lastException { return [self->context lastException]; } - (void)resetLastException { [self->context resetLastException]; } - (BOOL)isEqual:(id)_obj { if (self == _obj) return YES; if ([_obj isKindOfClass:[NGImap4ServerRoot class]]) return [self isEqualToServerRoot:_obj]; return NO; } - (BOOL)isEqualToServerRoot:(NGImap4ServerRoot *)_root { if (_root == self) return YES; if ([_root context] == self->context) return YES; return NO; } /* accessors */ - (NGImap4Context *)context { return self->context; } - (NSString *)name { return self->name; } - (NSString *)absoluteName { return self->name; } - (NSArray *)messages { return nil; } - (NSArray *)messagesForQualifier:(EOQualifier *)_qualifier { return nil; } - (NSArray *)messagesForQualifier:(EOQualifier *)_q maxCount:(int)_cnt { return nil; } - (NSArray *)fetchSortedMessages:(NSArray *)_so { return nil; } - (void)bulkFetchHeadersFor:(NSArray *)_array inRange:(NSRange)_aRange { } - (void)bulkFetchHeadersFor:(NSArray *)_array inRange:(NSRange)_aRange withAllUnread:(BOOL)_unread { } - (NSArray *)messageFlags { return nil; } - (NSArray *)subFolders { if (self->subFolders == nil) [self initializeSubFolders]; return self->subFolders; } - (NGImap4Folder *)subFolderWithName:(NSString *)_name caseInsensitive:(BOOL)_caseIns { return _subFolderWithName(self, _name, _caseIns); } - (NGImap4Folder *)parentFolder { return nil; } - (BOOL)isReadOnly { return YES; } - (BOOL)noinferiors { return self->noinferiors; } - (BOOL)noselect { return YES; } - (BOOL)nonexistent { return NO; } - (BOOL)haschildren { return YES; } - (BOOL)hasnochildren { return NO; } - (BOOL)marked { return NO; } - (BOOL)unmarked { return NO; } - (int)exists { return 0; } - (int)recent { return 0; } - (int)unseen { return 0; } - (int)usedSpace { return 0; } - (int)maxQuota { return 0; } - (BOOL)isOverQuota { return NO; } - (BOOL)hasNewMessagesSearchRecursiv:(BOOL)_recursiv fetchOnDemand:(BOOL)_fetch { if (_recursiv) return _hasNewMessagesInSubFolder(self, _fetch); return NO; } - (BOOL)hasNewMessagesSearchRecursiv:(BOOL)_recursiv { if (!_recursiv) return NO; return _hasNewMessagesInSubFolder(self, FetchNewUnseenMessagesInSubFoldersOnDemand); } - (BOOL)hasUnseenMessagesSearchRecursiv:(BOOL)_recursiv fetchOnDemand:(BOOL)_fetch { if (_recursiv) return _hasUnseenMessagesInSubFolder(self, _fetch); return NO; } - (BOOL)hasUnseenMessagesSearchRecursiv:(BOOL)_recursiv { if (_recursiv) { return _hasUnseenMessagesInSubFolder(self, FetchNewUnseenMessagesInSubFoldersOnDemand); } return NO; } // private methods /*" ** Should only happens if folder is rootfolder "*/ - (void)initializeSubFolders { NSEnumerator *folders; NSDictionary *res; id *objs, folder; unsigned cnt; BOOL gotInbox; if (self->subFolders != nil) { [self resetSubFolders]; } if ([self->context showOnlySubscribedInRoot]) { res = [[self->context client] lsub:@"" pattern:@"%"]; } else { res = [[self->context client] list:@"" pattern:@"%"]; } if (!_checkResult(self->context, res, __PRETTY_FUNCTION__)) return; res = [res objectForKey:@"list"]; objs = calloc([res count] + 2, sizeof(id)); { NSArray *names; names = [res allKeys]; names = [names sortedArrayUsingSelector: @selector(caseInsensitiveCompare:)]; folders = [names objectEnumerator]; } cnt = 0; gotInbox = NO; while ((folder = [folders nextObject])) { NSArray *f; f = [res objectForKey:folder]; if (!ShowNonExistentFolder) { if ([f containsObject:@"nonexistent"]) continue; } objs[cnt] = [[[NGImap4Folder alloc] initWithContext:self->context name:folder flags:f parentFolder:self] autorelease]; cnt++; if ([[folder lowercaseString] isEqualToString:@"/inbox"]) gotInbox = YES; } if (!gotInbox && [self->context showOnlySubscribedInRoot]) { /* try unsubscribed */ res = [[[self->context client] list:@"" pattern:@"%"] objectForKey:@"list"]; { NSArray *names; names = [res allKeys]; names = [names sortedArrayUsingSelector: @selector(caseInsensitiveCompare:)]; folders = [names objectEnumerator]; } while ((folder = [folders nextObject])) { if ([[folder lowercaseString] isEqualToString:@"/inbox"]) { objs[cnt] = [[[NGImap4Folder alloc] initWithContext:self->context name:folder flags:[res objectForKey:folder] parentFolder:self] autorelease]; cnt++; break; } } } self->subFolders = [[NSArray alloc] initWithObjects:objs count:cnt]; if (objs) free(objs); objs = NULL; } - (void)select { } - (BOOL)status { return YES; } /* actions */ - (void)resetFolder { } - (void)resetStatus { } - (void)resetSubFolders { [self->context resetSpecialFolders]; [self->subFolders release]; self->subFolders = nil; } - (BOOL)renameTo:(NSString *)_name { return NO; } /* folder */ - (BOOL)deleteSubFolder:(NGImap4Folder *)_folder { return _deleteSubFolder(self, _folder); } - (BOOL)copySubFolder:(NGImap4Folder *)_f to:(NGImap4Folder *)_folder { return _copySubFolder(self, _f, _folder); } - (BOOL)moveSubFolder:(NGImap4Folder *)_f to:(NGImap4Folder *)_folder { return _moveSubFolder(self, _f, _folder); } - (BOOL)createSubFolderWithName:(NSString *)_name { return _createSubFolderWithName(self, _name, NO); } - (void)expunge { } - (BOOL)addFlag:(NSString *)_flag toMessages:(NSArray *)_messages { return NO; } - (BOOL)removeFlag:(NSString *)_flag fromMessages:(NSArray *)_messages { return NO; } - (BOOL)flag:(NSString *)_flag toMessages:(NSArray *)_messages add:(NSNumber *)_add { return NO; } - (BOOL)flagToAllMessages:(NSString *)_flag add:(NSNumber *)_add { return NO; } - (BOOL)deleteAllMessages { return NO; } - (BOOL)deleteMessages:(NSArray *)_messages { return NO; } - (BOOL)moveMessages:(NSArray *)_messages toFolder:(NGImap4Folder *)_folder { return NO; } - (BOOL)copyMessages:(NSArray *)_messages toFolder:(NGImap4Folder *)_folder { return NO; } - (BOOL)appendMessage:(NSData *)_msg { return NO; } - (BOOL)isInTrash { return NO; } - (NSString *)description { NSMutableString *ms; NSString *tmp; ms = [NSMutableString stringWithCapacity:64]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if ((tmp = [self name])) [ms appendFormat:@" name=%@", tmp]; if ((tmp = [self absoluteName])) [ms appendFormat:@" absolute=%@", tmp]; [ms appendString:@">"]; return ms; } - (void)resetSync { NSEnumerator *enumerator; id folder; enumerator = [[self subFolders] objectEnumerator]; while ((folder = [enumerator nextObject])) { [folder resetSync]; } } @end /* NGImap4ServerRoot */ SOPE/sope-mime/NGImap4/NGImap4ServerGlobalID.m0000644000000000000000000000510315004363604017516 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4ServerGlobalID.h" #include "imCommon.h" @implementation NGImap4ServerGlobalID + (id)imap4ServerGlobalIDForHostname:(NSString *)_host port:(int)_port login:(NSString *)_login { NGImap4ServerGlobalID *gid; gid = [[self alloc] initWithHostname:_host port:_port login:_login]; return [gid autorelease]; } - (id)initWithHostname:(NSString *)_host port:(int)_p login:(NSString *)_l { if ((self = [super init])) { self->hostName = [_host copy]; self->login = [_l copy]; self->port = _p; } return self; } - (id)init { return [self initWithHostname:nil port:0 login:nil]; } - (void)dealloc { [self->hostName release]; [self->login release]; [super dealloc]; } /* accessors */ - (NSString *)hostName { return self->hostName; } - (NSString *)login { return self->login; } - (int)port { return self->port; } /* comparison */ - (NSUInteger)hash { return [self->login hash]; } - (BOOL)isEqualToImap4ServerGlobalID:(NGImap4ServerGlobalID *)_other { if (_other == nil) return NO; if (self == _other) return YES; if (self->login != _other->login) { if (![self->login isEqualToString:_other->login]) return NO; } if (self->hostName != _other->hostName) { if (![self->hostName isEqualToString:_other->hostName]) return NO; } if (self->port != _other->port) return NO; return YES; } - (BOOL)isEqual:(id)_otherObject { if (_otherObject == self) return YES; if (![_otherObject isKindOfClass:[self class]]) return NO; return [self isEqualToImap4ServerGlobalID:_otherObject]; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { return [self retain]; } /* support for some older code expecting only EO global IDs */ - (NSString *)entityName { return @"NGImap4Client"; } @end /* NGImap4ServerGlobalID */ SOPE/sope-mime/NGImap4/NGImap4Context.m0000644000000000000000000006322515004363604016347 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4Context.h" #include "NGImap4Client.h" #include "NGImap4Folder.h" #include "NGImap4ServerRoot.h" #include "NGImap4Support.h" #include "NGImap4Functions.h" #include "imCommon.h" @interface NGImap4Context(Private) - (void)initializeSentFolder; - (void)initializeTrashFolder; - (void)initializeDraftsFolder; - (void)initializeInboxFolder; - (void)initializeServerRoot; - (void)_setSortEncoding:(NSString *)_str; - (void)_setSubscribeFolderFailed:(BOOL)_b; - (void)_setShowOnlySubscribedInRoot:(BOOL)_b; - (void)_setShowOnlySubscribedInSubFolders:(BOOL)_b; @end @implementation NGImap4Context static id DefaultForSortEncoding = nil; static id DefaultForSubscribeFailed = nil; static id DefaultForShowOnlySubscribedInRoot = nil; static id DefaultForShowOnlySubscribedInSubFolders = nil; static int ImapLogEnabled = -1; + (void)initialize { NSUserDefaults *ud; static BOOL didInit = NO; if (didInit) return; didInit = YES; ud = [NSUserDefaults standardUserDefaults]; DefaultForSortEncoding = [[ud stringForKey:@"ImapSortEncoding"] copy]; DefaultForSubscribeFailed = [[ud stringForKey:@"ImapSubscribedCouldFailed"] copy]; DefaultForShowOnlySubscribedInSubFolders = [[ud stringForKey:@"ShowOnlySubscribedInSubFolders"] copy]; DefaultForShowOnlySubscribedInRoot = [[ud stringForKey:@"ShowOnlySubscribedInRoot"] copy]; ImapLogEnabled = [ud boolForKey:@"ImapLogEnabled"]?1:0; } + (id)imap4ContextWithURL:(id)_url { if (_url == nil) return nil; if (![_url isKindOfClass:[NSURL class]]) _url = [NSURL URLWithString:[_url stringValue]]; return [[(NGImap4Context *)[self alloc] initWithURL:_url] autorelease]; } + (id)imap4ContextWithConnectionDictionary:(NSDictionary *)_connection { return [[[self alloc] initWithConnectionDictionary:_connection] autorelease]; } - (id)initWithConnectionDictionary:(NSDictionary *)_connection { if ((self = [super init])) { self->connectionDictionary = [_connection copy]; self->folderForRefresh = [[NSMutableArray alloc] initWithCapacity:512]; self->syncMode = NO; self->subscribeFolderFailed = (DefaultForSubscribeFailed) ? [DefaultForSubscribeFailed boolValue]?1:0 : -1; self->showOnlySubscribedInRoot = (DefaultForShowOnlySubscribedInRoot) ? [DefaultForShowOnlySubscribedInRoot boolValue]?1:0 : -1; self->showOnlySubscribedInSubFolders = (DefaultForShowOnlySubscribedInSubFolders) ? [DefaultForShowOnlySubscribedInSubFolders boolValue]?1:0 : -1; self->sortEncoding = (DefaultForSortEncoding) ? [DefaultForSortEncoding retain] : nil; } return self; } - (id)initWithNSURL:(NSURL *)_url { NSMutableDictionary *md; id tmp; if (_url == nil) { [self release]; return nil; } md = [NSMutableDictionary dictionaryWithCapacity:4]; if ((tmp = [_url host])) [md setObject:tmp forKey:@"host"]; if ((tmp = [_url port])) [md setObject:tmp forKey:@"port"]; if ((tmp = [_url user])) [md setObject:tmp forKey:@"login"]; if ((tmp = [_url password])) [md setObject:tmp forKey:@"passwd"]; if ([[_url scheme] isEqualToString:@"imaps"]) [md setObject:[NSNumber numberWithBool:YES] forKey:@"SSL"]; return [self initWithConnectionDictionary:md]; } - (id)initWithURL:(id)_url { if ((_url != nil) && ![_url isKindOfClass:[NSURL class]]) _url = [NSURL URLWithString:[_url stringValue]]; return [self initWithNSURL:_url]; } - (void)dealloc { [self->url release]; [self->client removeFromResponseNotification:self]; [self->connectionDictionary release]; [self->client release]; [self->folderForRefresh release]; [self->serverName release]; [self->serverKind release]; [self->serverVersion release]; [self->serverSubVersion release]; [self->serverTag release]; [self->lastException release]; self->selectedFolder = nil; /* not retained */ self->trashFolder = nil; /* not retained */ self->draftsFolder = nil; /* not retained */ self->sentFolder = nil; /* not retained */ self->inboxFolder = nil; /* not retained */ self->serverRoot = nil; /* not retained */ [self->capability release]; [self->sortEncoding release]; [super dealloc]; } /* accessors */ - (NSException *)lastException { return self->lastException; } - (void)setLastException:(NSException *)_exception { ASSIGN(self->lastException, _exception); } - (void)resetLastException { [self->lastException release]; self->lastException = nil; } - (NGImap4Client *)client { if (self->client == nil) [self openConnection]; return self->client; } - (EOGlobalID *)serverGlobalID { if (self->client == nil) { // TODO: construct global-id using connectionDictionary! [self logWithFormat:@"WARNING: could not construct GID (client not set!)"]; return nil; } return [self->client serverGlobalID]; } - (NSURL *)url { NSString *scheme; if (self->url != nil) return self->url; scheme = [[self->connectionDictionary objectForKey:@"SSL"] boolValue] ? @"imaps" : @"imap"; self->url = [[NSURL alloc] initWithScheme:scheme host:[self->connectionDictionary objectForKey:@"host"] path:@"/"]; return self->url; } /* folder tracking */ - (BOOL)isSelectedFolder:(NGImap4Folder *)_folder { return [self->selectedFolder isEqual:_folder]; } - (void)setSelectedFolder:(NGImap4Folder *)_folder { self->selectedFolder = _folder; } - (BOOL)registerAsSelectedFolder:(NGImap4Folder *)_folder { id tmp; if (self->selectedFolder == _folder) return YES; if ([_folder noselect]) return NO; tmp = self->selectedFolder; self->selectedFolder = _folder; if (![_folder selectImmediately:YES]) { self->selectedFolder = tmp; return NO; } return YES; } - (BOOL)removeSelectedFolder:(NGImap4Folder *)_folder { if (self->selectedFolder == _folder) self->selectedFolder = nil; return YES; } - (BOOL)openConnection { NSString *login; NSString *passwd; NSString *host; login = [self->connectionDictionary objectForKey:@"login"]; passwd = [self->connectionDictionary objectForKey:@"passwd"]; host = [self->connectionDictionary objectForKey:@"host"]; [self resetSpecialFolders]; if ((login == nil) || (passwd == nil) || (host == nil)) { id exc; exc = [[NGImap4ConnectionException alloc] initWithFormat: @"missing login, passwd or host in connection-dictionary <%@>", self->connectionDictionary]; ASSIGN(self->lastException, exc); [exc release]; return NO; } if (self->client == nil) { self->client = [[NGImap4Client alloc] initWithHost:host]; [self->client registerForResponseNotification:self]; [self->client setContext:self]; } if (![[self->client isConnected] boolValue]) { NSDictionary *res; [self resetLastException]; res = [self->client openConnection]; if (!_checkResult(self, res, __PRETTY_FUNCTION__)) return NO; [self->serverName release]; self->serverName = nil; [self->serverKind release]; self->serverKind = nil; [self->serverVersion release]; self->serverVersion = nil; [self->serverSubVersion release]; self->serverSubVersion = nil; [self->serverTag release]; self->serverTag = nil; self->serverName = [[res objectForKey:@"server"] retain]; self->serverKind = [[res objectForKey:@"serverKind"] retain]; if (ImapLogEnabled) { [self logWithFormat:@"Server greeting: <%@> parse serverkind: <%@>", self->serverName, self->serverKind]; } // TODO: move capability to specialized object! // Note: capability of the IMAP4 server should be always configurable // using defaults because the identification might be broken for // security reasons if (self->serverKind != nil) { self->serverVersion = [[res objectForKey:@"version"] retain]; self->serverSubVersion = [[res objectForKey:@"subversion"] retain]; self->serverTag = [[res objectForKey:@"tag"] retain]; } if ([self->serverKind isEqual:@"courier"]) { [self _setSortEncoding:@"US-ASCII"]; [self _setSubscribeFolderFailed:NO]; [self _setShowOnlySubscribedInRoot:0]; [self _setShowOnlySubscribedInSubFolders:0]; } else if ([self->serverKind isEqual:@"washington"]) { [self _setSortEncoding:@"UTF-8"]; [self _setSubscribeFolderFailed:YES]; [self _setShowOnlySubscribedInRoot:1]; [self _setShowOnlySubscribedInSubFolders:1]; } else if ([self->serverKind isEqual:@"cyrus"]) { [self _setSortEncoding:@"UTF-8"]; [self _setSubscribeFolderFailed:YES]; [self _setShowOnlySubscribedInRoot:0]; [self _setShowOnlySubscribedInSubFolders:0]; } if (ImapLogEnabled) [self logWithFormat:@"sortEncoding %@ subscribeFolderFailed %@ " @"showOnlySubscribedInSubFolders %@ showOnlySubscribedInRoot %@", [self sortEncoding], [self subscribeFolderFailed] ? @"YES" : @"NO", [self showOnlySubscribedInSubFolders]? @"YES" : @"NO", [self showOnlySubscribedInRoot] ? @"YES" : @"NO"]; [self resetLastException]; res = [self->client login:login password:passwd]; if (!_checkResult(self, res, __PRETTY_FUNCTION__)) return NO; } { NSDictionary *res; [self->capability release]; self->capability = nil; res = [self->client capability]; if (!_checkResult(self, res, __PRETTY_FUNCTION__)) return NO; self->capability = [[res objectForKey:@"capability"] retain]; } self->canSort = -1; self->canQuota = -1; return YES; } - (void)_setSortEncoding:(NSString *)_str { if (!DefaultForSortEncoding) ASSIGN(self->sortEncoding, _str); } - (void)_setSubscribeFolderFailed:(BOOL)_b { if (!DefaultForSubscribeFailed) self->subscribeFolderFailed = _b?1:0; } - (void)_setShowOnlySubscribedInRoot:(BOOL)_b { if (!DefaultForShowOnlySubscribedInRoot) self->showOnlySubscribedInRoot = _b?1:0; } - (void)_setShowOnlySubscribedInSubFolders:(BOOL)_b { if (!DefaultForShowOnlySubscribedInSubFolders) self->showOnlySubscribedInSubFolders = _b?1:0; } - (void)setSortEncoding:(NSString *)_str { ASSIGN(self->sortEncoding, _str); } - (void)setSubscribeFolderFailed:(BOOL)_b { self->subscribeFolderFailed = _b?1:0; } - (void)setShowOnlySubscribedInRoot:(BOOL)_b { self->showOnlySubscribedInRoot = _b?1:0; } - (void)setShowOnlySubscribedInSubFolders:(BOOL)_b { self->showOnlySubscribedInSubFolders = _b?1:0; } - (BOOL)closeConnection { [self->client closeConnection]; [self resetSpecialFolders]; [self->capability release]; self->capability = nil; self->canSort = -1; self->canQuota = -1; return YES; } /*" ** NGImap4ResponseReceiver protocol ** If the NGImap4Context receive a response-notification it ** updates the selected folder "*/ - (void)responseNotificationFrom:(NGImap4Client *)_client response:(NSDictionary *)_dict { if (![[_dict objectForKey:@"result"] boolValue]) { id exc; NSString *str; if ((str = [_dict objectForKey:@"reason"]) == nil) str = @"Response failed"; exc = [[NGImap4ResponseException alloc] initWithName:@"NGImap4ResponseException" reason:str userInfo:_dict]; ASSIGN(self->lastException, exc); return; } if (self->selectedFolder) [self->selectedFolder processResponse:_dict]; } - (id)trashFolder { if (self->trashFolder == nil) [self initializeTrashFolder]; return self->trashFolder; } - (void)setTrashFolder:(NGImap4Folder *)_folder { self->trashFolder = _folder; } - (id)sentFolder { if (self->sentFolder == nil) [self initializeSentFolder]; return self->sentFolder; } - (void)setSentFolder:(NGImap4Folder *)_folder { self->sentFolder = _folder; } - (id)draftsFolder { if (self->draftsFolder == nil) [self initializeDraftsFolder]; return self->draftsFolder; } - (void)setDraftsFolder:(NGImap4Folder *)_folder { self->draftsFolder = _folder; } - (id)inboxFolder { if (self->inboxFolder == nil) [self initializeInboxFolder]; return self->inboxFolder; } - (id)serverRoot { if (self->serverRoot == nil) [self initializeServerRoot]; return self->serverRoot; } - (void)initializeServerRoot { if (self->serverRoot == nil) { /* Note: serverRoot is not retained by NGImap4Context to avoid a retain cycle. This is why the object is autoreleased immediatly after creation (the usercode uses -serverRoot to access the result). */ [self resetSpecialFolders]; self->serverRoot = [[NGImap4ServerRoot alloc] initServerRootWithContext:self]; self->serverRoot = [self->serverRoot autorelease]; } } - (void)_checkFolder:(id)_folder folderName:(NSString *)_name { NSDictionary *res; NSArray *list; [self resetLastException]; res = [self->client list:@"" pattern:_name]; if (![[res objectForKey:@"result"] boolValue]) return; list = [res objectForKey:@"list"]; if ([list isNotEmpty]) { /* folder exist but is not subscribed */ [self->client subscribe:_name]; } else { /* try to create folder */ [_folder createSubFolderWithName:[_name lastPathComponent]]; } [_folder resetSubFolders]; [self->lastException release]; self->lastException = nil; } - (NGImap4Folder *)_getFolderWithName:(NSString *)_name { NSEnumerator *enumerator; NGImap4Folder *folder; if (self->serverRoot == nil) [self initializeServerRoot]; enumerator = [[self->serverRoot subFolders] objectEnumerator]; while ((folder = [enumerator nextObject])) { NSString *name; name = [[folder name] lowercaseString]; if ([name isEqualToString:[_name lowercaseString]]) { return folder; } } if ([[_name lowercaseString] isEqual:@"inbox"]) { [self resetLastException]; [self->client subscribe:_name]; if (self->lastException != nil) { [self->serverRoot createSubFolderWithName:_name]; [self->lastException release]; self->lastException = nil; } [self resetSpecialFolders]; } else { if ([[self inboxFolder] noinferiors]) { /* try to create Sent/Trash/Drafts in root */ [self _checkFolder:self->serverRoot folderName:_name]; } else { /* take a look in inbox */ NGImap4Folder *f; NSString *absoluteName; f = [self inboxFolder]; folder = [f subFolderWithName:[_name lowercaseString] caseInsensitive:YES]; if (folder != nil) return folder; absoluteName = [[f absoluteName] stringByAppendingPathComponent:_name]; [self _checkFolder:f folderName:absoluteName]; } } return nil; } - (NSString *)sentFolderName { static NSString *SentFolderName = nil; if (SentFolderName == nil) { SentFolderName = [[[NSUserDefaults standardUserDefaults] stringForKey:@"ImapSentFolderName"] retain]; if (!SentFolderName) SentFolderName = @"Sent"; } return SentFolderName; } - (NSString *)trashFolderName { static NSString *TrashFolderName = nil; if (TrashFolderName == nil) { TrashFolderName = [[[NSUserDefaults standardUserDefaults] stringForKey:@"ImapTrashFolderName"] retain]; if (!TrashFolderName) TrashFolderName = @"Trash"; } return TrashFolderName; } - (NSString *)draftsFolderName { static NSString *DraftsFolderName = nil; if (DraftsFolderName == nil) { DraftsFolderName = [[[NSUserDefaults standardUserDefaults] stringForKey:@"ImapDraftsFolderName"] retain]; if (!DraftsFolderName) DraftsFolderName = @"Drafts"; } return DraftsFolderName; } - (void)initializeSentFolder { if ((self->sentFolder = [self _getFolderWithName: [self sentFolderName]]) == nil) self->sentFolder = [self _getFolderWithName: [self sentFolderName]]; if (self->sentFolder == nil) NSLog(@"WARNING[%s]: Couldn't find/create sentFolder", __PRETTY_FUNCTION__); } - (void)initializeTrashFolder { if ((self->trashFolder = [self _getFolderWithName: [self trashFolderName]]) == nil) self->trashFolder = [self _getFolderWithName:[self trashFolderName]]; if (self->trashFolder == nil) NSLog(@"WARNING[%s]: Couldn't find/create trashFolder", __PRETTY_FUNCTION__); } - (void)initializeDraftsFolder { if ((self->draftsFolder = [self _getFolderWithName: [self draftsFolderName]]) == nil) self->draftsFolder = [self _getFolderWithName: [self draftsFolderName]]; if (self->draftsFolder == nil) NSLog(@"WARNING[%s]: Couldn't find/create draftsFolder", __PRETTY_FUNCTION__); } - (void)initializeInboxFolder { if ((self->inboxFolder = [self _getFolderWithName:@"Inbox"]) == nil) self->inboxFolder = [self _getFolderWithName:@"Inbox"]; if (self->inboxFolder == nil) NSLog(@"WARNING[%s]: Couldn't find/create inbox", __PRETTY_FUNCTION__); } - (NGImap4Folder *)folderWithName:(NSString *)_name { return [self folderWithName:_name caseInsensitive:NO]; } - (NGImap4Folder *)folderWithName:(NSString *)_name caseInsensitive:(BOOL)_caseIn { NSEnumerator *enumerator; id obj; NGImap4Folder *f; [self resetLastException]; enumerator = [[_name componentsSeparatedByString:@"/"] objectEnumerator]; f = [self serverRoot]; while ((obj = [enumerator nextObject]) != nil) { if ([obj isNotEmpty]) f = [f subFolderWithName:obj caseInsensitive:_caseIn]; } return self->lastException ? (NGImap4Folder *)nil : f; } - (BOOL)createFolderWithPath:(NSString *)_name { NSEnumerator *enumerator; id f1, f2; NSString *name; [self resetLastException]; enumerator = [[_name componentsSeparatedByString:@"/"] objectEnumerator]; f1 = [self serverRoot]; f2 = nil; while ((name = [enumerator nextObject])) { if ((f2 = [f1 subFolderWithName:name caseInsensitive:YES]) == nil) break; f1 = f2; } if (name != nil) { do { if (![f1 createSubFolderWithName:name]) break; f1 = [f1 subFolderWithName:name caseInsensitive:YES]; } while ((name = [enumerator nextObject])); } return self->lastException ? NO : YES; } - (void)resetSpecialFolders { self->sentFolder = nil; self->trashFolder = nil; self->draftsFolder = nil; self->inboxFolder = nil; self->serverRoot = nil; } - (NSArray *)newMessages { NSEnumerator *enumerator; NGImap4Folder *f; NSMutableArray *result; EOQualifier *qual; [self resetLastException]; qual = [EOQualifier qualifierWithQualifierFormat:@"flags = \"recent\""]; result = [NSMutableArray array]; [self->inboxFolder status]; if ([self->inboxFolder hasNewMessagesSearchRecursiv:NO]) { NSArray *array; array = [self->inboxFolder messagesForQualifier:qual]; if (array != nil) [result addObjectsFromArray:array]; } enumerator = [self->folderForRefresh objectEnumerator]; while ((f = [enumerator nextObject])) { [f status]; if ([f hasNewMessagesSearchRecursiv:NO]) { NSArray *array; array = [self->inboxFolder messagesForQualifier:qual]; if (array != nil) [result addObjectsFromArray:array]; } } return self->lastException ? (NSMutableArray *)nil : result; } - (BOOL)hasNewMessages { NSEnumerator *enumerator; NGImap4Folder *f; BOOL result; [self resetLastException]; [self->inboxFolder status]; if ([self->inboxFolder hasNewMessagesSearchRecursiv:NO]) return YES; result = NO; enumerator = [self->folderForRefresh objectEnumerator]; while ((f = [enumerator nextObject])) { [f status]; if ([f hasNewMessagesSearchRecursiv:NO]) { result = YES; break; } } return self->lastException ? NO : result; } - (NSString *)host { return [self->connectionDictionary objectForKey:@"host"]; } - (NSString *)login { return [self->connectionDictionary objectForKey:@"login"]; } - (BOOL)registerForRefresh:(NGImap4Folder *)_folder { [self->folderForRefresh addObject:_folder]; return YES; } - (BOOL)removeFromRefresh:(NGImap4Folder *)_folder { [self->folderForRefresh removeObject:_folder]; return YES; } - (BOOL)removeAllFromRefresh { [self->folderForRefresh removeAllObjects]; return YES; } - (BOOL)refreshFolder { // TODO: explain // this runs status on each folder and status triggers notifications? NSEnumerator *enumerator; NGImap4Folder *f; BOOL refreshInbox = NO; if ([self lastException] != nil) return NO; enumerator = [self->folderForRefresh objectEnumerator]; [self resetLastException]; while ((f = [enumerator nextObject])) { if ([f isEqual:self->inboxFolder]) refreshInbox = YES; [f status]; } if (!refreshInbox) [self->inboxFolder status]; return self->lastException ? NO : YES; } - (id)serverName { return self->serverName; } - (id)serverKind { return self->serverKind; } - (id)serverVersion { return self->serverVersion; } - (id)serverSubVersion { return self->serverSubVersion; } - (id)serverTag { return self->serverTag; } /* synchronize */ - (void)resetSync { if (self->syncMode) [self->serverRoot resetSync]; else [self logWithFormat:@"WARNING: resetSync has no effect if syncMode == NO"]; } - (BOOL)isInSyncMode { return self->syncMode; } - (void)enterSyncMode { self->syncMode = YES; [self resetSync]; } - (void)leaveSyncMode { self->syncMode = NO; } - (BOOL)showOnlySubscribedInRoot { if (self->showOnlySubscribedInRoot == -1) return NO; return (self->showOnlySubscribedInRoot == 1) ? YES : NO; } - (BOOL)showOnlySubscribedInSubFolders { if (self->showOnlySubscribedInSubFolders == -1) return NO; return (self->showOnlySubscribedInSubFolders == 1) ? YES : NO; } - (BOOL)subscribeFolderFailed { if (self->subscribeFolderFailed == -1) return YES; return (self->subscribeFolderFailed == 1) ? YES : NO; } - (NSString *)sortEncoding { if (self->sortEncoding == nil) self->sortEncoding = @"UTF-8"; return self->sortEncoding; } /* Capability */ - (BOOL)canSort { if (self->capability == nil) { if (![self openConnection]) return NO; } if (self->canSort == -1) { self->canSort = ([self->capability containsObject:@"sort"])? 1 : 0; } return self->canSort; } - (BOOL)canQuota { if (self->capability == nil) { if (![self openConnection]) return NO; } if (self->canQuota == -1) { self->canQuota = ([self->capability containsObject:@"quota"])? 1 : 0; } return self->canQuota; } /* URL based factory */ + (id)messageWithURL:(id)_url { NGImap4Context *ctx; if (_url == nil) return nil; if (![_url isKindOfClass:[NSURL class]]) _url = [NSURL URLWithString:[_url stringValue]]; if ((ctx = [self imap4ContextWithURL:_url]) == nil) { NSLog(@"WARNING(%s): got no IMAP4 context for URL: %@", __PRETTY_FUNCTION__, _url); return nil; } return [ctx messageWithURL:_url]; } - (id)folderWithURL:(id)_url { NSString *path, *folderPath; if (_url != nil && ![_url isKindOfClass:[NSURL class]]) _url = [NSURL URLWithString:[_url stringValue]]; if (_url == nil) return nil; path = [_url path]; folderPath = [path stringByDeletingLastPathComponent]; return [self folderWithName:folderPath]; } - (id)messageWithURL:(id)_url { NSString *path, *folderPath; NGImap4Folder *f; unsigned messageID; if (_url != nil && ![_url isKindOfClass:[NSURL class]]) _url = [NSURL URLWithString:[_url stringValue]]; if (_url == nil) return nil; path = [_url path]; folderPath = [path stringByDeletingLastPathComponent]; messageID = [[path lastPathComponent] intValue]; if ((f = [self folderWithName:folderPath]) == nil) { [self logWithFormat:@"WARNING(%s): missing folder for URL: '%@'", __PRETTY_FUNCTION__, _url]; return nil; } return [f messageWithUid:messageID]; } /* description */ - (void)appendAttributesToDescription:(NSMutableString *)ms { NSString *tmp; if ((tmp = [self host]) != nil) [ms appendFormat:@" host=%@", tmp]; if ((tmp = [self login]) != nil) [ms appendFormat:@" login=%@", tmp]; if ((tmp = [self serverName]) != nil) [ms appendFormat:@" server='%@'", tmp]; [ms appendFormat:@" kind=%@/v%@.%@/tag=%@", [self serverName], [self serverKind], [self serverVersion], [self serverSubVersion]]; if (self->syncMode) [ms appendString:@" syncmode"]; } - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:64]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; [self appendAttributesToDescription:ms]; [ms appendString:@">"]; return ms; } @end /* NGImap4Context(Capability) */ SOPE/sope-mime/NGImap4/NGImap4Connection.h0000644000000000000000000001172215004363604017010 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of OpenGroupware.org. OGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. OGo 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with OGo; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGImap4Connection_H__ #define __NGImap4Connection_H__ #import /* NGImap4Connection A cached connection to an IMAP4 server plus some cached objects. Do not instantiate this object directly but rather use the NGImap4ConnectionManager. This API is intended to be simpler and more consistent than NGImap4Client. It caches: - the folder hierarchy - uid sets? - 'myrights' permissions of mailboxes ? */ @class NSString, NSDate, NSArray, NSDictionary, NSMutableArray, NSURL, NSMutableDictionary; @class NSException, NSData; @class NGImap4Client; @interface NGImap4Connection : NSObject { @public NGImap4Client *client; NSString *password; NSDate *creationTime; /* hierarchy cache */ NSMutableDictionary *subfolders; /* permission cache */ NSMutableDictionary *urlToRights; /* uids cache */ NSArray *cachedUIDs; NSURL *uidFolderURL; id uidSortOrdering; /* enabled extensions */ NSMutableDictionary *enabledExtensions; } - (id)initWithClient:(NGImap4Client *)_client password:(NSString *)_pwd; /* accessors */ - (NGImap4Client *)client; - (BOOL)isValidPassword:(NSString *)_pwd; - (NSDate *)creationTime; - (void)cacheHierarchyResults:(NSDictionary *)_hierarchy forURL:(NSURL *)_url; - (NSDictionary *)cachedHierarchyResultsForURL:(NSURL *)_url; - (void)flushFolderHierarchyCache; - (id)cachedUIDsForURL:(NSURL *)_url qualifier:(id)_q sortOrdering:(id)_so; - (void)cacheUIDs:(NSArray *)_uids forURL:(NSURL *)_url qualifier:(id)_q sortOrdering:(id)_so; - (NSString *)cachedMyRightsForURL:(NSURL *)_url; - (void)cacheMyRights:(NSString *)_rights forURL:(NSURL *)_url; - (void)flushMailCaches; /* utilities */ - (NSString *)imap4FolderNameForURL:(NSURL *)_url; - (NSString *)imap4FolderNameForURL:(NSURL *)_url removeFileName:(BOOL)_delfn; /* extensions methods */ - (NSException *)enableExtensions:(NSArray *)_extensions; /* folder operations */ - (NSArray *)subfoldersForURL:(NSURL *)_url; - (NSArray *)subfoldersForURL:(NSURL *)_url onlySubscribedFolders: (BOOL) subscribedFoldersOnly; - (NSArray *)allFoldersForURL:(NSURL *)_url; - (NSDictionary *) allFoldersMetadataForURL:(NSURL *)_url onlySubscribedFolders:(BOOL)_subscribedFoldersOnly; - (NSArray *)allFoldersForURL:(NSURL *)_url onlySubscribedFolders: (BOOL) subscribedFoldersOnly; - (BOOL)selectFolder:(id)_url; /* message operations */ - (NSArray *)fetchUIDsInURL:(NSURL *)_url qualifier:(id)_qualifier sortOrdering:(id)_so; - (NSArray *)fetchThreadedUIDsInURL:(NSURL *)_url qualifier:(id)_qualifier sortOrdering:(id)_so; - (NSArray *)fetchUIDs:(NSArray *)_uids inURL:(NSURL *)_url parts:(NSArray *)_parts; - (id)fetchURL:(NSURL *)_url parts:(NSArray *)_parts; - (NSData *)fetchContentOfBodyPart:(NSString *)_partId atURL:(NSURL *)_url; - (NSData *)fetchContentOfBodyPart:(NSString *)_partId atURL:(NSURL *)_url withPeek:(BOOL)_withPeek; /* message flags */ - (NSException *)addOrRemove:(BOOL)_flag flags:(id)_f toURL:(NSURL *)_url; - (NSException *)addFlags:(id)_f toURL:(NSURL *)_u; - (NSException *)removeFlags:(id)_f toURL:(NSURL *)_u; - (NSException *)markURLDeleted:(NSURL *)_url; - (NSException *)addFlags:(id)_f toAllMessagesInURL:(NSURL *)_url; /* posting new data */ - (NSException *)postData:(NSData *)_data flags:(id)_f toFolderURL:(NSURL *)_u; /* operations */ - (NSException *)expungeAtURL:(NSURL *)_url; /* copying and moving */ - (NSException *)copyMailURL:(NSURL *)_srcurl toFolderURL:(NSURL *)_desturl; /* managing folders */ - (BOOL)doesMailboxExistAtURL:(NSURL *)_url; - (id)infoForMailboxAtURL:(NSURL *)_url; - (NSException *)createMailbox:(NSString *)_mailbox atURL:(NSURL *)_url; - (NSException *)deleteMailboxAtURL:(NSURL *)_url; - (NSException *) deleteMailbox: (NSString *)_path; - (NSException *)moveMailboxAtURL:(NSURL *)_srcurl toURL:(NSURL *)_desturl; - (NSException *) moveMailbox: (NSString *)_srcname to: (NSString *)_destname; /* ACLs */ - (NSDictionary *)aclForMailboxAtURL:(NSURL *)_url; - (NSString *)myRightsForMailboxAtURL:(NSURL *)_url; @end #endif /* __NGImap4Connection_H__ */ SOPE/sope-mime/NGImap4/NGImap4Envelope.m0000644000000000000000000001312715004363604016474 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4Envelope.h" #include "NGImap4EnvelopeAddress.h" #include #include "imCommon.h" @implementation NGImap4Envelope static NGMimeRFC822DateHeaderFieldParser *dateParser = nil; + (void)initialize { dateParser = [[NGMimeRFC822DateHeaderFieldParser alloc] init]; } - (id)newEnvelopeAddressForEMail:(id)_email { if (![_email isNotNull]) return nil; if ([_email isKindOfClass:[NGImap4EnvelopeAddress class]]) return [_email copy]; if ([_email isKindOfClass:[NSDictionary class]]) { /* A body structure dictionary, contains those keys: hostName, mailboxName, personalName, sourceRoute */ return [[NGImap4EnvelopeAddress alloc] initWithBodyStructureInfo:_email]; } _email = [_email stringValue]; if (![_email isNotEmpty]) return nil; return [[NGImap4EnvelopeAddress alloc] initWithString:_email]; } - (NSArray *)envelopeAddressesForEMails:(NSArray *)_emails { NSMutableArray *ma; unsigned i, count; if (_emails == nil) return nil; if ((count = [_emails count]) == 0) return [NSArray array]; ma = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) { NGImap4EnvelopeAddress *envaddr; envaddr = [self newEnvelopeAddressForEMail:[_emails objectAtIndex:i]]; if (![envaddr isNotNull]) continue; [ma addObject:envaddr]; [envaddr release]; } return ma; } - (id)initWithMessageID:(NSString *)_msgID subject:(NSString *)_subject from:(NSArray *)_from replyTo:(NSArray *)_replyTo to:(NSArray *)_to cc:(NSArray *)_cc bcc:(NSArray *)_bcc { if ((self = [self init])) { self->msgId = [_msgID copy]; self->subject = [_subject copy]; self->from = [[self envelopeAddressesForEMails:_from] copy]; self->replyTo = [[self envelopeAddressesForEMails:_replyTo] copy]; self->to = [[self envelopeAddressesForEMails:_to] copy]; self->cc = [[self envelopeAddressesForEMails:_cc] copy]; self->bcc = [[self envelopeAddressesForEMails:_bcc] copy]; } return self; } - (id)initWithBodyStructureInfo:(NSDictionary *)_info { id lDate; if (![_info isNotNull]) { [self release]; return nil; } self = [self initWithMessageID:[_info valueForKey:@"messageId"] subject:[_info valueForKey:@"subject"] from:[_info valueForKey:@"from"] replyTo:[_info valueForKey:@"reply-to"] to:[_info valueForKey:@"to"] cc:[_info valueForKey:@"cc"] bcc:[_info valueForKey:@"bcc"]]; if (self == nil) return nil; /* extended ivars */ self->inReplyTo = [[_info valueForKey:@"in-reply-to"] copy]; if ([(lDate = [_info valueForKey:@"date"]) isNotNull]) { if ([lDate isKindOfClass:[NSDate class]]) self->date = [lDate copy]; else self->date = [[dateParser parseValue:lDate ofHeaderField:@"date"] copy]; } return self; } - (void)dealloc { [self->date release]; [self->subject release]; [self->inReplyTo release]; [self->msgId release]; [self->from release]; [self->sender release]; [self->replyTo release]; [self->to release]; [self->cc release]; [self->bcc release]; [super dealloc]; } /* accessors */ - (NSCalendarDate *)date { return self->date; } - (id)subject { return self->subject; } - (NSString *)inReplyTo { return self->inReplyTo; } - (NSString *)messageID { return self->msgId; } - (NSArray *)from { return self->from; } - (NGImap4EnvelopeAddress *)sender { return self->sender; } - (NSArray *)replyTo { return self->replyTo; } - (NSArray *)to { return self->to; } - (NSArray *)cc { return self->cc; } - (NSArray *)bcc { return self->bcc; } /* derived accessors */ - (BOOL)hasTo { return [self->to isNotEmpty] ? YES : NO; } - (BOOL)hasCC { return [self->cc isNotEmpty] ? YES : NO; } - (BOOL)hasBCC { return [self->bcc isNotEmpty] ? YES : NO; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if (self->date) [ms appendFormat:@" date='%@'", self->date]; if (self->subject) [ms appendFormat:@" subject='%@'", self->subject]; if (self->msgId) [ms appendFormat:@" msgid='%@'", self->msgId]; if (self->inReplyTo) [ms appendFormat:@" inreplyto='%@'", self->inReplyTo]; if (self->from) [ms appendFormat:@" from=%@", self->from]; if (self->replyTo) [ms appendFormat:@" reply-to=%@", self->replyTo]; if (self->sender) [ms appendFormat:@" sender=%@", [self->sender email]]; if (self->to) [ms appendFormat:@" to=%@", self->to]; if (self->cc) [ms appendFormat:@" cc=%@", self->cc]; if (self->bcc) [ms appendFormat:@" bcc=%@", self->bcc]; [ms appendString:@">"]; return ms; } @end /* NGImap4Envelope */ SOPE/sope-mime/NGImap4/NGImap4Functions.m0000644000000000000000000002350215004363604016665 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include "imCommon.h" @interface NGImap4Context(Private) - (void)setLastException:(NSException *)_exception; @end /*NGImap4Context(Private) */ @implementation NGImap4FolderHandler static int LogImapEnabled = -1; static NGImap4FolderHandler *sharedHandler = nil; // THREAD static BOOL debugFolderLookup = NO; + (id)sharedImap4FolderHandler { if (sharedHandler == nil) sharedHandler = [[self alloc] init]; return sharedHandler; } void _checkDefault() { if (LogImapEnabled == -1) { LogImapEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"ImapLogEnabled"]?1:0; } } BOOL _checkResult(NGImap4Context *_ctx, NSDictionary *_dict, const char *_command) { _checkDefault(); if (![[_dict objectForKey:@"result"] boolValue]) { if (![_ctx lastException]) { NGImap4ResponseException *exc; if (LogImapEnabled) { NSLog(@"ERROR[%s]: got error during %s: %@", __PRETTY_FUNCTION__, _command, _dict); } exc = [[NGImap4ResponseException alloc] initWithFormat: [_dict objectForKey:@"reason"]]; [_ctx setLastException:exc]; [_ctx removeAllFromRefresh]; [exc release]; exc = nil; } return NO; } return YES; } - (BOOL)isFolder:(id)_child aSubfolderOf:(id)_parent { return _isSubFolder(_parent, _child); } BOOL _isSubFolder(id parentFolder, id_folder) { NSEnumerator *enumerator; NGImap4Folder *folder; enumerator = [[parentFolder subFolders] objectEnumerator]; while ((folder = [enumerator nextObject])) { if ([_folder isEqual:folder]) break; if ([[parentFolder context] lastException]) return NO; } return (folder != nil) ? YES : NO; } - (NGImap4Folder *)subfolderWithName:(NSString *)_name parentFolder:(id)_parent ignoreCase:(BOOL)_caseIns { return _subFolderWithName(_parent, _name, _caseIns); } NGImap4Folder *_subFolderWithName (id _parent, NSString *_name, BOOL _caseIns) { NSEnumerator *enumerator; NGImap4Folder *f; if (_caseIns) _name = [_name lowercaseString]; if (debugFolderLookup) NSLog(@"LOOKUP %@ IN %@", _name, [_parent subFolders]); enumerator = [[_parent subFolders] objectEnumerator]; while ((f = [enumerator nextObject]) != nil) { NSString *n; n = [f name]; if (_caseIns) n = [n lowercaseString]; if ([n isEqualToString:_name]) { if (debugFolderLookup) NSLog(@" FOUND: %@", f); return f; } if ([[_parent context] lastException] != nil) { if (debugFolderLookup) { NSLog(@" FAILED: %@", [[_parent context] lastException]); } return nil; } } if (debugFolderLookup) NSLog(@" NOT FOUND."); return nil; } BOOL _hasNewMessagesInSubFolder(id _parent, BOOL _fetch) { NSEnumerator *enumerator; id obj; enumerator = [[_parent subFolders] objectEnumerator]; while ((obj = [enumerator nextObject])) { if ([obj hasNewMessagesSearchRecursiv:YES fetchOnDemand:_fetch]) return YES; if ([[_parent context] lastException]) return NO; } return NO; } BOOL _hasUnseenMessagesInSubFolder(id self, BOOL _fetch) { NSEnumerator *enumerator; id obj; enumerator = [[self subFolders] objectEnumerator]; while ((obj = [enumerator nextObject])) { if ([obj hasUnseenMessagesSearchRecursiv:YES fetchOnDemand:_fetch]) return YES; if ([[self context] lastException]) return NO; } return NO; } BOOL _deleteSubFolder(id self, NGImap4Folder *_folder) { /* TODO: jr, why is this a function and not a method ? AW: they will be used in 2 different classes ... 'grep _deleteSubFolder *.m' */ NSEnumerator *enumerator; NGImap4Folder *folder; NGImap4Context *ctx; _checkDefault(); ctx = [self context]; [ctx resetLastException]; if (!_isSubFolder(self, _folder)) { if (LogImapEnabled) { NSLog(@"ERROR: Couldn`t delete %@ because it`s no subfolder of %@", _folder, self); } return NO; } enumerator = [[_folder subFolders] objectEnumerator]; while ((folder = [enumerator nextObject])) { [_folder deleteSubFolder:folder]; if ([ctx lastException]) { [self resetSubFolders]; return NO; } } if (![_folder isReadOnly] && ![_folder noselect]) { NSDictionary *result; if ([self isKindOfClass:[NGImap4Folder class]]) { if (![ctx registerAsSelectedFolder:(NGImap4Folder *)self]) { [self resetSubFolders]; return NO; } } [ctx resetLastException]; result = [[ctx client] delete:[_folder absoluteName]]; if (!_checkResult(ctx, result, __PRETTY_FUNCTION__)) { [self resetSubFolders]; return NO; } [self resetSubFolders]; [ctx removeFromRefresh:_folder]; return YES; } return NO; } BOOL _copySubFolder(id self, id _f, id _toFolder) { /* TODO: jr, why is this a function and not a method ? AW: they will be used in 2 different classes ... 'grep _deleteSubFolder *.m' */ NSEnumerator *enumerator; NGImap4Folder *folder, *subFolder; NSString *folderName; _checkDefault(); if (!_isSubFolder(self, _f)) { if (LogImapEnabled) { NSLog(@"ERROR: Couldn`t copy %@ because it`s no subfolder of %@", _f, self); } return NO; } if ([[_toFolder absoluteName] hasPrefix:[_f absoluteName]]) { if (LogImapEnabled) { NSLog(@"ERROR: Couldn`t copy %@ is subFolder from %@", _toFolder, _f); } return NO; } if ([self isEqual:_toFolder]) return YES; folderName = [_f name]; self = [self retain]; if (![_toFolder createSubFolderWithName:folderName]) { return NO; } [self autorelease]; enumerator = [[_toFolder subFolders] objectEnumerator]; while ((folder = [enumerator nextObject])) { if ([[folder name] isEqualToString:folderName]) break; if ([[self context] lastException]) return NO; } if (!folder) return NO; if (![_f noselect]) { if (![[self context] registerAsSelectedFolder:(NGImap4Folder *)_f]) return NO; if ([_f exists] > 0) { NSDictionary *res; res = [[[self context] client] copyFrom:0 to:[_f exists] toFolder:[folder absoluteName]]; if (!_checkResult([self context], res, __PRETTY_FUNCTION__)) return NO; } } [folder resetFolder]; enumerator = [[_f subFolders] objectEnumerator]; while ((subFolder = [enumerator nextObject])) { if (![_f copySubFolder:subFolder to:folder]) break; if ([[self context] lastException]) return NO; } return (subFolder == nil) ? YES : NO; } BOOL _moveSubFolder(id self, NGImap4Folder *_f, id_folder) { if (!_isSubFolder(self, _f)) return NO; if ([[_folder absoluteName] hasSuffix:[_f absoluteName]]) /* _folder is the same as or a subfolder from _f */ return NO; if ([_folder isEqual:self]) return YES; if (![self copySubFolder:_f to:(NGImap4Folder *)_folder]) return NO; return [self deleteSubFolder:_f]; } BOOL _createSubFolderWithName(id self, NSString *_name, BOOL _append) { NGImap4Context *ctx; NSRange r; NSDictionary *res; if (_name == nil) return NO; ctx = [self context]; r = [_name rangeOfString:[[ctx client] delimiter]]; if (r.length > 0) { NSException *e; e = [[NGImap4Exception alloc] initWithFormat:@"It`s not allowed to use '%@' in " @"a foldername <%@>", [[ctx client] delimiter], _name]; [ctx setLastException:e]; [e release]; return NO; } [ctx resetLastException]; if (_append) _name = [[self absoluteName] stringByAppendingPathComponent:_name]; res = [[ctx client] create:_name]; if (!_checkResult(ctx, res, __PRETTY_FUNCTION__)) return NO; res = [[ctx client] subscribe:_name]; if (!_checkResult(ctx, res, __PRETTY_FUNCTION__)) return NO; [self resetSubFolders]; return YES; } - (NSException *)createSubfolderWithName:(NSString *)_name parentFolder:(id)_parent append:(BOOL)_append { if (_createSubFolderWithName(_parent, _name, _append)) return nil; return [[_parent context] lastException]; } @end /* NGImap4FolderHandler */ NSString * SaneFolderName(NSString *folderName) { NSString *saneFName; saneFName = [[folderName stringByReplacingString: @"\\" withString: @"\\\\"] stringByReplacingString: @"\"" withString: @"\\\""]; return saneFName; } SOPE/sope-mime/NGImap4/NGSieveClient.h0000644000000000000000000000623115004363604016227 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __Networking_NGImap4_NGSieveClient_H__ #define __Networking_NGImap4_NGSieveClient_H__ #import #include #include #include #include /* NGSieveClient This implements a client for server stored Sieve scripts as supported by the Cyrus IMAP server. */ @class NSMutableArray, NSString, NSNumber, NSDictionary, NSArray, NSException; @class EOQualifier; @class NGHashMap; @class NGBufferedStream; typedef enum { UnConnected_NGSieveState = 1, NonAuthenticated_NGSieveState, Authenticated_NGSieveState, } NGSieveState; @interface NGSieveClient : NSObject { @protected id socket; id previous_socket; NGBufferedStream *io; id address; NGImap4ResponseParser *parser; NSException *lastException; BOOL isLogin; NSString *authname; NSString *login; NSString *password; NSString *serverType; NSArray *capabilities; BOOL debug; BOOL useTLS; int tlsVerifyMode; } + (id)clientWithURL:(id)_url andAuthMech:(NSString *) imapAuthMech; + (id)clientWithAddress:(id)_address; + (id)clientWithHost:(id)_host; - (id)initWithURL:(id)_url andAuthMech:(NSString *) imapAuthMech; - (id)initWithHost:(id)_host; - (id)initWithAddress:(id)_address; /* accessors */ - (id)socket; - (id)address; /* exceptions */ - (NSException *)lastException; - (void)resetLastException; /* connection */ - (NSDictionary *)openConnection; - (void)closeConnection; - (NSNumber *)isConnected; - (void)reconnect; /* commands */ - (NSDictionary *)login:(NSString *)_login password:(NSString *)_passwd; - (NSDictionary *)login:(NSString *)_login authname:(NSString *)_authname password:(NSString *)_passwd; - (NSDictionary *)logout; - (NSString *)getScript:(NSString *)_scriptName; - (NSDictionary *)putScript:(NSString *)_name script:(NSString *)_script; - (NSDictionary *)setActiveScript:(NSString *)_name; - (NSDictionary *)deleteScript:(NSString *)_script; - (NSDictionary *)listScripts; /* equality */ - (BOOL)isEqualToSieveClient:(NGSieveClient *)_obj; /* Misc */ - (NSString *) serverType; - (NSArray *) capabilities; - (BOOL) hasCapability: (NSString *)_capabilityName; @end #endif /* __Networking_NGSieve_NGSieveClient_H__ */ SOPE/sope-mime/NGImap4/NGImap4Support.h0000644000000000000000000000601715004363604016366 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __Networking_NGImap4_NGImap4Support_H__ #define __Networking_NGImap4_NGImap4Support_H__ #import @class NSDictionary, NSString, NSArray, EOQualifier, NSNumber, NSData; @class NGImap4Client, NGImap4Context, NGImap4Folder; @protocol NGImap4Folder - (NGImap4Context *)context; - (NGImap4Folder *)parentFolder; - (NSString *)name; - (NSString *)absoluteName; - (BOOL)renameTo:(NSString *)_name; - (BOOL)isInTrash; - (NSArray *)messageFlags; - (NSArray *)messages; - (NSArray *)messagesForQualifier:(EOQualifier *)_qualifier; - (NSArray *)messagesForQualifier:(EOQualifier *)_qualifier maxCount:(int)_cnt; - (BOOL)deleteMessages:(NSArray *)_messages; - (BOOL)deleteAllMessages; - (BOOL)moveMessages:(NSArray *)_messages toFolder:(NGImap4Folder *)_folder; - (BOOL)copyMessages:(NSArray *)_messages toFolder:(NGImap4Folder *)_folder; - (BOOL)appendMessage:(NSData *)_msg; - (BOOL)hasNewMessagesSearchRecursiv:(BOOL)_recursiv; - (BOOL)hasUnseenMessagesSearchRecursiv:(BOOL)_recursiv; - (BOOL)addFlag:(NSString *)_flag toMessages:(NSArray *)_messages; - (BOOL)removeFlag:(NSString *)_flag fromMessages:(NSArray *)_messages; - (NSArray *)subFolders; - (NGImap4Folder *)subFolderWithName:(NSString *)_name caseInsensitive:(BOOL)_caseIns; - (BOOL)deleteSubFolder:(NGImap4Folder *)_folder; - (BOOL)createSubFolderWithName:(NSString *)_name; - (BOOL)copySubFolder:(NGImap4Folder *)_f to:(NGImap4Folder *)_folder; - (BOOL)moveSubFolder:(NGImap4Folder *)_f to:(NGImap4Folder *)_folder; - (BOOL)isReadOnly; - (BOOL)noselect; - (BOOL)noinferiors; - (int)exists; - (int)recent; - (int)unseen; - (void)status; - (void)select; - (void)expunge; - (int)usedSpace; - (int)maxQuota; - (BOOL)isOverQuota; - (void)resetFolder; - (void)resetSubFolders; - (void)resetStatus; - (void)resetSync; @end @protocol NGImap4ResponseReceiver - (void)responseNotificationFrom:(NGImap4Client *)_client response:(NSDictionary *)_dict; @end @interface NGImap4Exception : NSException @end @interface NGImap4ParserException : NGImap4Exception @end @interface NGImap4ConnectionException : NGImap4Exception @end @interface NGImap4ResponseException : NGImap4Exception @end @interface NGImap4SearchException : NGImap4Exception @end #endif /* __Networking_NGImap4_NGImap4Support_H__ */ SOPE/sope-mime/NGImap4/NGImap4Folder.m0000644000000000000000000014642015004363604016135 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4Folder.h" #include "NGImap4Context.h" #include "NGImap4Client.h" #include "NGImap4Message.h" #include "NGImap4Functions.h" #include "NGImap4FolderGlobalID.h" #include "NGImap4FolderMailRegistry.h" #include "NGImap4FolderFlags.h" #include "imCommon.h" @interface NGImap4Message(Private) - (void)_setHeaders:(NGHashMap *)_headers size:(unsigned)_size flags:(NSArray *)_flags; - (BOOL)isComplete; - (void)setIsRead:(BOOL)_isRead; @end /* NGImap4Message(Private) */ @interface NGImap4Context(Private) - (void)setLastException:(NSException *)_exception; - (void)setSelectedFolder:(NGImap4Folder *)_folder; @end /* NGImap4Context(Private) */ @interface NGImap4Folder(Private) - (void)_resetFolder; - (void)_resetSubFolder; - (void)quota; - (NSArray *)initializeMessagesFrom:(unsigned)_from to:(unsigned)_to; - (NSArray *)initializeMessages; - (void)initializeSubFolders; - (void)addSubFolder:(NGImap4Folder *)_folder; - (BOOL)flag:(NSString*)_doof toMessages:(NSArray*)_msg add:(NSNumber*)_n; - (BOOL)flagToAllMessages:(NSString *)_flag add:(NSNumber *)_add; - (NSArray *)fetchMessagesFrom:(unsigned)_from to:(unsigned)_to; #if USE_MESSAGE_CACHE - (void)resetQualifierCache; #endif - (void)setRecent:(NSNumber *)_rec exists:(NSNumber *)_exists; - (void)clearParentFolder; - (BOOL)_testMessages:(NSArray *)_msgs operation:(NSString *)_op; - (NSArray *)_getMsnRanges:(NSArray *)_msgs; - (NSArray *)_calculateSequences:(NSMutableArray *)_numbers count:(int)_cnt; - (NSNotificationCenter *)notificationCenter; - (void)_registerForNotifications; @end /* NGImap4Folder(Private) */ @implementation NGImap4Folder static NSNumber *YesNumber = nil; static NSNumber *NoNumber = nil; static NSArray *StatusFlags = nil; static NSArray *UnseenFlag = nil; static BOOL ImapDebugEnabled = NO; static int ShowNonExistentFolder = -1; static int IgnoreHasNoChildrenFlag = -1; static int FetchNewUnseenMessagesInSubFoldersOnDemand = -1; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; static BOOL didInit = NO; if (didInit) return; didInit = YES; YesNumber = [[NSNumber numberWithBool:YES] retain]; NoNumber = [[NSNumber numberWithBool:NO] retain]; StatusFlags = [[NSArray alloc] initWithObjects:@"messages", @"recent", @"unseen", nil]; UnseenFlag = [[NSArray alloc] initWithObjects:@"unseen", nil]; ShowNonExistentFolder = [ud boolForKey:@"ShowNonExistentFolder"] ? 1 : 0; IgnoreHasNoChildrenFlag = [ud boolForKey:@"IgnoreHasNoChildrenFlag"] ? 1 : 0; ImapDebugEnabled = [ud boolForKey:@"ImapDebugEnabled"]; FetchNewUnseenMessagesInSubFoldersOnDemand = [ud boolForKey:@"FetchNewUnseenMessagesInSubFoldersOnDemand"] ? 1 : 0; } - (id)init { [self release]; [self logWithFormat:@"ERROR: cannot init NGImap4Folder with -init!"]; [self doesNotRecognizeSelector:_cmd]; return nil; } - (void)_setupMessageCache { #if USE_MESSAGE_CACHE self->cacheIdx = 0; self->qualifierCache = [[NSMutableArray alloc] initWithCapacity:MAX_QUALIFIER_CACHE]; self->messagesCache = [[NSMutableArray alloc] initWithCapacity:MAX_QUALIFIER_CACHE]; #endif } - (id)initWithContext:(NGImap4Context *)_context name:(NSString *)_name flags:(NSArray *)_flags parentFolder:(id)_folder { if ((self = [super init])) { self->context = [_context retain]; self->flags = [[NGImap4FolderFlags alloc] initWithFlagArray:_flags]; self->name = [_name copy]; self->parentFolder = _folder; self->mailRegistry = [[NGImap4FolderMailRegistry alloc] init]; /* mark as 'to be fetched' */ self->exists = -1; self->recent = -1; self->unseen = -1; self->usedSpace = -1; self->maxQuota = -1; self->overQuota = -1; self->failedFlags.status = NO; self->failedFlags.select = NO; self->failedFlags.quota = NO; // TODO: this also looks pretty weird! if ([[self->name lowercaseString] isEqualToString:@"/inbox"] && [self->flags doNotSelectFolder]) { NSDictionary *res; [self resetLastException]; res = [[self->context client] subscribe:[self absoluteName]]; if ([self lastException] != nil) { [self release]; return nil; } if ([[res objectForKey:@"result"] boolValue]) [self->flags allowFolderSelect]; } [self _registerForNotifications]; [self _setupMessageCache]; } #if NGIMAP_FOLDER_DEBUG return [self->context registerFolder:self]; #else return self; #endif } - (void)dealloc { [[self notificationCenter] removeObserver:self]; [self->context removeSelectedFolder:self]; [self->subFolders makeObjectsPerformSelector:@selector(clearParentFolder)]; [self->mailRegistry release]; [self->msn2UidCache release]; [self->context release]; [self->flags release]; [self->name release]; [self->subFolders release]; [self->messageFlags release]; [self->url release]; #if USE_MESSAGE_CACHE [self->messages release]; [self->qualifierCache release]; [self->messagesCache release]; #endif self->isReadOnly = nil; self->parentFolder = nil; [super dealloc]; } - (BOOL)isEqual:(id)_obj { if (self == _obj) return YES; if ([_obj isKindOfClass:[NGImap4Folder class]]) return [self isEqualToImap4Folder:_obj]; return NO; } - (BOOL)isEqualToImap4Folder:(NGImap4Folder *)_folder { if (self == _folder) return YES; if (([[_folder absoluteName] isEqualToString:self->name]) && [_folder context] == self->context) { return YES; } return NO; } /* accessors */ - (NSException *)lastException { return [self->context lastException]; } - (void)resetLastException { [self->context resetLastException]; } - (NGImap4Context *)context { return self->context; } - (NSString *)name { return [[self absoluteName] lastPathComponent]; } - (NSString *)absoluteName { // TODO: sometimes this contains a name with no / in front (eg Dovecot on // MacOSX). Find out why this is. return self->name; } - (NSArray *)flags { return [self->flags flagArray]; } - (NSArray *)messages { return [self initializeMessages]; } - (BOOL)_checkResult:(NSDictionary *)_dict cmd:(const char *)_command { return _checkResult(self->context, _dict, _command); } - (NSArray *)messagesForQualifier:(EOQualifier *)_qualifier maxCount:(int)_cnt { // TODO: split up method NSMutableArray *mes = nil; NSMutableArray *msn = nil; NSDictionary *dict = nil; NSAutoreleasePool *pool = nil; if ([self->flags doNotSelectFolder] || self->failedFlags.select) return nil; if (![self->context registerAsSelectedFolder:self]) return nil; pool = [[NSAutoreleasePool alloc] init]; #if USE_MESSAGE_CACHE if (self->cacheIdx > 0) { NSEnumerator *qualifierEnum = nil; EOQualifier *qual = nil; int cnt = 0; qualifierEnum = [self->qualifierCache objectEnumerator]; while ((qual = [qualifierEnum nextObject])) { if ([qual isEqual:_qualifier]) { NSArray *m; m = [[self->messagesCache objectAtIndex:cnt] retain]; [pool release]; return [m autorelease]; } cnt++; } } #endif [self resetLastException]; dict = [[self->context client] searchWithQualifier:_qualifier]; if (![self _checkResult:dict cmd:__PRETTY_FUNCTION__]) return nil; msn = [[dict objectForKey:@"search"] mutableCopy]; if ((msn == nil) || ![msn isNotEmpty]) { mes = [NSArray array]; } else { NSEnumerator *seq = nil; NSDictionary *obj = nil; mes = [NSMutableArray arrayWithCapacity:512]; seq = [[self _calculateSequences:msn count:_cnt] objectEnumerator]; while ((obj = [seq nextObject])) { NSArray *a; a = [self fetchMessagesFrom: [[obj objectForKey:@"start"] unsignedIntValue] to:[[obj objectForKey:@"end"] unsignedIntValue]]; if ([self lastException] != nil) break; if (a) [mes addObjectsFromArray:a]; } mes = [[mes copy] autorelease]; } [msn release]; #if USE_MESSAGE_CACHE if (self->cacheIdx == 5) self->cacheIdx = 0; if ([self->qualifierCache count] == self->cacheIdx) [self->qualifierCache addObject:_qualifier]; else [self->qualifierCache replaceObjectAtIndex:self->cacheIdx withObject:_qualifier]; if ([self->messagesCache count] == self->cacheIdx) [self->messagesCache addObject:mes]; else { [self->messagesCache replaceObjectAtIndex:self->cacheIdx withObject:mes]; } self->cacheIdx++; #endif mes = [mes retain]; [pool release]; if ([self lastException]) { [mes release]; return nil; } return [mes autorelease]; } - (NSArray *)messagesForQualifier:(EOQualifier *)_qualifier { return [self messagesForQualifier:_qualifier maxCount:-1]; } - (NSArray *)messageFlags { if (self->messageFlags == nil) [self->context registerAsSelectedFolder:self]; return self->messageFlags; } - (NSArray *)subFolders { if (self->subFolders == nil) [self initializeSubFolders]; return self->subFolders; } - (NGImap4Folder *)subFolderWithName:(NSString *)_name caseInsensitive:(BOOL)_caseIns { return _subFolderWithName(self, _name, _caseIns); } - (id)parentFolder { return self->parentFolder; } - (BOOL)isReadOnly { if (self->isReadOnly == nil) [self->context registerAsSelectedFolder:self]; return (self->isReadOnly == YesNumber) ? YES : NO; } /* flags */ - (BOOL)noselect { return [self->flags doNotSelectFolder]; } - (BOOL)noinferiors { return [self->flags doesNotSupportSubfolders]; } - (BOOL)nonexistent { return [self->flags doesNotExist]; } - (BOOL)haschildren { return [self->flags hasSubfolders]; } - (BOOL)hasnochildren { return [self->flags hasNoSubfolders]; } - (BOOL)marked { return [self->flags isMarked]; } - (BOOL)unmarked { return [self->flags isUnmarked]; } - (int)exists { if (self->exists == -1) { [self status]; } return self->exists; } - (int)recent { if (self->recent == -1) [self status]; return self->recent; } - (int)unseen { if (self->unseen == -1) [self status]; return self->unseen; } - (BOOL)isOverQuota { if (self->overQuota == -1) [self->context registerAsSelectedFolder:self]; return (self->overQuota == 1)? YES : NO; } - (int)usedSpace { if (self->usedSpace == -1) [self quota]; return self->usedSpace; } - (int)maxQuota { if (self->maxQuota == -1) [self quota]; return self->maxQuota; } - (BOOL)hasNewMessagesSearchRecursiv:(BOOL)_rec fetchOnDemand:(BOOL)_fetch { if (_fetch) { if (([self recent] > 0) && ([self unseen] > 0)) return YES; } else { if ((self->recent > 0) && (self->unseen > 0)) return YES; } if (_rec) return _hasNewMessagesInSubFolder(self, _fetch); return NO; } - (BOOL)hasNewMessagesSearchRecursiv:(BOOL)_recursiv { if (([self recent] > 0) && ([self unseen] > 0)) return YES; if (_recursiv) { return _hasNewMessagesInSubFolder(self, FetchNewUnseenMessagesInSubFoldersOnDemand); } return NO; } - (BOOL)hasUnseenMessagesSearchRecursiv:(BOOL)_rec fetchOnDemand:(BOOL)_fetch { if (_fetch) { if ([self unseen] > 0) return YES; } else if (self->unseen > 0) return YES; if (_rec) return _hasUnseenMessagesInSubFolder(self, _fetch); return NO; } - (BOOL)hasUnseenMessagesSearchRecursiv:(BOOL)_recursiv { if ([self unseen] > 0) return YES; if (_recursiv) return _hasUnseenMessagesInSubFolder(self, FetchNewUnseenMessagesInSubFoldersOnDemand); return NO; } /* notifications (fix that junk!) */ - (NSNotificationCenter *)notificationCenter { static NSNotificationCenter *nc = nil; if (nc == nil) nc = [[NSNotificationCenter defaultCenter] retain]; return nc; } - (NSString *)resetFolderNotificationName { return [@"NGImap4FolderReset_" stringByAppendingString:[self absoluteName]]; } - (NSString *)resetSubfolderNotificationName { return [@"NGImap4SubFolderReset__" stringByAppendingString:[self absoluteName]]; } - (void)_registerForNotifications { NSNotificationCenter *nc; NSString *n; nc = [self notificationCenter]; n = [self absoluteName]; // TODO: fix that junk! if ([n isNotEmpty]) { [nc addObserver:self selector:@selector(_resetFolder) name:[self resetFolderNotificationName] object:nil]; [nc addObserver:self selector:@selector(_resetSubFolder) name:[self resetSubfolderNotificationName] object:nil]; } } - (void)_postResetFolderNotification { [[self notificationCenter] postNotificationName: [self resetFolderNotificationName] object:nil]; } - (void)_postResetSubfolderNotification { [[self notificationCenter] postNotificationName: [self resetSubfolderNotificationName] object:nil]; } /* private methods */ - (NSArray *)initializeMessages { return [self initializeMessagesFrom:0 to:[self exists]]; } - (NSArray *)initializeMessagesFrom:(unsigned)_from to:(unsigned)_to { #if USE_MESSAGE_CACHE if (self->messages == nil) { self->messages = [[NSMutableArray alloc] initWithCapacity:_to]; } [self->messages addObjectsFromArray:[self fetchMessagesFrom:_from to:_to]]; return self->messages; #else return [self fetchMessagesFrom:_from to:_to]; #endif } - (NGImap4Message *)createMessageForUid:(unsigned)_uid headers:(id)_headers size:(unsigned)_size flags:(NSArray *)_flags { return [[NGImap4Message alloc] initWithUid:_uid headers:_headers size:_size flags:_flags folder:self context:self->context]; } - (NSArray *)_buildMessagesFromFetch:(NSDictionary *)_fetch usingMessages:(NSDictionary *)_messages { NSEnumerator *mEnum; NSDictionary *m; NGMimeMessageParser *parser; NSMutableArray *mes; NSAutoreleasePool *pool; pool = [[NSAutoreleasePool alloc] init]; mEnum = [[_fetch objectForKey:@"fetch"] objectEnumerator]; mes = nil; if (_messages == nil) mes = [[NSMutableArray alloc] initWithCapacity:512]; parser = [[[NGMimeMessageParser alloc] init] autorelease]; // TODO: should we disable parsing of some headers? but which? // is this method only for parsing headers?! while ((m = [mEnum nextObject])) { NGDataStream *stream = nil; NSData *headerData; id headers, uid, f, size; headerData = [m objectForKey:@"header"]; uid = [m objectForKey:@"uid"]; f = [m objectForKey:@"flags"]; size = [m objectForKey:@"size"]; if (headerData == nil || uid == nil || f == nil || size == nil) { [self logWithFormat:@"WARNING[%s]: got no header, uid, flags, size " @"for %@", __PRETTY_FUNCTION__, m]; continue; } if (([f containsObject:@"recent"]) && ([f containsObject:@"seen"])) { f = [f mutableCopy]; [f removeObject:@"recent"]; [f autorelease]; } /* setup parser */ stream = [[NGDataStream alloc] initWithData:headerData mode:NGStreamMode_readOnly]; [parser prepareForParsingFromStream:stream]; [stream release]; stream = nil; /* parse */ headers = [parser parseHeader]; if (_messages) { NGImap4Message *msg; if ((msg = [_messages objectForKey:uid]) == nil) { [self logWithFormat:@"WARNING[%s]: missing message for uid %@ from " @"fetch %@ in dict %@", __PRETTY_FUNCTION__, uid, _fetch, _messages]; continue; } [msg _setHeaders:headers size:[size intValue] flags:f]; } else { NGImap4Message *m; m = [self createMessageForUid:[uid unsignedIntValue] headers:headers size:[size unsignedIntValue] flags:f]; if (m) [mes addObject:m]; [m release]; } } NSArray *a = [mes copy]; [mes release]; mes = nil; [pool release]; return [a autorelease];; } - (NSArray *)_buildMessagesFromFetch:(NSDictionary *)_fetch { return [self _buildMessagesFromFetch:_fetch usingMessages:nil]; } - (NSArray *)_messageIds:(NSArray *)_so onlyUnseen:(BOOL)_unseen { NSAutoreleasePool *pool; NSDictionary *dict; NSArray *uids; static EOQualifier *UnseenQual = nil; uids = nil; /* hack for sorting for unseen/seen */ if (UnseenQual == nil) { UnseenQual = [[EOKeyValueQualifier alloc] initWithKey:@"flags" operatorSelector: EOQualifierOperatorEqual value:@"unseen"]; } pool = [[NSAutoreleasePool alloc] init]; if ([_so count] == 1) { EOSortOrdering *so; so = [_so lastObject]; if ([[so key] isEqualToString:@"unseen"]) { static NSArray *DateSo = nil; static EOQualifier *SeenQual = nil; NSMutableArray *muids; EOQualifier *qual1, *qual2; if (DateSo == nil) { DateSo = [[NSArray alloc] initWithObjects: [EOSortOrdering sortOrderingWithKey:@"date" selector:[so selector]], nil]; } if (SeenQual == nil) { SeenQual = [[EOKeyValueQualifier alloc] initWithKey:@"flags" operatorSelector: EOQualifierOperatorEqual value:@"seen"]; } muids = [[NSMutableArray alloc] initWithCapacity:255]; if (sel_isEqual([so selector], EOCompareAscending) || sel_isEqual([so selector], EOCompareCaseInsensitiveAscending)) { qual1 = UnseenQual; if (_unseen) qual2 = nil; else qual2 = SeenQual; } else { if (_unseen) qual1 = nil; else qual1 = SeenQual; qual2 = UnseenQual; } if (qual1 != nil) { dict = [[self->context client] sort:DateSo qualifier:qual1 encoding:[self->context sortEncoding]]; if (![[dict objectForKey:@"result"] boolValue]) { [self logWithFormat:@"ERROR[%s](1): sort failed (sortOrderings %@, " @"qual1 %@)", __PRETTY_FUNCTION__, DateSo, qual1]; return nil; } [muids addObjectsFromArray:[dict objectForKey:@"sort"]]; } if (qual2 != nil) { dict = [[self->context client] sort:DateSo qualifier:qual2 encoding:[self->context sortEncoding]]; if (![[dict objectForKey:@"result"] boolValue]) { [self logWithFormat:@"ERROR[%s](2): sort failed (sortOrderings %@, " @"qual2 %@ ", __PRETTY_FUNCTION__, DateSo, qual2]; return nil; } [muids addObjectsFromArray:[dict objectForKey:@"sort"]]; } uids = [muids copy]; [muids release]; muids = nil; } } if (uids == nil) { EOQualifier *qual; if (![_so isNotEmpty]) { static NSArray *ArrivalSO = nil; if (ArrivalSO == nil) { ArrivalSO = [[NSArray alloc] initWithObjects: [EOSortOrdering sortOrderingWithKey:@"arrival" selector:EOCompareAscending], nil]; } _so = ArrivalSO; } if (_unseen) { qual = UnseenQual; } else qual = nil; [self resetLastException]; dict = [[self->context client] sort:_so qualifier:qual encoding:[self->context sortEncoding]]; if (![self _checkResult:dict cmd:__PRETTY_FUNCTION__]) return nil; uids = [[dict objectForKey:@"sort"] retain]; } [pool release]; pool = nil; return [uids autorelease]; } - (NSData *)blobForUid:(unsigned)_mUid part:(NSString *)_part { /* called by NGImap4Message -contentsOfPart: */ NSDictionary *result; NSArray *fetchResults; NSString *bodyKey; NSArray *uids, *parts; if (![self->context registerAsSelectedFolder:self]) return nil; bodyKey = [NSString stringWithFormat: @"body[%@]", _part ? _part : (NSString *)@""]; uids = [NSArray arrayWithObject:[NSNumber numberWithUnsignedInt:_mUid]]; parts = [NSArray arrayWithObject:bodyKey]; result = [[self->context client] fetchUids:uids parts:parts]; if (![self _checkResult:result cmd:__PRETTY_FUNCTION__]) { [self debugWithFormat:@"Note: _checkResult: rejected result %d/%@: %@", _mUid, _part, result]; return nil; } else if (result == nil) { [self debugWithFormat:@"Note: got no result for %d/%@", _mUid, _part]; return nil; } fetchResults = [result objectForKey:@"fetch"]; if (![fetchResults isNotEmpty]) [self debugWithFormat:@"found no fetch result"]; // TODO: using 'lastObject' is certainly wrong? need to search for body result = [fetchResults lastObject]; if ((result = [result objectForKey: _part ? bodyKey : @"body"]) == nil) [self debugWithFormat:@"found no body in fetch results: %@", fetchResults]; return [result objectForKey:@"data"]; } - (NGImap4Message *)messageForUid:(unsigned)_mUid sortOrderings:(NSArray *)_so onlyUnread:(BOOL)_unread nextMessage:(BOOL)_next { NSArray *uids, *allSortUids; NSEnumerator *enumerator; NSNumber *uid, *eUid, *lastUid; if ([self->flags doNotSelectFolder] || self->failedFlags.select) return nil; uid = [NSNumber numberWithUnsignedInt:_mUid]; allSortUids = [self _messageIds:_so onlyUnseen:NO]; uids = _unread ? [self _messageIds:_so onlyUnseen:_unread] : (NSArray *)nil; enumerator = [allSortUids objectEnumerator]; lastUid = nil; while ((eUid = [enumerator nextObject])) { if ([uid isEqual:eUid]) break; if (_unread) { if ([uids containsObject:eUid]) lastUid = eUid; } else lastUid = eUid; } if (eUid == nil) { [self logWithFormat:@"WARNING[%s]: Couldn`t found next/prev message " @"(missing orig. message %d for sortordering %@", __PRETTY_FUNCTION__, _mUid, _so]; return nil; } if (_next) { if (_unread) { while ((uid = [enumerator nextObject])) { if ([uids containsObject:uid]) break; } } else uid = [enumerator nextObject]; } else { uid = lastUid; } if (uid == nil) return nil; return [[[NGImap4Message alloc] initWithUid:[uid unsignedIntValue] folder:self context:self->context] autorelease]; } /* build NGImap4Messages with sorted uids */ - (NSArray *)fetchSortedMessages:(NSArray *)_so { NSArray *uids, *array; NSMutableArray *marray; NSAutoreleasePool *pool; NSEnumerator *enumerator; NSNumber *uid; if ([self->flags doNotSelectFolder] || self->failedFlags.select) return nil; if (![self->context registerAsSelectedFolder:self]) return nil; pool = [[NSAutoreleasePool alloc] init]; if (![_so isNotEmpty]) return [self messages]; if (!(uids = [self _messageIds:_so onlyUnseen:NO])) return [self messages]; enumerator = [uids objectEnumerator]; marray = [[NSMutableArray alloc] initWithCapacity:[uids count]]; while ((uid = [enumerator nextObject])) { NGImap4Message *m; m = [[NGImap4Message alloc] initWithUid:[uid intValue] folder:self context:self->context]; if (m) [marray addObject:m]; [m release]; } array = [marray shallowCopy]; [marray release]; marray = nil; [pool release]; pool = nil; return [array autorelease]; } /* fetch headers for _array in range (for use with fetchSortedMessages) */ - (void)bulkFetchHeadersFor:(NSArray *)_array inRange:(NSRange)_aRange withAllUnread:(BOOL)_unread { NSArray *messages, *uids; NSAutoreleasePool *pool; NSEnumerator *enumerator; NGImap4Message *message; NSMutableDictionary *messageMapping; NSDictionary *dict; NSArray *unreadUids; if ([self->flags doNotSelectFolder]) return; if (_aRange.length == 0) return; if (![self->context registerAsSelectedFolder:self]) return; pool = [[NSAutoreleasePool alloc] init]; if (_aRange.location >= [_array count]) { return; } if (_aRange.location + _aRange.length > [_array count]) { _aRange.length = [_array count] - _aRange.location; } messages = [_array subarrayWithRange:_aRange]; unreadUids = nil; if (_unread) { EOQualifier *q; NSDictionary *d; q = [EOQualifier qualifierWithQualifierFormat:@"flags = \"unseen\""]; d = [[self->context client] searchWithQualifier:q]; if ([[d objectForKey:@"result"] boolValue]) unreadUids = [d objectForKey:@"search"]; } enumerator = [messages objectEnumerator]; messageMapping = [NSMutableDictionary dictionaryWithCapacity: [messages count]]; while ((message = [enumerator nextObject]) != nil) { if (![message isComplete]) { [messageMapping setObject:message forKey:[NSNumber numberWithUnsignedInt:[message uid]]]; } } if ([unreadUids isNotEmpty]) { enumerator = [_array objectEnumerator]; while ((message = [enumerator nextObject])) { NSNumber *number; number = [NSNumber numberWithUnsignedInt:[message uid]]; if ([unreadUids containsObject:number]) [messageMapping setObject:message forKey:number]; } } if ([messageMapping isNotEmpty]) { static NSArray *sortKeys = nil; uids = [messageMapping allKeys]; if (sortKeys == nil) { sortKeys = [[NSArray alloc] initWithObjects:@"uid", @"rfc822.header", @"rfc822.size", @"flags", nil]; } dict = [[self->context client] fetchUids:uids parts:sortKeys]; if ([self _checkResult:dict cmd:__PRETTY_FUNCTION__]) { [self _buildMessagesFromFetch:dict usingMessages:messageMapping]; if (_unread) { /* set unfetched messeges to unread */ NSEnumerator *enumerator; NGImap4Message *m; enumerator = [_array objectEnumerator]; while ((m = [enumerator nextObject])) { NSNumber *n; n = [NSNumber numberWithUnsignedInt:[m uid]]; if (![uids containsObject:n]) [m setIsRead:YES]; } } } } [pool release]; pool = nil; return; } - (void)bulkFetchHeadersFor:(NSArray *)_array inRange:(NSRange)_aRange { [self bulkFetchHeadersFor:_array inRange:_aRange withAllUnread:NO]; } /* fetch only sorted messages in range */ - (NSArray *)fetchSortedMessages:(NSRange)_aRange sortOrderings:(NSArray *)_so { static NSArray *sortKeys = nil; NSDictionary *dict; NSArray *uids, *m; NSAutoreleasePool *pool; if ([self->flags doNotSelectFolder] || self->failedFlags.select) return nil; if (_aRange.length == 0) return [NSArray array]; if (![self->context registerAsSelectedFolder:self]) return nil; pool = [[NSAutoreleasePool alloc] init]; if ((uids = [self _messageIds:_so onlyUnseen:NO]) == nil) return nil; if (_aRange.location + _aRange.length > [uids count]) _aRange.length = [uids count] - _aRange.location; uids = [uids subarrayWithRange:_aRange]; if (sortKeys == nil) { sortKeys = [[NSArray alloc] initWithObjects:@"uid", @"rfc822.header", @"rfc822.size", @"flags", nil]; } dict = [[self->context client] fetchUids:uids parts:sortKeys]; if (![self _checkResult:dict cmd:__PRETTY_FUNCTION__]) return nil; m = [[self _buildMessagesFromFetch:dict] retain]; [pool release]; return [m autorelease]; } - (NSArray *)fetchMessagesFrom:(unsigned)_from to:(unsigned)_to { static NSArray *sortKeys = nil; NSAutoreleasePool *pool; NSDictionary *dict; NSArray *m; if ([self->flags doNotSelectFolder]) return nil; if (_from == 0) _from = 1; if (![self->context registerAsSelectedFolder:self]) return nil; if (_to == 0) return [NSArray array]; pool = [[NSAutoreleasePool alloc] init]; [self resetLastException]; /* TODO: normalize sort-key arrays? */ if (sortKeys == nil) { sortKeys = [[NSArray alloc] initWithObjects:@"uid", @"rfc822.header", @"rfc822.size", @"flags", nil]; } dict = [[self->context client] fetchFrom:_from to:_to parts:sortKeys]; if (![self _checkResult:dict cmd:__PRETTY_FUNCTION__]) return nil; m = [[self _buildMessagesFromFetch:dict] retain]; [pool release]; return [m autorelease]; } - (void)initializeSubFolders { NSEnumerator *folders; NSDictionary *res; id folder, *objs; unsigned cnt; BOOL showSubsrcFolders; NSString *pattern; if ([self->flags doesNotSupportSubfolders]) return; if (!IgnoreHasNoChildrenFlag && [self->flags hasNoSubfolders]) return; if (self->subFolders) [self resetSubFolders]; [self resetLastException]; showSubsrcFolders = [self->context showOnlySubscribedInSubFolders]; pattern = [[self absoluteName] stringByAppendingString:@"/%"]; res = (showSubsrcFolders) ? [[self->context client] lsub:@"" pattern:pattern] : [[self->context client] list:@"" pattern:pattern]; if (![self _checkResult:res cmd:__PRETTY_FUNCTION__]) return; res = [res objectForKey:@"list"]; objs = calloc([res count] + 2, sizeof(id)); { NSArray *names; names = [res allKeys]; names = [names sortedArrayUsingSelector: @selector(caseInsensitiveCompare:)]; folders = [names objectEnumerator]; } cnt = 0; while ((folder = [folders nextObject])) { NGImap4Folder *newFolder; NSArray *f; f = [res objectForKey:folder]; if (!ShowNonExistentFolder) { if ([f containsObject:@"nonexistent"]) continue; } newFolder = [NGImap4Folder alloc]; /* to keep gcc happy */ objs[cnt] = [[newFolder initWithContext:self->context name:folder flags:f parentFolder:self] autorelease]; if (objs[cnt] == nil) break; cnt++; } if (folder == nil) self->subFolders = [[NSArray alloc] initWithObjects:objs count:cnt]; if (objs) free(objs); } - (BOOL)select { return [self selectImmediately:NO]; } - (BOOL)selectImmediately:(BOOL)_imm { NSDictionary *dict; if ([self->flags doNotSelectFolder]) { [self logWithFormat:@"WARNING[%s]: try to select folder with noselect " @"flag <%@>", __PRETTY_FUNCTION__, self]; return NO; } if (self->failedFlags.select) return NO; if (!_imm) { if ([[self context] isInSyncMode] && self->selectSyncState) return YES; } [self resetLastException]; dict = [[self->context client] select:[self absoluteName]]; if (![self _checkResult:dict cmd:__PRETTY_FUNCTION__]) { self->failedFlags.select = YES; return NO; } [self->context setSelectedFolder:self]; ASSIGN(self->messageFlags, [dict objectForKey:@"flags"]); self->isReadOnly = [[dict objectForKey:@"access"] isEqualToString:@"READ-WRITE"] ? NoNumber : YesNumber; // TODO: isn't there a better way to check for overquota? if ([[dict objectForKey:@"alert"] isEqualToString:@"Mailbox is over quota"]) self->overQuota = 1; else self->overQuota = 0; [self setRecent:[dict objectForKey:@"recent"] exists:[dict objectForKey:@"exists"]]; self->maxQuota = -1; self->usedSpace = -1; self->failedFlags.quota = NO; self->selectSyncState = YES; return YES; } - (BOOL)status { NSDictionary *dict; if ([self->flags doNotSelectFolder]) return NO; if (self->failedFlags.status) return NO; [self->context resetLastException]; dict = [[self->context client] status:[self absoluteName] flags:StatusFlags]; if (![self _checkResult:dict cmd:__PRETTY_FUNCTION__]) { self->unseen = -1; self->recent = -1; self->exists = -1; self->maxQuota = -1; self->usedSpace = -1; self->overQuota = -1; self->failedFlags.status = YES; self->failedFlags.quota = NO; return NO; } [self setRecent:[dict objectForKey:@"recent"] exists:[dict objectForKey:@"messages"]]; self->unseen = [[dict objectForKey:@"unseen"] intValue]; return YES; } /* actions */ - (void)resetFolder { // TODO: shouldn't the post happen after the expunge? [self _postResetFolderNotification]; [self expunge]; } - (void)_resetFolder { #if USE_MESSAGE_CACHE [self resetQualifierCache]; #endif [self->msn2UidCache release]; self->msn2UidCache = nil; [self->flags release]; self->flags = nil; [self->messageFlags release]; self->messageFlags = nil; #if USE_MESSAGE_CACHE [self->messages release]; self->messages = nil; #endif self->maxQuota = -1; self->usedSpace = -1; self->overQuota = -1; self->failedFlags.select = NO; self->failedFlags.quota = NO; self->isReadOnly = nil; [self resetStatus]; } - (void)resetStatus { self->unseen = -1; self->exists = -1; self->recent = -1; self->failedFlags.status = NO; } - (void)_resetSubFolder { id ctx; ctx = [self context]; if ((self->parentFolder == nil) || (self == [ctx inboxFolder])) [ctx resetSpecialFolders]; [self->subFolders release]; self->subFolders = nil; } - (void)resetSubFolders { // TODO: explain in detail what this does NSString *n; n = [self absoluteName]; if ([n isNotEmpty]) [self _postResetSubfolderNotification]; else [self _resetSubFolder]; } - (BOOL)renameTo:(NSString *)_name { NSString *n; NSDictionary *dict; if ([self isReadOnly]) return NO; if ((_name == nil) || ([_name length] == 0)) return NO; n = [[self->name stringByDeletingLastPathComponent] stringByAppendingPathComponent:_name]; [self resetLastException]; dict = [[self->context client] rename:[self absoluteName] to:n]; if (![self _checkResult:dict cmd:__PRETTY_FUNCTION__]) return NO; ASSIGNCOPY(self->name, n); [self->globalID release]; self->globalID = nil; [self resetSubFolders]; dict = [[self->context client] subscribe:self->name]; if (![self _checkResult:dict cmd:__PRETTY_FUNCTION__]) return NO; return YES; } /* folder */ - (BOOL)deleteSubFolder:(NGImap4Folder *)_folder { if ([self isReadOnly]) return NO; return _deleteSubFolder(self, _folder);; } - (BOOL)copySubFolder:(NGImap4Folder *)_f to:(NGImap4Folder *)_folder { return _copySubFolder(self, _f, _folder); } - (BOOL)moveSubFolder:(NGImap4Folder *)_f to:(NGImap4Folder *)_folder { if ([self isReadOnly]) return NO; return _moveSubFolder(self, _f, _folder); } - (BOOL)createSubFolderWithName:(NSString *)_name { if ([self isReadOnly]) return NO; return _createSubFolderWithName(self, _name, YES); } - (void)expunge { NSDictionary *dict; if ([self->flags doNotSelectFolder] || self->failedFlags.select) return; if ([self isReadOnly]) return; if (![self->context registerAsSelectedFolder:self]) return; dict = [[self->context client] expunge]; if (![self _checkResult:dict cmd:__PRETTY_FUNCTION__]) return; [self setRecent:[dict objectForKey:@"recent"] exists:[dict objectForKey:@"exists"]]; } - (BOOL)addFlag:(NSString *)_flag toMessages:(NSArray *)_messages { return [self flag:_flag toMessages:_messages add:YesNumber]; } - (BOOL)removeFlag:(NSString *)_flag fromMessages:(NSArray *)_messages { return [self flag:_flag toMessages:_messages add:NoNumber]; } - (BOOL)flag:(NSString *)_flag toMessages:(NSArray *)_messages add:(NSNumber *)_add { NSEnumerator *enumerator; NGImap4Message *message; NSDictionary *obj; BOOL add; NSArray *flagArray; add = [_add boolValue]; if ([self->flags doNotSelectFolder]) return NO; if (_flag == nil) { [self logWithFormat:@"WARNING[%s]: try to set an empty flag", __PRETTY_FUNCTION__]; return NO; } if ([self isReadOnly]) return NO; if (![self->context registerAsSelectedFolder:self]) return NO; if (![self _testMessages:_messages operation:@"store"]) return NO; [self resetLastException]; enumerator = [[self _getMsnRanges:_messages] objectEnumerator]; if (enumerator == nil) { [self resetStatus]; [self->context removeSelectedFolder:self]; return NO; } flagArray = [_flag isNotNull] ? [NSArray arrayWithObject:_flag] : nil; while ((obj = [enumerator nextObject])) { NSDictionary *res; int objEnd, objStart; if ((objEnd = [[obj objectForKey:@"end"] unsignedIntValue]) <= 0) continue; objStart = [[obj objectForKey:@"start"] unsignedIntValue]; res = [[self->context client] storeFrom:objStart to:objEnd add:_add flags:flagArray]; if (![self _checkResult:res cmd:__PRETTY_FUNCTION__]) break; } if (obj) return NO; enumerator = [_messages objectEnumerator]; while ((message = [enumerator nextObject])) { if (add) [message addFlag:_flag]; else [message removeFlag:_flag]; } [self resetStatus]; return YES; } - (BOOL)flagToAllMessages:(NSString *)_flag add:(NSNumber *)_add { #if USE_MESSAGE_CACHE BOOL add = [_add boolValue]; NSEnumerator *enumerator = nil; NGImap4Message *m = nil; #endif if ([self->flags doNotSelectFolder]) return NO; if (_flag == nil) return NO; if ([self isReadOnly]) return NO; if (![self->context registerAsSelectedFolder:self]) return NO; if ([self exists] > 0) { NSDictionary *res; [self resetLastException]; res = [[self->context client] storeFrom:0 to:[self exists] add:_add flags:[NSArray arrayWithObject:_flag]]; if (![self _checkResult:res cmd:__PRETTY_FUNCTION__]) return NO; #if USE_MESSAGE_CACHE enumerator = [self->messages objectEnumerator]; while ((m = [enumerator nextObject])) { (add) ? [m addFlag:_flag] : [m removeFlag:_flag]; } #endif } return YES; } - (BOOL)deleteAllMessages { if ([self isReadOnly]) return NO; if ([self flagToAllMessages:@"Deleted" add:YesNumber]) { [self resetFolder]; return YES; } return NO; } - (BOOL)deleteMessages:(NSArray *)_messages { if ([self isReadOnly]) return NO; if ([self addFlag:@"Deleted" toMessages:_messages]) { [self resetFolder]; return YES; } return NO; } - (BOOL)moveMessages:(NSArray *)_messages toFolder:(NGImap4Folder *)_folder { if ([self isReadOnly]) return NO; if (_folder != nil) { if ([self copyMessages:_messages toFolder:_folder]) { return [self deleteMessages:_messages]; } } return NO; } - (BOOL)copyMessages:(NSArray *)_messages toFolder:(NGImap4Folder *)_folder { NSEnumerator *enumerator; NSDictionary *obj; NSString *folderName; if ([self->flags doNotSelectFolder]) return NO; folderName = [_folder absoluteName]; if (_folder == nil) { [self logWithFormat:@"WARNING[%s]: try to copy to nil folder", __PRETTY_FUNCTION__]; return NO; } [self resetLastException]; if ([_folder isReadOnly]) { NGImap4ResponseException *exc; [self logWithFormat:@"WARNING[%s]: try to copy to readonly folder %@", __PRETTY_FUNCTION__, _folder]; exc = [[NGImap4ResponseException alloc] initWithFormat: @"copy to read only folder"]; [self->context setLastException:exc]; [exc release]; exc = nil; return NO; } if (![self->context registerAsSelectedFolder:self]) return NO; if (![self _testMessages:_messages operation:@"copy"]) return NO; enumerator = [[self _getMsnRanges:_messages] objectEnumerator]; if (enumerator == nil) { [self resetStatus]; [self->context removeSelectedFolder:self]; return NO; } [self resetLastException]; if (![self->context registerAsSelectedFolder:self]) return NO; while ((obj = [enumerator nextObject])) { int objEnd; objEnd = [[obj objectForKey:@"end"] unsignedIntValue]; if (objEnd > 0) { NSDictionary *res; unsigned int start; start = [[obj objectForKey:@"start"] unsignedIntValue]; res = [[self->context client] copyFrom:start to:objEnd toFolder:folderName]; if (![self _checkResult:res cmd:__PRETTY_FUNCTION__]) break; } } [_folder resetFolder]; return (obj == nil) ? YES : NO; } - (BOOL)appendMessage:(NSData *)_msg { if ([self isReadOnly]) return NO; if (_msg != nil) { NSDictionary *dict; dict = [[self->context client] append:_msg toFolder:[self absoluteName] withFlags:[NSArray arrayWithObject:@"seen"]]; if ([self _checkResult:dict cmd:__PRETTY_FUNCTION__]) { [self resetFolder]; return YES; } } return NO; } #if USE_MESSAGE_CACHE - (void)resetQualifierCache { self->cacheIdx = 0; [self->qualifierCache removeAllObjects]; } #endif /* notifications */ - (void)setRecent:(NSNumber *)_rec exists:(NSNumber *)_exists { #if USE_MESSAGE_CACHE BOOL resetQualifier = NO; if (_rec != nil) { int tmp = [_rec intValue]; if (self->recent != tmp) { self->recent = tmp; resetQualifier = YES; } } if (_exists != nil) { int tmp = [_exists intValue]; if (self->exists != tmp) { self->exists = tmp; resetQualifier = YES; } } if (resetQualifier) [self resetQualifierCache]; #else { if (_exists != nil) { int e; e = [_exists intValue]; if (e == 0) { self->exists = 0; self->recent = 0; self->unseen = 0; } else { int r; r = [_rec intValue]; if ((e != self->exists) || (r != self->recent)) { self->exists = e; self->recent = r; self->unseen = -1; } } } } #endif } - (void)processResponse:(NSDictionary *)_dict { #if USE_MESSAGE_CACHE id exp = [_dict objectForKey:@"expunge"]; #endif [self setRecent:[_dict objectForKey:@"recent"] exists:[_dict objectForKey:@"exists"]]; #if USE_MESSAGE_CACHE if ((exp != nil) && ([exp count] > 0) && ([self->messages count] > 0)) { NSEnumerator *enumerator; id obj; enumerator = [exp objectEnumerator]; while ((obj = [enumerator nextObject])) { int n = [obj intValue] - 1; [self->messages removeObjectAtIndex:n]; } [self resetQualifierCache]; } #endif } - (BOOL)isInTrash { id f, trash; trash = [self->context trashFolder]; if (trash == nil) { [self logWithFormat:@"WARNING[%s]: No trash folder was set", __PRETTY_FUNCTION__]; return NO; } for (f = self; f; f = [f parentFolder]) { if ([f isEqual:trash]) return YES; } return NO; } - (void)resetSync { NSEnumerator *enumerator; id folder; self->selectSyncState = NO; if (self->subFolders == nil) return; enumerator = [[self subFolders] objectEnumerator]; while ((folder = [enumerator nextObject])) [folder resetSync]; } - (NSURL *)url { NSString *p; NSURL *base; if (self->url != nil) return self->url; if ((base = [self->context url]) == nil) { [self logWithFormat:@"ERROR: got no URL for context: %@", self->context]; return nil; } if ((p = [self absoluteName]) == nil) return nil; if (![p hasPrefix:@"/"]) p = [@"/" stringByAppendingString:p]; self->url = [[NSURL alloc] initWithScheme:[base scheme] host:[base host] path:p]; return self->url; } - (EOGlobalID *)serverGlobalID { return [self->context serverGlobalID]; } - (EOGlobalID *)globalID { if (self->globalID) return self->globalID; self->globalID = [[NGImap4FolderGlobalID alloc] initWithServerGlobalID: [self serverGlobalID] andAbsoluteName: [self absoluteName]]; return self->globalID; } /* quota information */ - (void)quota { NSString *n; NSDictionary *quota; if (self->failedFlags.quota) return; if (![self->context canQuota]) { [self logWithFormat:@"WARNING[%s] call quota but capability contains" @" no quota string", __PRETTY_FUNCTION__]; return; } n = [self absoluteName]; [self resetLastException]; if ([self->flags doNotSelectFolder]) return; quota = [[self->context client] getQuotaRoot:n]; if (![self _checkResult:quota cmd:__PRETTY_FUNCTION__]) { self->failedFlags.quota = YES; return; } quota = [quota objectForKey:@"quotas"]; quota = [quota objectForKey:n]; self->maxQuota = [[quota objectForKey:@"maxQuota"] intValue]; self->usedSpace = [[quota objectForKey:@"usedSpace"] intValue]; } - (BOOL)_testMessages:(NSArray *)_messages operation:(NSString *)_operation { NSEnumerator *enumerator; id obj; enumerator = [_messages objectEnumerator]; while ((obj = [enumerator nextObject])) { if ([obj folder] != self) { [self logWithFormat:@"ERROR: try to %@ mails in folder who didn`t own" @" this mail \nFolder %@\nMail %@ allMessages %@", _operation, self, obj, _messages]; return NO; } } return YES; } - (NSArray *)_getMsnRanges:(NSArray *)_messages { // TODO: might split up? document! static NSArray *UidKey = nil; NSArray *result; NSMutableDictionary *map; NSMutableArray *msn; NSEnumerator *enumerator; NSDictionary *obj; NSAutoreleasePool *pool; NGImap4Message *message; if ([self exists] == 0) return [NSArray array]; pool = [[NSAutoreleasePool alloc] init]; if (UidKey == nil) { id objs = nil; objs = @"uid"; UidKey = [[NSArray alloc] initWithObjects:&objs count:1]; } [self resetLastException]; if (![self->context registerAsSelectedFolder:self]) return nil; if ([_messages count] > [self->msn2UidCache count]) { [self->msn2UidCache release]; self->msn2UidCache = nil; } if (!self->msn2UidCache) { NSDictionary *res; res = [[self->context client] fetchFrom:1 to:[self exists] parts:UidKey]; if (![self _checkResult:res cmd:__PRETTY_FUNCTION__]) return nil; self->msn2UidCache = [[res objectForKey:@"fetch"] retain]; } map = [[NSMutableDictionary alloc] initWithCapacity: [self->msn2UidCache count]]; enumerator = [self->msn2UidCache objectEnumerator]; while ((obj = [enumerator nextObject])) [map setObject:[obj objectForKey:@"msn"] forKey:[obj objectForKey:@"uid"]]; msn = [[NSMutableArray alloc] initWithCapacity:[_messages count]]; enumerator = [_messages objectEnumerator]; while ((message = [enumerator nextObject])) { id m; m = [map objectForKey:[NSNumber numberWithUnsignedInt:[message uid]]]; if (m == nil) { [self logWithFormat:@"WARNING[%s]: Couldn`t map a message sequence " @"number to message %@ numbers %@ messages %@ " @"self->msn2UidCache %@", __PRETTY_FUNCTION__, message, map, _messages, self->msn2UidCache]; [msn release]; [map release]; [pool release]; return nil; } [msn addObject:m]; } [map release]; map = nil; result = [self _calculateSequences:msn count:-1]; result = [result retain]; [msn release]; msn = nil; [pool release]; return [result autorelease]; } - (NSArray *)_calculateSequences:(NSMutableArray *)_numbers count:(int)_cnt { // TODO: might split up? document! This looks pretty weird NSAutoreleasePool *pool; NSEnumerator *enumerator; NSMutableDictionary *range; NSMutableArray *ranges; id obj, buffer; int cntMsgs; pool = [[NSAutoreleasePool alloc] init]; if (_cnt == -1) _cnt = [_numbers count]; [_numbers sortUsingSelector:@selector(compare:)]; ranges = [NSMutableArray arrayWithCapacity:[_numbers count]]; enumerator = [_numbers objectEnumerator]; buffer = [NSNumber numberWithInt:0]; range = nil; cntMsgs = 0; while (((obj = [enumerator nextObject])) && (cntMsgs < _cnt)) { cntMsgs++; if (range == nil) { range = [NSMutableDictionary dictionaryWithCapacity:2]; [range setObject:buffer forKey:@"start"]; } if ([obj intValue] != [buffer intValue] + 1) { NSDictionary *ir; [range setObject:buffer forKey:@"end"]; ir = [range copy]; [ranges addObject:ir]; [ir release]; range = nil; } buffer = obj; } if (range != nil) { [range setObject:buffer forKey:@"end"]; [ranges addObject:range]; } else { NSDictionary *d; d = [[NSDictionary alloc] initWithObjectsAndKeys: buffer, @"start", buffer, @"end", nil]; [ranges addObject:d]; [d release]; } range = [ranges objectAtIndex:0]; if ([[range objectForKey:@"end"] intValue] == 0) [ranges removeObjectAtIndex:0]; obj = [ranges copy]; [pool release]; return [obj autorelease]; } - (void)clearParentFolder { self->parentFolder = nil; } /* message factory */ - (id)messageWithUid:(unsigned int)_uid { return [[[NGImap4Message alloc] initWithUid:_uid folder:self context:[self context]] autorelease]; } /* message registry */ - (NGImap4FolderMailRegistry *)mailRegistry { return self->mailRegistry; } /* debugging */ - (BOOL)isDebuggingEnabled { return ImapDebugEnabled; } /* description */ - (NSString *)description { NSMutableString *ms; NSString *tmp; ms = [NSMutableString stringWithCapacity:64]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if ((tmp = [self name])) [ms appendFormat:@" name=%@", tmp]; if ((tmp = [self absoluteName])) [ms appendFormat:@" absolute=%@", tmp]; if ((tmp = [[self flags] componentsJoinedByString:@","])) [ms appendFormat:@" flags=%@", tmp]; [ms appendString:@">"]; return ms; } @end /* NGImap4Folder */ #if 0 @implementation NSData(xxxx) - (NSString *)description { return [NSString stringWithFormat:@"NSData len: %d", [self length]]; } @end #endif SOPE/sope-mime/NGImap4/NGImap4FileManager.h0000644000000000000000000000463515004363604017070 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGImap4FileManager_H__ #define __NGImap4FileManager_H__ #import #include @class NSArray, NSString, NSData, NSDictionary, NSURL; @class NGImap4Context, NGImap4Folder, NGImap4Message; @class EODataSource; @interface NGImap4FileManager : NGFileManager { NGImap4Context *imapContext; NGImap4Folder *rootFolder; NGImap4Folder *currentFolder; } - (id)initWithURL:(NSURL *)_url; - (id)initWithUser:(NSString *)_user password:(NSString *)_pwd host:(NSString *)_host; /* operations */ - (id)imapContext; - (BOOL)createDirectoryAtPath:(NSString *)_path attributes:(NSDictionary *)_attributes; - (BOOL)changeCurrentDirectoryPath:(NSString *)_path; - (NSString *)currentDirectoryPath; - (NGImap4Folder *)currentFolder; - (NGImap4Message *)messageAtPath:(NSString *)_path; - (NSData *)contentsAtPath:(NSString *)_path part:(NSString *)_part; - (NSData *)contentsAtPath:(NSString *)_path; - (NSArray *)directoryContentsAtPath:(NSString *)_path; - (NSArray *)directoriesAtPath:(NSString *)_path; - (NSArray *)filesAtPath:(NSString *)_path; - (NSArray *)directoryContentsAtPath:(NSString *)_path directories:(BOOL)_dirs files:(BOOL)_files; - (EODataSource *)dataSourceAtPath:(NSString *)_path; - (BOOL)fileExistsAtPath:(NSString *)_path; - (BOOL)fileExistsAtPath:(NSString *)_path isDirectory:(BOOL *)_isDir; - (BOOL)isReadableFileAtPath:(NSString *)_path; - (BOOL)isWritableFileAtPath:(NSString *)_path; - (BOOL)isExecutableFileAtPath:(NSString *)_path; - (BOOL)isDeletableFileAtPath:(NSString *)_path; - (BOOL)syncMode; - (void)setSyncMode:(BOOL)_bool; @end #endif /* __NGImap4FileManager_H__ */ SOPE/sope-mime/NGImap4/NGImap4ConnectionManager.h0000644000000000000000000000277615004363604020314 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of OpenGroupware.org. OGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. OGo 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with OGo; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGImap4ConnectionManager_H__ #define __NGImap4ConnectionManager_H__ #import /* NGImap4ConnectionManager This class manages and pools NGImap4Connection objects. */ @class NSString, NSTimer, NSMutableDictionary, NSURL; @class NGImap4Connection, NGImap4Client; @interface NGImap4ConnectionManager : NSObject { NSMutableDictionary *urlToEntry; NSTimer *gcTimer; } + (id)defaultConnectionManager:(NSString *) imapAuthMech; /* client object */ - (NGImap4Connection *)connectionForURL:(NSURL *)_url password:(NSString *)_p; - (NGImap4Client *)imap4ClientForURL:(NSURL *)_url password:(NSString *)_pwd; - (void)flushCachesForURL:(NSURL *)_url; @end #endif /* __NGImap4ConnectionManager_H__ */ SOPE/sope-mime/NGImap4/NGImap4EnvelopeAddress.m0000644000000000000000000000736015004363604020004 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4EnvelopeAddress.h" #include "imCommon.h" @implementation NGImap4EnvelopeAddress - (id)initWithPersonalName:(NSString *)_pname sourceRoute:(NSString *)_route mailbox:(NSString *)_mbox host:(NSString *)_host { /* Note: we expect NSNull for unset values! */ if (_pname == nil || _route == nil || _mbox == nil || _host == nil) { [self release]; return nil; } if ((self = [super init])) { if ([_pname isNotNull]) self->personalName = [_pname copy]; if ([_route isNotNull]) self->sourceRoute = [_route copy]; if ([_mbox isNotNull]) self->mailbox = [_mbox copy]; if ([_host isNotNull]) self->host = [_host copy]; } return self; } - (id)init { return [self initWithPersonalName:nil sourceRoute:nil mailbox:nil host:nil]; } - (id)initWithString:(NSString *)_str { // TODO: properly parse string using NGMailAddressParser return [self initWithPersonalName:nil sourceRoute:nil mailbox:_str host:nil]; } - (id)initWithBodyStructureInfo:(NSDictionary *)_info { if (![_info isNotNull]) { [self release]; return nil; } return [self initWithPersonalName:[_info valueForKey:@"personalName"] sourceRoute:[_info valueForKey:@"sourceRoute"] mailbox:[_info valueForKey:@"mailboxName"] host:[_info valueForKey:@"hostName"]]; } - (void)dealloc { [self->personalName release]; [self->sourceRoute release]; [self->mailbox release]; [self->host release]; [super dealloc]; } /* accessors */ - (NSString *)personalName { return self->personalName; } - (NSString *)sourceRoute { return self->sourceRoute; } - (NSString *)mailbox { return self->mailbox; } - (NSString *)host { return self->host; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { /* we are immutable */ return [self retain]; } /* derived accessors */ - (NSString *)baseEMail { NSString *t; if (![self->mailbox isNotEmpty]) return nil; if (![self->host isNotEmpty]) return self->mailbox; t = [self->mailbox stringByAppendingString:@"@"]; return [t stringByAppendingString:self->host]; } - (NSString *)email { NSString *t; if (![self->personalName isNotEmpty]) return [self baseEMail]; if ((t = [self baseEMail]) == nil) return self->personalName; t = [[self->personalName stringByAppendingString:@" <"] stringByAppendingString:t]; return [t stringByAppendingString:@">"]; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if (self->personalName) [ms appendFormat:@" name='%@'", self->personalName]; if (self->sourceRoute) [ms appendFormat:@" source='%@'", self->sourceRoute]; if (self->mailbox) [ms appendFormat:@" mailbox='%@'", self->mailbox]; if (self->host) [ms appendFormat:@" host='%@'", self->host]; [ms appendString:@">"]; return ms; } @end /* NGImap4EnvelopeAddress */ SOPE/sope-mime/NGImap4/NGImap4Envelope.h0000644000000000000000000000374215004363604016471 0ustar rootroot/* Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGImap4_NGImap4Envelope_H__ #define __NGImap4_NGImap4Envelope_H__ #import /* NGImap4Envelope Wraps the raw envelope as parsed from an IMAP4 fetch response. */ @class NSString, NSArray, NSCalendarDate, NSDictionary; @class NGImap4EnvelopeAddress; @interface NGImap4Envelope : NSObject { @public NSCalendarDate *date; id subject; /* can be either NSData or NSString */ NSString *inReplyTo; NSString *msgId; NGImap4EnvelopeAddress *sender; NSArray *from; NSArray *replyTo; NSArray *to; NSArray *cc; NSArray *bcc; } - (id)initWithMessageID:(NSString *)_msgID subject:(NSString *)_subject from:(NSArray *)_sender replyTo:(NSArray *)_replyTo to:(NSArray *)_to cc:(NSArray *)_cc bcc:(NSArray *)_bcc; - (id)initWithBodyStructureInfo:(NSDictionary *)_info; /* accessors */ - (NSCalendarDate *)date; - (id)subject; - (NSString *)inReplyTo; - (NSString *)messageID; - (NGImap4EnvelopeAddress *)sender; - (NSArray *)from; - (NSArray *)replyTo; - (NSArray *)to; - (NSArray *)cc; - (NSArray *)bcc; /* derived accessors */ - (BOOL)hasTo; - (BOOL)hasCC; - (BOOL)hasBCC; @end #endif /* __NGImap4_NGImap4Envelope_H__ */ SOPE/sope-mime/NGImap4/NGImap4ResponseParser.m0000644000000000000000000022723415004363604017700 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public /bin/bash: 58: command not found You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4ResponseParser.h" #include "NGImap4Support.h" #include "NGImap4Envelope.h" #include "NGImap4EnvelopeAddress.h" #include "imCommon.h" // TODO(hh): code is now prepared for last-exception, but currently it just // raises and may leak the exception object @interface NGImap4ResponseParser(ParsingPrivates) - (BOOL)_parseNumberUntaggedResponse:(NGMutableHashMap *)result_; - (NSDictionary *)_parseBodyContent; - (NSData *) _parseBodyHeaderFields; - (NSData *)_parseData; - (BOOL)_parseQuotaResponseIntoHashMap:(NGMutableHashMap *)result_; - (void)_parseContinuationResponseIntoHashMap:(NGMutableHashMap *)result_; - (BOOL)_parseListOrLSubResponseIntoHashMap:(NGMutableHashMap *)result_; - (BOOL)_parseCapabilityResponseIntoHashMap:(NGMutableHashMap *)result_; - (BOOL)_parseNamespaceResponseIntoHashMap:(NGMutableHashMap *)result_; - (BOOL)_parseSearchResponseIntoHashMap:(NGMutableHashMap *)result_; - (BOOL)_parseSortResponseIntoHashMap:(NGMutableHashMap *)result_; - (BOOL)_parseQuotaRootResponseIntoHashMap:(NGMutableHashMap *)result_; - (BOOL)_parseStatusResponseIntoHashMap:(NGMutableHashMap *)result_; - (BOOL)_parseThreadResponseIntoHashMap:(NGMutableHashMap *)result_; - (BOOL)_parseVanishedResponseIntoHashMap:(NGMutableHashMap *)result_; - (BOOL)_parseByeUntaggedResponseIntoHashMap:(NGMutableHashMap *)result_; - (BOOL)_parseACLResponseIntoHashMap:(NGMutableHashMap *)result_; - (BOOL)_parseAnnotationResponseIntoHashMap:(NGMutableHashMap *)result_; - (BOOL)_parseMyRightsResponseIntoHashMap:(NGMutableHashMap *)result_; - (BOOL)_parseListRightsResponseIntoHashMap:(NGMutableHashMap *)result_; - (NSArray *)_parseThread; @end @implementation NGImap4ResponseParser #define __la(__SELF__, __PEEKPOS) \ ((__SELF__->la == NULL) \ ? [__SELF__->buffer la:__PEEKPOS]\ : __SELF__->la(__SELF__->buffer, @selector(la:), __PEEKPOS)) static __inline__ int _la(NGImap4ResponseParser *self, unsigned _laCnt) { register unsigned char c = __la(self, _laCnt); return (c == '\r') ? _la(self, _laCnt + 1) : c; } static __inline__ BOOL _matchesString(NGImap4ResponseParser *self, const char *s) { register unsigned int i; for (i = 0; s[i] != '\0'; i++) { if (_la(self, i) != s[i]) return NO; } return YES; } static NSDictionary *_parseBody(NGImap4ResponseParser *self, BOOL isBodyStructure); static NSDictionary *_parseSingleBody(NGImap4ResponseParser *self, BOOL isBodyStructure); static NSDictionary *_parseMultipartBody(NGImap4ResponseParser *self, BOOL isBodyStructure); static NSArray *_parseLanguages(); static NSString *_parseBodyString(NGImap4ResponseParser *self, BOOL _convertString); static NSString *_parseBodyDecodeString(NGImap4ResponseParser *self, BOOL _convertString, BOOL _decode); static NSDictionary *_parseBodyParameterList(NGImap4ResponseParser *self); static NSDictionary *_parseContentDisposition(NGImap4ResponseParser *self); static NSArray *_parseAddressStructure(NGImap4ResponseParser *self); static NSArray *_parseParenthesizedAddressList(NGImap4ResponseParser *self); static int _parseTaggedResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_); static void _parseUntaggedResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_); static NSArray *_parseFlagArray(NGImap4ResponseParser *self); static BOOL _parseEnabledUntaggedResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_); static BOOL _parseFlagsUntaggedResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_); static BOOL _parseOkUntaggedResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_); static BOOL _parseBadUntaggedResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_); static BOOL _parseNoUntaggedResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_); static NSNumber *_parseUnsigned(NGImap4ResponseParser *self); static NSString *_parseUntil(NGImap4ResponseParser *self, char _c); static NSString *_parseUntil2(NGImap4ResponseParser *self, char _c1, char _c2); static __inline__ NSException *_consumeIfMatch (NGImap4ResponseParser *self, unsigned char _m); static __inline__ void _consume(NGImap4ResponseParser *self, unsigned _cnt); static void _parseSieveRespone(NGImap4ResponseParser *self, NGMutableHashMap *result_); static BOOL _parseGreetingsSieveResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_); static BOOL _parseDataSieveResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_); static BOOL _parseOkSieveResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_); static BOOL _parseNoSieveResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_); static NSString *_parseContentSieveResponse(NGImap4ResponseParser *self); static NSString *_parseStringSieveResponse(NGImap4ResponseParser *self); static unsigned int LaSize = 4097; static unsigned UseMemoryMappedData = 0; static unsigned Imap4MMDataBoundary = 0; static BOOL debugOn = NO; static BOOL debugDataOn = NO; static NSStringEncoding encoding; static Class StrClass = Nil; static Class NumClass = Nil; static Class DataClass = Nil; static NSStringEncoding defCStringEncoding; static NSNumber *YesNum = nil; static NSNumber *NoNum = nil; static NSNull *null = nil; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; static BOOL didInit = NO; if (didInit) return; didInit = YES; null = [[NSNull null] retain]; encoding = [NGMimePartParser defaultHeaderFieldEncoding]; defCStringEncoding = [NSString defaultCStringEncoding]; debugOn = [ud boolForKey:@"ImapDebugEnabled"]; debugDataOn = [ud boolForKey:@"ImapDebugDataEnabled"]; UseMemoryMappedData = [ud boolForKey:@"NoMemoryMappedDataForImapBlobs"]?0:1; Imap4MMDataBoundary = [ud integerForKey:@"Imap4MMDataBoundary"]; if (Imap4MMDataBoundary < 10) /* Note: this should be larger than a usual header size! */ Imap4MMDataBoundary = 2 * LaSize; StrClass = [NSString class]; NumClass = [NSNumber class]; DataClass = [NSData class]; YesNum = [[NumClass numberWithBool:YES] retain]; NoNum = [[NumClass numberWithBool:NO] retain]; } + (id)parserWithStream:(id)_stream { NGImap4ResponseParser *parser; parser = [NGImap4ResponseParser alloc]; /* seperate line to keep gcc happy */ return [[parser initWithStream:_stream] autorelease]; } - (id)initWithStream:(id)_stream { // designated initializer if (_stream == nil) { [self logWithFormat:@"%s: got no stream ...", __PRETTY_FUNCTION__]; [self release]; return nil; } if ((self = [super init])) { id s; s = [(NGBufferedStream *)[NGBufferedStream alloc] initWithSource:_stream]; self->buffer = [NGByteBuffer alloc]; self->buffer = [self->buffer initWithSource:s la:LaSize]; [s release]; if ([self->buffer respondsToSelector:@selector(methodForSelector:)]) self->la = (int(*)(id, SEL, unsigned)) [self->buffer methodForSelector:@selector(la:)]; self->debug = debugOn; } return self; } - (id)init { [self release]; [NSException raise:@"InvalidUseOfMethodException" format: @"calling -init on the NGImap4ResponseParser is not allowed"]; return nil; } - (void)dealloc { [self->buffer release]; if (self->debug) [self->serverResponseDebug release]; [super dealloc]; } /* exception handling */ - (void)setLastException:(NSException *)_exc { // TODO: support last exception [_exc raise]; } /* ** Parse Sieve Responses */ - (NGHashMap *)parseSieveResponse { NGMutableHashMap *result; if (self->debug) { if (self->serverResponseDebug != nil) [self->serverResponseDebug release]; self->serverResponseDebug = [[NSMutableString alloc] initWithCapacity:512]; } result = [NGMutableHashMap hashMapWithCapacity:64]; if (_la(self,0) == -1) { [self setLastException:[self->buffer lastException]]; return nil; } _parseSieveRespone(self, result); return result; } - (NGHashMap *)parseResponseForTagId:(int)_tag exception:(NSException **)ex_ { /* parse a response from the server, _tag!=-1 parse until tagged response */ // TODO: is NGHashMap really necessary here? BOOL endOfCommand; NGMutableHashMap *result; if (ex_) *ex_ = nil; if (self->debug) { [self->serverResponseDebug release]; self->serverResponseDebug = nil; self->serverResponseDebug = [[NSMutableString alloc] initWithCapacity:512]; } result = [NGMutableHashMap hashMapWithCapacity:64]; for (endOfCommand = NO; !endOfCommand; ) { unsigned char l0; l0 = _la(self, 0); if (l0 == '*') { /* those starting with '* ' */ _parseUntaggedResponse(self, result); if ([result objectForKey:@"bye"]) { endOfCommand = YES; } else { if (_tag == -1) { if ([result objectForKey:@"ok"] != nil) endOfCommand = YES; } } } else if (l0 == '+') { /* starting with a '+'? */ [self _parseContinuationResponseIntoHashMap:result]; endOfCommand = YES; } else if (isdigit(l0)) { /* those starting with a number '24 ', eg '24 OK Completed' */ endOfCommand = (_parseTaggedResponse(self, result) == _tag); } else if (l0 == (unsigned char) -1) { if (ex_) { *ex_ = [self->buffer lastException]; if (!*ex_) *ex_ = [NSException exceptionWithName:@"UnexpectedEndOfStream" reason:(@"the parsed stream ended" @" unexpectedly") userInfo:nil]; } else { [self setLastException: [self->buffer lastException]]; } endOfCommand = YES; result = nil; } else { if (ex_) { *ex_ = [self->buffer lastException]; if (!*ex_) { NSString *reason = [NSString stringWithFormat: @"The char %u received is not expected", l0]; *ex_ = [NSException exceptionWithName:@"UnexpectedCharFromImapSever" reason:reason userInfo:nil]; } } else { [self setLastException: [self->buffer lastException]]; } endOfCommand = YES; result = nil; } } return result; } - (NGHashMap *)parseResponseForTagId:(int)_tag { // DEPRECATED NSException *e = nil; NGHashMap *hm; hm = [self parseResponseForTagId:_tag exception:&e]; if (e) { [self setLastException:e]; return nil; } return hm; } static void _parseSieveRespone(NGImap4ResponseParser *self, NGMutableHashMap *result_) { if (_parseGreetingsSieveResponse(self, result_)) return; if (_parseDataSieveResponse(self, result_)) // la: 1 return; if (_parseOkSieveResponse(self, result_)) // la: 2 return; if (_parseNoSieveResponse(self, result_)) // la: 2 return; } - (NSData *)_parseDataToFile:(unsigned)_size { // TODO: move to own method // TODO: do not use NGFileStream but just fopen/fwrite static NSProcessInfo *Pi = nil; NGFileStream *stream; NSData *result; unsigned char buf[LaSize + 2]; unsigned char tmpBuf[LaSize + 2]; unsigned wasRead = 0; NSString *path; signed char lastChar; // must be signed if (debugDataOn) [self logWithFormat:@" using memory mapped data ..."]; if (Pi == nil) Pi = [[NSProcessInfo processInfo] retain]; path = [Pi temporaryFileName]; stream = [NGFileStream alloc]; /* extra line to keep gcc happy */ stream = [stream initWithPath:path]; if (![stream openInMode:NGFileWriteOnly]) { NSException *e; e = [[NGImap4ParserException alloc] initWithFormat:@"Could not open temporary file %@", path]; [self setLastException:[e autorelease]]; [self logWithFormat: [e reason]]; return nil; } lastChar = -1; while (wasRead < _size) { unsigned readCnt, bufCnt, tmpSize, cnt, tmpBufCnt; bufCnt = 0; if (lastChar != -1) { buf[bufCnt++] = lastChar; lastChar = -1; } [self->buffer la:(_size - wasRead < LaSize) ? (_size - wasRead) : LaSize]; readCnt = [self->buffer readBytes:buf+bufCnt count:_size - wasRead]; wasRead+=readCnt; bufCnt +=readCnt; tmpSize = bufCnt - 1; cnt = 0; tmpBufCnt = 0; while (cnt < tmpSize) { if ((buf[cnt] == '\r') && (buf[cnt+1] == '\n')) { cnt++; } tmpBuf[tmpBufCnt++] = buf[cnt++]; } if (cnt < bufCnt) { lastChar = buf[cnt]; } [stream writeBytes:tmpBuf count:tmpBufCnt]; } if (lastChar != -1) [stream writeBytes:&lastChar count:1]; [stream close]; [stream release]; stream = nil; result = [DataClass dataWithContentsOfMappedFile:path]; [[NSFileManager defaultManager] removeFileAtPath:path handler:nil]; return result; } - (NSData *)_parseDataIntoRAM:(unsigned)_size { /* parses data into a RAM buffer (NSData) */ unsigned char *buf = NULL; unsigned char *tmpBuf; unsigned wasRead = 0; unsigned cnt, tmpBufCnt, tmpSize; NSData *result; buf = calloc(_size + 10, sizeof(char)); while (wasRead < _size) { [self->buffer la:(_size - wasRead < LaSize) ? (_size - wasRead) : LaSize]; wasRead += [self->buffer readBytes:(buf + wasRead) count:(_size-wasRead)]; } /* normalize response \r\n -> \n */ tmpBuf = calloc(_size + 10, sizeof(char)); cnt = 0; tmpBufCnt = 0; tmpSize = _size == 0 ? 0 : _size - 1; while (tmpBufCnt < tmpSize && cnt < _size) { if ((buf[cnt] == '\r') && (buf[cnt + 1] == '\n')) cnt++; /* skip \r */ tmpBuf[tmpBufCnt] = buf[cnt]; tmpBufCnt++; cnt++; } if (cnt < _size) { tmpBuf[tmpBufCnt] = buf[cnt]; tmpBufCnt++; cnt++; } result = [DataClass dataWithBytesNoCopy:tmpBuf length:tmpBufCnt]; if (buf != NULL) free(buf); buf = NULL; return result; } - (NSData *)_parseData { /* parses: { } \n */ // TODO: split up method unsigned size; NSNumber *sizeNum; if (_la(self, 0) != '{') return nil; if (debugDataOn) [self logWithFormat:@"parse data ..."]; /* got header */ _consume(self, 1); // '{' if ((sizeNum = _parseUnsigned(self)) == nil) { NSException *e; e = [[NGImap4ParserException alloc] initWithFormat:@"expect a number between {}"]; [self setLastException:[e autorelease]]; return nil; } if (debugDataOn) [self logWithFormat:@" parse data, size: %@", sizeNum]; _consumeIfMatch(self, '}'); _consumeIfMatch(self, '\n'); if ((size = [sizeNum intValue]) == 0) { [self logWithFormat:@"ERROR(%s): got content size '0'!", __PRETTY_FUNCTION__]; return nil; } if (UseMemoryMappedData && (size > Imap4MMDataBoundary)) return [self _parseDataToFile:size]; return [self _parseDataIntoRAM:size]; } /* Similair to _parseData but used to parse something like this : BODY[HEADER.FIELDS (X-PRIORITY)] {17} X-Priority: 1 ) Headers are returned as data, as is. */ - (NSData *) _parseBodyHeaderFields { NSData *result; unsigned size; NSNumber *sizeNum; result = nil; /* We skip until we're ready to parse {length}. We must be careful here and not assume we will have a valid length - we could very well receive NIL from the server */ _parseUntil(self, ' '); if ((_la(self,0)) == '{') { _consume(self, 1); if ((sizeNum = _parseUnsigned(self)) == nil) { NSException *e; e = [[NGImap4ParserException alloc] initWithFormat:@"expect a number between {}"]; [self setLastException:[e autorelease]]; return nil; } _consumeIfMatch(self, '}'); _consumeIfMatch(self, '\n'); if ((size = [sizeNum intValue]) == 0) { [self logWithFormat:@"ERROR(%s): got content size '0'!", __PRETTY_FUNCTION__]; return nil; } if (UseMemoryMappedData && (size > Imap4MMDataBoundary)) return [self _parseDataToFile:size]; return [self _parseDataIntoRAM:size]; } return result; } static int _parseTaggedResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_) { NSDictionary *d; NSNumber *tag = nil; NSString *res = nil; NSString *desc = nil; NSString *flag = nil; if ((tag = _parseUnsigned(self)) == nil) { NSException *e; if (self->debug) { e = [[NGImap4ParserException alloc] initWithFormat:@"expect a number at begin of tagged response <%@>", self->serverResponseDebug]; } else { e = [[NGImap4ParserException alloc] initWithFormat:@"expect a number at begin of tagged response"]; } e = [e autorelease]; [self setLastException:e]; return -1; } _consumeIfMatch(self, ' '); res = [_parseUntil(self, ' ') lowercaseString]; if (_la(self, 0) == '[') { /* Found flag like [READ-ONLY] */ _consume(self, 1); flag = _parseUntil(self, ']'); } desc = _parseUntil(self, '\n'); /* ATTENTION: if no flag was set, flag == nil, in this case all key-value pairs after flag will be ignored */ d = [[NSDictionary alloc] initWithObjectsAndKeys: tag, @"tagId", res, @"result", desc, @"description", flag, @"flag", nil]; [result_ addObject:d forKey:@"ResponseResult"]; [d release]; return [tag intValue]; } static void _parseUntaggedResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_) { // TODO: is it really required by IMAP4 that responses are uppercase? // TODO: apparently this code *breaks* with lowercase detection on! unsigned char l0, l1 = 0; _consumeIfMatch(self, '*'); _consumeIfMatch(self, ' '); l0 = _la(self, 0); switch (l0) { case 'A': l1 = _la(self, 1); if (l1 == 'C' && [self _parseACLResponseIntoHashMap:result_]) return; if (l1 == 'N' && [self _parseAnnotationResponseIntoHashMap:result_]) return; break; case 'B': l1 = _la(self, 1); if (l1 == 'A' && _parseBadUntaggedResponse(self, result_)) // la: 3 return; if (l1 == 'Y' && [self _parseByeUntaggedResponseIntoHashMap:result_]) // 3 return; break; case 'C': if ([self _parseCapabilityResponseIntoHashMap:result_]) // la: 10 return; break; case 'E': if (_parseEnabledUntaggedResponse(self, result_)) // la: 7 return; break; case 'F': if (_parseFlagsUntaggedResponse(self, result_)) // la: 5 return; break; // ID untagged response case 'I': _parseUntil(self, '\n'); return; case 'L': if (_matchesString(self, "LISTRIGHTS")) { if ([self _parseListRightsResponseIntoHashMap:result_]) return; } if ([self _parseListOrLSubResponseIntoHashMap:result_]) // la: 4 return; break; case 'M': if ([self _parseMyRightsResponseIntoHashMap:result_]) return; break; case 'N': if (_matchesString(self, "NAMESPACE")) { if ([self _parseNamespaceResponseIntoHashMap:result_]) return; } if (_parseNoUntaggedResponse(self, result_)) // la: 2 return; break; case 'O': if (_parseOkUntaggedResponse(self, result_)) // la: 2 /* eg "* OK Completed" */ return; break; case 'R': break; case 'S': switch (_la(self, 1)) { case 'O': // SORT if ([self _parseSortResponseIntoHashMap:result_]) // la: 4 return; break; case 'E': // SEARCH if ([self _parseSearchResponseIntoHashMap:result_]) // la: 5 return; break; case 'T': // STATUS if ([self _parseStatusResponseIntoHashMap:result_]) // la: 6 /* eg "* STATUS INBOX (MESSAGES 0 RECENT 0 UNSEEN 0)" */ return; break; } break; case 'T': if ([self _parseThreadResponseIntoHashMap:result_]) // la: 6 return; break; case 'V': if ([self _parseVanishedResponseIntoHashMap:result_]) // la: 6 return; break; case 'Q': if ([self _parseQuotaResponseIntoHashMap:result_]) // la: 6 return; if ([self _parseQuotaRootResponseIntoHashMap:result_]) // la: 10 return; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if ([self _parseNumberUntaggedResponse:result_]) // la: 5 /* eg "* 928 FETCH ..." */ return; break; } // TODO: what if none matches? [self logWithFormat:@"%s: no matching tag specifier?", __PRETTY_FUNCTION__]; [self logWithFormat:@" line: '%@'", _parseUntil(self, '\n')]; } - (void)_parseContinuationResponseIntoHashMap:(NGMutableHashMap *)result_ { _consumeIfMatch(self, '+'); _consumeIfMatch(self, ' '); [result_ addObject:YesNum forKey:@"ContinuationResponse"]; [result_ addObject:_parseUntil(self, '\n') forKey:@"description"]; } static inline void _purifyQuotedString(NSMutableString *quotedString) { unichar *currentChar, *qString, *maxC, *startC; unsigned int max, questionMarks; BOOL possiblyQuoted, skipSpaces; NSMutableString *newString; newString = [NSMutableString string]; max = [quotedString length]; qString = malloc (sizeof (unichar) * max); [quotedString getCharacters: qString]; currentChar = qString; startC = qString; maxC = qString + max; possiblyQuoted = NO; skipSpaces = NO; questionMarks = 0; while (currentChar < maxC) { if (possiblyQuoted) { if (questionMarks == 2) { if ((*currentChar == 'Q' || *currentChar == 'q' || *currentChar == 'B' || *currentChar == 'b') && ((currentChar + 1) < maxC && (*(currentChar + 1) == '?'))) { currentChar++; questionMarks = 3; } else { possiblyQuoted = NO; } } else if (questionMarks == 4) { if (*currentChar == '=') { skipSpaces = YES; possiblyQuoted = NO; currentChar++; [newString appendString: [NSString stringWithCharacters: startC length: (currentChar - startC)]]; startC = currentChar; } else { possiblyQuoted = NO; } } else { if (*currentChar == '?') { questionMarks++; } else if (*currentChar == ' ' && questionMarks != 3) { possiblyQuoted = NO; } } } else if (*currentChar == '=' && ((currentChar + 1) < maxC && (*(currentChar + 1) == '?'))) { [newString appendString: [NSString stringWithCharacters: startC length: (currentChar - startC)]]; startC = currentChar; possiblyQuoted = YES; skipSpaces = NO; currentChar++; questionMarks = 1; } if (skipSpaces) { /* This part is about skipping the spaces separating two encoded chunks, which occurs when the chunks are on different lines. However we cannot ignore them if the next chunk is not encoded. Basically, we can deduce a case from the other by the fact that it makes no sense per se to have a space separating two encoded chunks. */ startC = currentChar; while (currentChar < maxC && (*currentChar == ' ' || *currentChar == '\t')) currentChar++; if (currentChar != startC) { if (currentChar < maxC && *currentChar != '=') [newString appendString: [NSString stringWithCharacters: startC length: (currentChar - startC)]]; startC = currentChar; } else currentChar++; skipSpaces = NO; } else currentChar++; } if (startC < maxC) [newString appendString: [NSString stringWithCharacters: startC length: (currentChar - startC)]]; [quotedString setString: newString]; free (qString); } - (NSString *)_parseQuotedString { NSMutableString *quotedString; NSString *tmpString; /* parse a quoted string, eg '"' */ if (_la(self, 0) == '"') { _consume(self, 1); quotedString = [NSMutableString string]; tmpString = _parseUntil(self, '"'); [quotedString appendString: tmpString]; } else { quotedString = nil; } _purifyQuotedString(quotedString); return quotedString; } - (NSString *)_parseQuotedStringOrNIL { unsigned char c0; if ((c0 = _la(self, 0)) == '"') return [self _parseQuotedString]; if (c0 == '{') { /* a size indicator, eg '{112}\nkasdjfkja sdj fhj hasdfj hjasdf' */ NSData *data; NSString *s; if ((data = [self _parseData]) == nil) return nil; if (![data isNotEmpty]) return @""; s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; if (s == nil) s = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding]; if (s == nil) { [self logWithFormat: @"ERROR(%s): could not convert data (%d bytes) into string.", __PRETTY_FUNCTION__, [data length]]; return @"[ERROR: NGImap4 could not parse IMAP4 data string]"; } return [s autorelease]; } if (c0 == 'N' && _matchesString(self, "NIL")) { _consume(self, 3); return (id)null; } return nil; } - (id)_parseQuotedStringOrDataOrNIL { if (_la(self, 0) == '"') return [self _parseQuotedString]; if (_la(self, 0) == '{') return [self _parseData]; if (_matchesString(self, "NIL")) { _consume(self, 3); return null; } return nil; } - (void)_consumeOptionalSpace { if (_la(self, 0) == ' ') _consume(self, 1); } - (BOOL)_parseListOrLSubResponseIntoHashMap:(NGMutableHashMap *)result_ { NSArray *flags = nil; NSString *delim = nil; NSString *name = nil; NSDictionary *d; if (!_matchesString(self, "LIST ") && !_matchesString(self, "LSUB ")) return NO; _consume(self, 5); /* consume 'LIST ' or 'LSUB ' */ flags = _parseFlagArray(self); _consumeIfMatch(self, ' '); if (_la(self, 0) == '"') { delim = [self _parseQuotedString]; _consumeIfMatch(self, ' '); } else { _parseUntil(self, ' '); delim = nil; } if (_la(self, 0) == '"') { name = [self _parseQuotedString]; _parseUntil(self, '\n'); } else if (_la(self, 0) == '{') { name = [self _parseQuotedStringOrNIL]; _parseUntil(self, '\n'); } else name = _parseUntil(self, '\n'); d = [[NSDictionary alloc] initWithObjectsAndKeys: name, @"folderName", flags, @"flags", delim, @"delimiter", nil]; [result_ addObject:d forKey:@"list"]; [d release]; return YES; } - (BOOL)_parseCapabilityResponseIntoHashMap:(NGMutableHashMap *)result_ { NSString *caps; NSEnumerator *enumerator; id obj; NSMutableArray *array; NSArray *tmp; if (!_matchesString(self, "CAPABILITY ")) return NO; caps = _parseUntil(self, '\n'); array = [[NSMutableArray alloc] initWithCapacity:16]; enumerator = [[caps componentsSeparatedByString:@" "] objectEnumerator]; while ((obj = [enumerator nextObject]) != nil) [array addObject:[obj lowercaseString]]; tmp = [array copy]; [result_ addObject:tmp forKey:@"capability"]; [array release]; array = nil; [tmp release]; tmp = nil; return YES; } /* support for NAMESPACE extension - RFC2342 */ - (NSDictionary *)_parseNamespacePart { NSDictionary *namespacePart; NSString *prefix, *key, *delimiter; NSMutableDictionary *parameters; NSMutableArray *values; _consume(self, 1); /* ( */ prefix = [self _parseQuotedStringOrNIL]; /* "prefix" */ _consume(self, 1); /* */ delimiter = [self _parseQuotedStringOrNIL]; /* "delimiter" */ parameters = [NSMutableDictionary dictionary]; while (_la(self, 0) == ' ') { _consume(self, 1); /* */ key = [self _parseQuotedString]; _consume(self, 1); /* */ values = [NSMutableArray new]; while (_la(self, 0) != ')') { _consume(self, 1); /* ( or */ [values addObject: [self _parseQuotedString]]; } _consume(self, 1); /* ) */ [parameters setObject: values forKey: key]; [values release]; } _consume(self, 1); /* ) */ namespacePart = [NSDictionary dictionaryWithObjectsAndKeys: prefix, @"prefix", delimiter, @"delimiter", parameters, @"parameters", nil]; return namespacePart; } - (NSArray *)_parseNamespace { NSMutableArray *namespace; namespace = [[NSMutableArray alloc] initWithCapacity: 3]; if (_la(self, 0) == 'N') { namespace = nil; _consume(self, 3); } else { _consume(self, 1); /* ( */ while (_la(self, 0) == '(') { [namespace addObject: [self _parseNamespacePart]]; } _consume(self, 1); /* ) */ } return namespace; } - (BOOL)_parseNamespaceResponseIntoHashMap:(NGMutableHashMap *)result_ { NSArray *namespace; if (!_matchesString(self, "NAMESPACE ")) return NO; _parseUntil(self, ' '); namespace = [self _parseNamespace]; if (namespace) [result_ addObject:namespace forKey:@"personal"]; _consume(self, 1); namespace = [self _parseNamespace]; if (namespace) [result_ addObject:namespace forKey:@"other users"]; _consume(self, 1); namespace = [self _parseNamespace]; if (namespace) [result_ addObject:namespace forKey:@"shared"]; _consume(self, 1); /* \n */ return YES; } - (BOOL)_parseACLResponseIntoHashMap:(NGMutableHashMap *)result_ { /* 21 GETACL INBOX * ACL INBOX test.et.di.cete-lyon lrswipcda helge lrwip "a group" lrs fred "" */ NSString *uid; NSString *userRights; NSString *mailbox; NSMutableArray *uids; NSMutableArray *rights; NSDictionary *result; if (!_matchesString(self, "ACL ")) return NO; _consume(self, 4); if ((mailbox = _parseBodyString(self, YES)) != nil) [result_ setObject:mailbox forKey:@"mailbox"]; _consumeIfMatch(self, ' '); uids = [[NSMutableArray alloc] initWithCapacity:8]; rights = [[NSMutableArray alloc] initWithCapacity:8]; while (_la(self, 0) != '\n') { if (_la(self, 0) == '"') { uid = [self _parseQuotedString]; _consumeIfMatch(self, ' '); } else uid = _parseUntil(self, ' ' ); if (_la(self, 0) == '"') userRights = [self _parseQuotedString]; else userRights = _parseUntil2(self, ' ', '\n'); [self _consumeOptionalSpace]; [uids addObject:uid]; [rights addObject:userRights]; } _consume(self,1); result = [[NSDictionary alloc] initWithObjects:rights forKeys:uids]; [result_ addObject:result forKey:@"acl"]; [uids release]; uids = nil; [rights release]; rights = nil; [result release]; result = nil; return YES; } - (BOOL)_parseMyRightsResponseIntoHashMap:(NGMutableHashMap *)result_ { /* Raw Sample (Cyrus): 18 myrights INBOX * MYRIGHTS INBOX lrswipcda 18 OK Completed */ NSString *rights; id obj; if (!_matchesString(self, "MYRIGHTS ")) return NO; _consume(self, 9); if ((obj = _parseBodyString(self, YES)) != nil) [result_ setObject:obj forKey:@"mailbox"]; _consumeIfMatch(self, ' '); rights = _parseUntil(self, '\n'); [result_ setObject:rights forKey:@"myrights"]; return YES; } - (BOOL)_parseListRightsResponseIntoHashMap:(NGMutableHashMap *)result_ { /* Raw Sample (Cyrus): 22 LISTRIGHTS INBOX helge * LISTRIGHTS INBOX helge "" l r s w i p c d a 0 1 2 3 4 5 6 7 8 9 22 OK Completed */ NSString *rights; id obj; if (!_matchesString(self, "LISTRIGHTS ")) return NO; _consume(self, 11); if ((obj = _parseBodyString(self, YES)) != nil) [result_ setObject:obj forKey:@"mailbox"]; _consumeIfMatch(self, ' '); if ((obj = _parseBodyString(self, YES)) != nil) [result_ setObject:obj forKey:@"uid"]; _consumeIfMatch(self, ' '); if ((obj = _parseUntil(self, ' ')) != nil) { if ([obj isEqual:@"\"\""]) obj = @""; [result_ setObject:obj forKey:@"requiredRights"]; } rights = _parseUntil(self, '\n'); [result_ setObject:[rights componentsSeparatedByString:@" "] forKey:@"listrights"]; return YES; } - (BOOL)_parseSearchResponseIntoHashMap:(NGMutableHashMap *)result_ { NSMutableArray *msn = nil; NSNumber *n; if (!_matchesString(self, "SEARCH")) return NO; _consume(self, 6); msn = [NSMutableArray arrayWithCapacity:128]; while (_la(self, 0) == ' ') { _consume(self, 1); n = _parseUnsigned(self); if (n) [msn addObject:n]; } _parseUntil(self, '\n'); [result_ addObject:msn forKey:@"search"]; return YES; } - (BOOL)_parseSortResponseIntoHashMap:(NGMutableHashMap *)result_ { NSMutableArray *msn = nil; if (!_matchesString(self, "SORT")) return NO; _consume(self, 4); msn = [NSMutableArray arrayWithCapacity:128]; while (_la(self, 0) == ' ') { _consume(self, 1); if (_la(self, 0) == '(') { _consume(self, 1); if (!_matchesString(self, "MODSEQ ")) return NO; _consume(self, 7); [result_ addObject:_parseUnsigned(self) forKey:@"modseq"]; _consume(self, 1); /* final ')' */ } else [msn addObject:_parseUnsigned(self)]; } _parseUntil(self, '\n'); [result_ addObject:msn forKey:@"sort"]; return YES; } - (BOOL)_parseQuotaResponseIntoHashMap:(NGMutableHashMap *)result_ { NSString *qRoot; NSMutableDictionary *parse; NSMutableDictionary *quota; if (!_matchesString(self, "QUOTA ")) return NO; _consume(self, 6); quota = [result_ objectForKey:@"quota"]; if (quota == nil) { quota = [NSMutableDictionary dictionaryWithCapacity:2]; [result_ setObject:quota forKey:@"quota"]; } parse = [NSMutableDictionary dictionaryWithCapacity:3]; if (_la(self, 0) == '"') { NSMutableString *str; _consume(self, 1); str = [NSMutableString stringWithFormat: @"\"%@\"", _parseUntil(self, '"')]; qRoot = str; } else { qRoot = _parseUntil2(self, ' ', '\n'); } if (_la(self, 0) == ' ') { _consume(self, 1); if (_la(self, 0) == '(') { _consume(self,1); if (_la(self, 0) == ')') { /* empty quota response */ _consume(self,1); } else { NSString *key; key = _parseUntil(self, ' '); key = [key lowercaseString]; if ([key isEqualToString:@"storage"]) { NSString *used, *max; used = _parseUntil(self, ' '); max = _parseUntil2(self, ' ', ')'); [parse setObject:used forKey:@"usedSpace"]; [parse setObject:max forKey:@"maxQuota"]; } else if ([key isEqualToString:@"message"]) { NSString *used, *max; used = _parseUntil(self, ' '); max = _parseUntil2(self, ' ', ')'); [parse setObject:used forKey:@"messagesCount"]; [parse setObject:max forKey:@"maxMessages"]; } else { NSString *v; v = _parseUntil(self, ')'); [parse setObject:v forKey:@"resource"]; } } } [quota setObject:parse forKey:qRoot]; } _parseUntil(self, '\n'); return YES; } - (BOOL)_parseQuotaRootResponseIntoHashMap:(NGMutableHashMap *)result_ { NSString *folderName, *folderRoot; NSMutableDictionary *dict; if (!_matchesString(self, "QUOTAROOT ")) return NO; _consume(self, 10); dict = [result_ objectForKey:@"quotaRoot"]; if (!dict) { dict = [NSMutableDictionary dictionaryWithCapacity:2]; [result_ setObject:dict forKey:@"quotaRoot"]; } if (_la(self, 0) == '"') { _consume(self , 1); folderName = _parseUntil(self, '"'); } else { folderName = _parseUntil2(self, '\n', ' '); } if (_la(self, 0) == ' ') { _consume(self, 1); folderRoot = _parseUntil(self, '\n'); } else { _consume(self, 1); folderRoot = nil; } if ([folderName isNotEmpty] && [folderRoot isNotEmpty]) [dict setObject:folderRoot forKey:folderName]; return YES; } - (NSArray *)_parseThread { NSMutableArray *array; NSNumber *msg; array = [NSMutableArray arrayWithCapacity:64]; if (_la(self, 0) == '(') _consume(self, 1); while (1) { if (_la(self, 0) == '(') { NSArray *a; a = [self _parseThread]; if (a != nil) [array addObject:a]; } else if ((msg = _parseUnsigned(self))) { [array addObject:msg]; } else { return nil; } if (_la(self, 0) == ')') break; else if (_la(self, 0) == ' ') _consume(self, 1); } _consumeIfMatch(self, ')'); return array; } - (BOOL)_parseThreadResponseIntoHashMap:(NGMutableHashMap *)result_ { NSMutableArray *msn; if (!_matchesString(self, "THREAD")) return NO; _consume(self, 6); if (_la(self, 0) == ' ') { _consume(self, 1); } msn = [NSMutableArray arrayWithCapacity:64]; while ((_la(self, 0) == '(')) { NSArray *array; if ((array = [self _parseThread]) != nil) [msn addObject:array]; } _parseUntil(self, '\n'); [result_ addObject:msn forKey:@"thread"]; return YES; } - (BOOL)_parseVanishedResponseIntoHashMap:(NGMutableHashMap *)result_ { // VANISHED (EARLIER) 1:53,55:56,58:113,115,120,126,128' NSMutableArray *uids; NSNumber *uid; NSUInteger count, max; if (!_matchesString(self, "VANISHED")) return NO; _consume(self, 8); if (_la(self, 0) == ' ') { _consume(self, 1); } if (_la(self, 0) == '(') { _consume(self, 1); if (!_matchesString(self, "EARLIER")) return NO; _consume(self, 7); /* EARLIER */ _consumeIfMatch(self, ')'); if (_la(self, 0) == ' ') { _consume(self, 1); } } uids = [NSMutableArray new]; while ((_la(self, 0) != '\n')) { uid = _parseUnsigned(self); [uids addObject:uid]; if (_la(self, 0) == ':') { _consume(self, 1); count = [uid unsignedIntValue] + 1; uid = _parseUnsigned(self); max = [uid unsignedIntValue]; while (count < max) { [uids addObject: [NSNumber numberWithUnsignedInt: count]]; count++; } [uids addObject: uid]; } if (_la(self, 0) == ',') { _consume(self, 1); } } _consume(self, 1); [result_ addObject:uids forKey:@"vanished"]; [uids release]; return YES; } - (BOOL)_parseStatusResponseIntoHashMap:(NGMutableHashMap *)result_ { NSString *name = nil; NSMutableDictionary *flags = nil; NSDictionary *d; if (!_matchesString(self, "STATUS ")) return NO; _consume(self, 7); if (_la(self, 0) == '"') { name = [self _parseQuotedString]; // _consume(self, 1); // name = _parseUntil(self, '"'); _consumeIfMatch(self, ' '); } else if (_la(self, 0) == '{') { name = [self _parseQuotedStringOrNIL]; _consumeIfMatch(self, ' '); } else { name = _parseUntil(self, ' '); } _consumeIfMatch(self, '('); flags = [NSMutableDictionary dictionaryWithCapacity:8]; while (_la(self, 0) != ')') { NSString *key = _parseUntil(self, ' '); id value = _parseUntil2(self, ' ', ')'); if (_la(self, 0) == ' ') _consume(self, 1); if ([[key lowercaseString] isEqualToString:@"x-guid"]) [flags setObject:value forKey:[key lowercaseString]]; else [flags setObject:[NumClass numberWithInt:[value intValue]] forKey:[key lowercaseString]]; } _consumeIfMatch(self, ')'); _parseUntil(self, '\n'); d = [[NSDictionary alloc] initWithObjectsAndKeys: name, @"folderName", flags, @"flags", nil]; [result_ addObject:d forKey:@"status"]; [d release]; return YES; } - (BOOL)_parseAnnotationResponseIntoHashMap:(NGMutableHashMap *)result_ { NSString *name = nil; NSString *entry = nil; NSMutableDictionary *attributes = nil; NSMutableDictionary *d, *f; if (!_matchesString(self, "ANNOTATION ")) return NO; _consume(self, 11); if (_la(self, 0) == '"') { name = [self _parseQuotedString]; _consumeIfMatch(self, ' '); } else if (_la(self, 0) == '{') { name = [self _parseQuotedStringOrNIL]; _consumeIfMatch(self, ' '); } else { name = _parseUntil(self, ' '); } if (_la(self, 0) == '"') { entry = [self _parseQuotedString]; _consumeIfMatch(self, ' '); } else if (_la(self, 0) == '{') { entry = [self _parseQuotedStringOrNIL]; _consumeIfMatch(self, ' '); } else { entry = _parseUntil(self, ' '); } _consumeIfMatch(self, '('); attributes = [NSMutableDictionary dictionaryWithCapacity:2]; d = [NSMutableDictionary dictionaryWithCapacity:2]; f = [NSMutableDictionary dictionaryWithCapacity:2]; while (_la(self, 0) != ')') { NSString *key = [self _parseQuotedString]; _consume(self, 1); // ' ' NSString *value = [self _parseQuotedStringOrNIL]; if (_la(self, 0) == ' ') _consume(self, 1); if (value) { [attributes setObject:value forKey:[key lowercaseString]]; [d setObject:[NSMutableDictionary dictionaryWithDictionary:attributes] forKey:entry]; } } _consumeIfMatch(self, ')'); _parseUntil(self, '\n'); [f setObject:d forKey:name]; [result_ addObject:f forKey:@"FolderList"]; return YES; } - (BOOL)_parseByeUntaggedResponseIntoHashMap:(NGMutableHashMap *)result_ { NSString *reason; if (!_matchesString(self, "BYE ")) return NO; _consume(self, 4); reason = _parseUntil(self, '\n'); [result_ addObject:reason forKey:@"bye"]; return YES; } - (id)_decodeQP:(id)_string headerField:(NSString *)_field { if (![_string isNotNull]) return _string; if ([_string isKindOfClass:DataClass]) return [_string decodeQuotedPrintableValueOfMIMEHeaderField:_field]; if ([_string isKindOfClass:StrClass]) { if ([_string length] <= 6 /* minimum size */) return _string; if ([_string rangeOfString:@"=?"].length > 0) { NSData *data; if (debugOn) [self debugWithFormat:@"WARNING: string with quoted printable info!"]; // TODO: this is really expensive ... data = [_string dataUsingEncoding:NSUTF8StringEncoding]; if (data != nil) { NSData *qpData; qpData = [data decodeQuotedPrintableValueOfMIMEHeaderField:_field]; if (qpData != data) return qpData; } } return _string; } return _string; } - (NGImap4EnvelopeAddress *)_parseEnvelopeAddressStructure { /* Note: returns retained object! Order: personal name SMTP@at-domain-list(source route) mailbox name hostname eg: ("Helge Hess" NIL "helge.hess" "opengroupware.org") */ NGImap4EnvelopeAddress *address = nil; NSString *pname, *route, *mailbox, *host; if (_la(self, 0) != '(') { if (_matchesString(self, "NIL")) { _consume(self, 3); return (id)[null retain]; } return nil; } _consume(self, 1); // '(' /* parse personal name, can be with quoted printable encoding! */ pname = [self _parseQuotedStringOrNIL]; if ([pname isNotNull]) // TODO: headerField 'subject'?? explain! pname = [self _decodeQP:pname headerField:@"subject"]; [self _consumeOptionalSpace]; // TODO: I think those forbid QP encoding? route = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace]; mailbox = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace]; host = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace]; if (_la(self, 0) != ')') { [self logWithFormat:@"WARNING: IMAP4 envelope " @"address not properly closed (c0=%c,c1=%c): %@", _la(self, 0), _la(self, 1), self->serverResponseDebug]; } else _consume(self, 1); if ([pname isNotNull] || [route isNotNull] || [mailbox isNotNull] || [host isNotNull]) address = [[NGImap4EnvelopeAddress alloc] initWithPersonalName:pname sourceRoute:route mailbox:mailbox host:host]; return address; } - (NSArray *)_parseEnvelopeAddressStructures { /* Parses an array of envelopes, most common: ((NIL NIL "users-admin" "opengroupware.org")) (just one envelope in the array) */ NSMutableArray *ma; if (_la(self, 0) != '(') { if (_matchesString(self, "NIL")) { _consume(self, 3); return (id)[null retain]; } return nil; } _consume(self, 1); // '(' ma = nil; while (_la(self, 0) != ')') { NGImap4EnvelopeAddress *address; if ((address = [self _parseEnvelopeAddressStructure]) == nil) { [self _consumeOptionalSpace]; continue; // TODO: should we stop parsing? } if (![address isNotNull]) continue; if (ma == nil) ma = [NSMutableArray arrayWithCapacity:4]; [ma addObject:address]; [address release]; /* the parse returns a retained object! */ } if (_la(self, 0) != ')') { [self logWithFormat: @"WARNING: IMAP4 envelope address not properly closed!"]; } else _consume(self, 1); return ma; } - (id)_parseEnvelope { /* http://www.hunnysoft.com/rfc/rfc3501.html envelope = "(" env-date SP env-subject SP env-from SP env-sender SP env-reply-to SP env-to SP env-cc SP env-bcc SP env-in-reply-to SP env-message-id ")" * 1189 FETCH (UID 1189 ENVELOPE ("Tue, 22 Jun 2004 08:42:01 -0500" "" (("Jeff Glaspie" NIL "jeff" "glaspie.org")) (("Jeff Glaspie" NIL "jeff" "glaspie.org")) (("Jeff Glaspie" NIL "jeff" "glaspie.org")) ((NIL NIL "helge.hess" "opengroupware.org")) NIL NIL NIL "<20040622134354.F11133CEB14@mail.opengroupware.org>" ) ) */ static NGMimeRFC822DateHeaderFieldParser *dateParser = nil; NGImap4Envelope *env; NSString *dateStr; id tmp; if (dateParser == nil) dateParser = [[NGMimeRFC822DateHeaderFieldParser alloc] init]; if (_la(self, 0) != '(') return nil; _consume(self, 1); env = [[[NGImap4Envelope alloc] init] autorelease]; /* parse date */ dateStr = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace]; if ([dateStr isNotNull]) env->date = [[dateParser parseValue:dateStr ofHeaderField:nil] retain]; /* parse subject */ if ((tmp = [self _parseQuotedStringOrDataOrNIL]) != nil) { // TODO: that one is an issue, the client does know the requested charset // but doesn't pass it down to the parser? Requiring the client to // deal with NSData's is a bit overkill? env->subject = [tmp isNotNull] ? [[self _decodeQP:tmp headerField:@"subject"] copy] : nil; if (![env->subject isKindOfClass: [NSString class]]) env->subject = [[NSString alloc] initWithData: env->subject encoding: NSUTF8StringEncoding]; [self _consumeOptionalSpace]; } else { [self logWithFormat:@"ERROR(%s): failed on subject(%c): %@", __PRETTY_FUNCTION__, _la(self, 0), self->serverResponseDebug]; return nil; } /* parse addresses */ if ((tmp = [self _parseEnvelopeAddressStructures]) != nil) { env->from = [tmp isNotNull] ? [tmp copy] : nil; [self _consumeOptionalSpace]; } else { [self logWithFormat:@"ERROR(%s): failed on from.", __PRETTY_FUNCTION__]; return nil; } if ((tmp = [self _parseEnvelopeAddressStructures]) != nil) { env->sender = [tmp isNotNull] ? [[tmp lastObject] copy] : nil; [self _consumeOptionalSpace]; } else { [self logWithFormat:@"ERROR(%s): failed on sender.", __PRETTY_FUNCTION__]; return nil; } if ((tmp = [self _parseEnvelopeAddressStructures]) != nil) { env->replyTo = [tmp isNotNull] ? [tmp copy] : nil; [self _consumeOptionalSpace]; } if ((tmp = [self _parseEnvelopeAddressStructures]) != nil) { env->to = [tmp isNotNull] ? [tmp copy] : nil; [self _consumeOptionalSpace]; } if ((tmp = [self _parseEnvelopeAddressStructures]) != nil) { env->cc = [tmp isNotNull] ? [tmp copy] : nil; [self _consumeOptionalSpace]; } if ((tmp = [self _parseEnvelopeAddressStructures]) != nil) { env->bcc = [tmp isNotNull] ? [tmp copy] : nil; [self _consumeOptionalSpace]; } if ((tmp = [self _parseQuotedStringOrNIL])) { env->inReplyTo = [tmp isNotNull] ? [tmp copy] : nil; [self _consumeOptionalSpace]; } if ((tmp = [self _parseQuotedStringOrNIL])) { env->msgId = [tmp isNotNull] ? [tmp copy] : nil; [self _consumeOptionalSpace]; } if (_la(self, 0) != ')') { [self logWithFormat:@"WARNING: IMAP4 envelope not properly closed" @" (c0=%c,c1=%c): %@", _la(self, 0), _la(self, 1), self->serverResponseDebug]; } else _consume(self, 1); return env; } - (BOOL)_parseNumberUntaggedResponse:(NGMutableHashMap *)result_ { NSMutableDictionary *fetch; NSNumber *number; NSString *key = nil; if ((number = _parseUnsigned(self)) == nil) return NO; _consumeIfMatch(self, ' '); if (!_matchesString(self, "FETCH ")) { /* got a number request from select like exists or recent */ key = _parseUntil(self, '\n'); [result_ addObject:number forKey:[key lowercaseString]]; return YES; } /* eg: "FETCH (FLAGS (\Seen) UID 5 RFC822.HEADER {2903}" */ fetch = [[NSMutableDictionary alloc] initWithCapacity:10]; _consume(self, 6); /* "FETCH " */ _consumeIfMatch(self, '('); while (_la(self, 0) != ')') { /* until closing parent */ NSString *key; key = [_parseUntil(self, ' ') lowercaseString]; #if 0 [self logWithFormat:@"PARSE KEY: %@", key]; #endif if ([key hasPrefix:@"body[header.fields"]) { NSData *content; if ((content = [self _parseBodyHeaderFields]) != nil) [fetch setObject:content forKey:key]; else [self logWithFormat:@"ERROR: got no body content for key: '%@'",key]; } else if ([key hasPrefix:@"body["]) { NSDictionary *content; if ((content = [self _parseBodyContent]) != nil) [fetch setObject:content forKey:key]; else [self logWithFormat:@"ERROR: got no body content for key: '%@'",key]; } else if ([key isEqualToString:@"body"]) { [fetch setObject:_parseBody(self, NO) forKey:key]; } else if ([key isEqualToString:@"bodystructure"]) { [fetch setObject:_parseBody(self, YES) forKey:key]; } else if ([key isEqualToString:@"flags"]) { [fetch setObject:_parseFlagArray(self) forKey:key]; } else if ([key isEqualToString:@"uid"]) { [fetch setObject:_parseUnsigned(self) forKey:key]; } else if ([key isEqualToString:@"modseq"]) { _consumeIfMatch(self, '('); [fetch setObject:_parseUnsigned(self) forKey:key]; _consumeIfMatch(self, ')'); } else if ([key isEqualToString:@"rfc822.size"]) { [fetch setObject:_parseUnsigned(self) forKey:key]; } else if ([key hasPrefix:@"rfc822"]) { NSData *data; if (_la(self, 0) == '"') { NSString *str; _consume(self,1); str = _parseUntil(self, '"'); data = [str dataUsingEncoding:defCStringEncoding]; } else data = [self _parseData]; if (data != nil) [fetch setObject:data forKey:key]; } else if ([key isEqualToString:@"envelope"]) { id envelope; if ((envelope = [self _parseEnvelope]) != nil) [fetch setObject:envelope forKey:key]; else [self logWithFormat:@"ERROR: could not parse envelope!"]; } else if ([key isEqualToString:@"internaldate"]) { // TODO: implement! NSException *e; e = [[NGImap4ParserException alloc] initWithFormat:@"INTERNALDATE fetch result not yet supported!"]; [self setLastException:[e autorelease]]; return NO; } else { NSException *e; e = [[NGImap4ParserException alloc] initWithFormat: @"unsupported fetch key: %@", key]; [self setLastException:[e autorelease]]; return NO; } if (_la(self, 0) == ' ') _consume(self, 1); } if (fetch != nil) { [fetch setObject:number forKey:@"msn"]; [result_ addObject:fetch forKey:@"fetch"]; _consume(self, 1); /* consume ')' */ _consumeIfMatch(self, '\n'); } else { /* no correct fetch line */ _parseUntil(self, '\n'); } [fetch release]; fetch = nil; return YES; } static BOOL _parseGreetingsSieveResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_) { BOOL isOK; while (!(isOK = _parseOkSieveResponse(self, result_))) { NSString *key, *value; if (!(key = _parseStringSieveResponse(self))) { break; } if (_la(self, 0) == ' ') { _consume(self, 1); if (!(value = _parseStringSieveResponse(self))) { break; } } else { value = @""; } _parseUntil(self, '\n'); [result_ addObject:value forKey:[key lowercaseString]]; } return isOK; } static BOOL _parseDataSieveResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_) { NSString *str; NSData *data; if ((data = [self _parseData]) == nil) return NO; str = [[StrClass alloc] initWithData:data encoding:NSUTF8StringEncoding]; [result_ setObject:str forKey:@"data"]; [str release]; str = nil; _parseUntil(self, '\n'); return YES; } static BOOL _parseOkSieveResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_) { if (!((_la(self, 0) == 'O') && (_la(self, 1) == 'K'))) return NO; _consume(self, 2); if (_la(self, 0) == ' ') { NSString *reason; if ((reason = _parseContentSieveResponse(self))) [result_ addObject:reason forKey:@"reason"]; } _parseUntil(self, '\n'); [result_ addObject:YesNum forKey:@"ok"]; return YES; } static BOOL _parseNoSieveResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_) { NSString *code, *data; if (!((_la(self, 0)=='N') && (_la(self, 1)=='O') && (_la(self, 2)==' '))) return NO; _consume(self, 3); if (_la(self, 0) == '(') { _consume(self, 1); code = _parseUntil(self, ')'); if (_la(self, 0) == ' ') _consume(self, 1); if (code) [result_ addObject:code forKey:@"code"]; } data = _parseContentSieveResponse(self); [result_ addObject:NoNum forKey:@"ok"]; if (data) [result_ addObject:data forKey:@"reason"]; _parseUntil(self, '\n'); return YES; } static NSString *_parseContentSieveResponse(NGImap4ResponseParser *self) { NSString *str; NSData *data; if ((str = _parseStringSieveResponse(self))) return str; if ((data = [self _parseData]) == nil) return nil; return [[[StrClass alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; } static NSString *_parseStringSieveResponse(NGImap4ResponseParser *self) { if (_la(self, 0) != '"') return nil; _consume(self, 1); return _parseUntil(self, '"'); } static NSString *_parseBodyDecodeString(NGImap4ResponseParser *self, BOOL _convertString, BOOL _decode) { NSString *str; if (_la(self, 0) == '"') { // TODO: can the " be escaped somehow? _consume(self, 1); str = _parseUntil(self, '"'); } else if (_la(self, 0) == '{') { NSData *data; if (debugDataOn) [self logWithFormat:@"parse body decode string"]; data = [self _parseData]; if (_decode) data = [data decodeQuotedPrintableValueOfMIMEHeaderField:nil]; if ([data isKindOfClass: [NSString class]]) return (NSString *) data; else { NSString *s; // Let's try with the supplied encoding. If it doesn't work, // we'll then try UTF-8 or fallback to ISO-8859-1 s = [[StrClass alloc] initWithData:data encoding:encoding]; if (!s && encoding != NSUTF8StringEncoding) s = [[StrClass alloc] initWithData:data encoding:NSUTF8StringEncoding]; if (!s) s = [[StrClass alloc] initWithData:data encoding:NSISOLatin1StringEncoding]; return [s autorelease]; } } else { str = _parseUntil2(self, ' ', ')'); } if (_convertString) { if ([[str lowercaseString] isEqualToString:@"nil"]) str = @""; } if (_decode) { id d; d = [str dataUsingEncoding:defCStringEncoding]; d = [d decodeQuotedPrintableValueOfMIMEHeaderField:nil]; if ([d isKindOfClass:StrClass]) str = d; else { str = [[[StrClass alloc] initWithData:d encoding:encoding] autorelease]; } } return str; } static NSString *_parseBodyString(NGImap4ResponseParser *self, BOOL _convertString) { return _parseBodyDecodeString(self, _convertString, NO /* no decode */); } static NSArray *_parseLanguages(NGImap4ResponseParser *self) { NSMutableArray *languages; NSString *language; languages = [NSMutableArray array]; if (_la(self, 0) == '(') { while (_la(self, 0) != ')') { _consume(self,1); language = _parseBodyString(self, YES); if ([language length]) [languages addObject: language]; } _consume(self,1); } else { language = _parseBodyString(self, YES); if ([language length]) [languages addObject: language]; } return languages; } static NSDictionary *_parseBodyParameterList(NGImap4ResponseParser *self) { NSMutableDictionary *list; if (_la(self, 0) == '(') { _consume(self, 1); list = [NSMutableDictionary dictionaryWithCapacity:4]; while (_la(self,0) != ')') { NSString *key, *value; if (_la(self, 0) == ' ') _consume(self, 1); key = _parseBodyString(self, YES); _consumeIfMatch(self, ' '); value = _parseBodyDecodeString(self, YES, YES); if (value) [list setObject:value forKey:[key lowercaseString]]; } _consumeIfMatch(self, ')'); } else { NSString *str; str = _parseBodyString(self, YES); if ([str isNotEmpty]) NSLog(@"%s: got unexpected string %@", __PRETTY_FUNCTION__, str); list = (id)[NSDictionary dictionary]; } return list; } static NSDictionary *_parseContentDisposition(NGImap4ResponseParser *self) { NSMutableDictionary *disposition; NSString *type; disposition = [NSMutableDictionary dictionary]; if (_la(self, 0) == '(') { _consume(self, 1); type = _parseBodyString(self, YES); [disposition setObject: type forKey: @"type"]; if (_la(self, 0) != ')') { _consume(self, 1); [disposition setObject: _parseBodyParameterList(self) forKey: @"parameterList"]; } _consume(self, 1); } else _parseBodyString(self, YES); return disposition; } static NSArray *_parseAddressStructure(NGImap4ResponseParser *self) { NSString *personalName, *sourceRoute, *mailboxName, *hostName; // Handle broken address list - generally sent by Microsoft Exchange. if (_la(self, 0) == '(') { _consume(self, 1); personalName = _parseBodyString(self, YES); _consumeIfMatch(self, ' '); sourceRoute = _parseBodyString(self, YES); _consumeIfMatch(self, ' '); mailboxName = _parseBodyString(self, YES); _consumeIfMatch(self, ' '); hostName = _parseBodyString(self, YES); _consumeIfMatch(self, ')'); return [NSDictionary dictionaryWithObjectsAndKeys: personalName, @"personalName", sourceRoute, @"sourceRoute", mailboxName, @"mailboxName", hostName, @"hostName", nil]; } _parseUntil(self, ')'); return [NSDictionary dictionary]; } static NSArray *_parseParenthesizedAddressList(NGImap4ResponseParser *self) { NSMutableArray *result; result = [NSMutableArray arrayWithCapacity:8]; if (_la(self, 0) == '(') { _consume(self, 1); while (_la(self, 0) != ')') { [result addObject:_parseAddressStructure(self)]; } _consume(self, 1); } else { NSString *str; str = _parseBodyString(self, YES); if ([str isNotEmpty]) NSLog(@"%s: got unexpected string %@", __PRETTY_FUNCTION__, str); result = (id)[NSArray array]; } return result; } static NSDictionary *_parseSingleBody(NGImap4ResponseParser *self, BOOL isBodyStructure) { NSString *type, *subtype, *bodyId, *description, *result, *encoding, *bodysize; NSDictionary *parameterList; NSMutableDictionary *dict; NSArray *languages; type = [_parseBodyString(self, YES) lowercaseString]; _consumeIfMatch(self, ' '); subtype = [_parseBodyString(self, YES) lowercaseString]; _consumeIfMatch(self, ' '); parameterList = _parseBodyParameterList(self); _consumeIfMatch(self, ' '); bodyId = _parseBodyString(self, YES); _consumeIfMatch(self, ' '); description = _parseBodyString(self, YES); _consumeIfMatch(self, ' '); encoding = _parseBodyString(self, YES); _consumeIfMatch(self, ' '); bodysize = _parseBodyString(self, YES); dict = [NSMutableDictionary dictionaryWithObjectsAndKeys: type, @"type", subtype, @"subtype", parameterList, @"parameterList", bodyId, @"bodyId", description, @"description", encoding, @"encoding", bodysize, @"size", nil]; if ([type isEqualToString:@"text"]) { _consumeIfMatch(self, ' '); [dict setObject:_parseBodyString(self, YES) forKey:@"lines"]; } else if ([type isEqualToString:@"message"] && ([subtype isEqualToString:@"rfc822"] || ([subtype isEqualToString:@"global"] && _la(self, 1) != 'N' && _la(self, 2) != 'I' && _la(self, 3) != 'L'))) { if (_la(self, 0) != ')') { _consumeIfMatch(self, ' '); _consumeIfMatch(self, '('); result = _parseBodyString(self, YES); if (result == nil) result = @""; [dict setObject:result forKey:@"date"]; _consumeIfMatch(self, ' '); result = _parseBodyString(self, YES); if (result == nil) result = @""; [dict setObject:result forKey:@"subject"]; _consumeIfMatch(self, ' '); [dict setObject:_parseParenthesizedAddressList(self) forKey:@"from"]; if (_la(self, 0) == ' ') _consume(self, 1); [dict setObject:_parseParenthesizedAddressList(self) forKey:@"sender"]; if (_la(self, 0) == ' ') _consume(self, 1); [dict setObject:_parseParenthesizedAddressList(self) forKey:@"reply-to"]; if (_la(self, 0) == ' ') _consume(self, 1); [dict setObject:_parseParenthesizedAddressList(self) forKey:@"to"]; if (_la(self, 0) == ' ') _consume(self, 1); [dict setObject:_parseParenthesizedAddressList(self) forKey:@"cc"]; if (_la(self, 0) == ' ') _consume(self, 1); [dict setObject:_parseParenthesizedAddressList(self) forKey:@"bcc"]; if (_la(self, 0) == ' ') _consume(self, 1); result = _parseBodyString(self, YES); if (result == nil) result = @""; [dict setObject:result forKey:@"in-reply-to"]; if (_la(self, 0) == ' ') _consume(self, 1); result = _parseBodyString(self, YES); if (result == nil) result = @""; [dict setObject:result forKey:@"messageId"]; _consumeIfMatch(self, ')'); if (_la(self, 0) == ' ') _consume(self, 1); [dict setObject:_parseBody(self, isBodyStructure) forKey:@"body"]; if (_la(self, 0) == ' ') _consume(self, 1); result = _parseBodyString(self, YES); if (result == nil) result = @""; [dict setObject:result forKey:@"bodyLines"]; } } if (isBodyStructure) { if (_la(self, 0) != ')') { _consume(self,1); [dict setObject: _parseBodyString(self, YES) forKey: @"md5"]; if (_la(self, 0) != ')') { _consume(self,1); [dict setObject: _parseContentDisposition(self) forKey: @"disposition"]; if (_la(self, 0) != ')') { _consume(self,1); languages = _parseLanguages(self); if ([languages count]) [dict setObject: languages forKey: @"languages"]; if (_la(self, 0) != ')') { _consume(self,1); [dict setObject: _parseBodyString(self, YES) forKey: @"location"]; }; }; }; }; } return dict; } static NSDictionary *_parseMultipartBody(NGImap4ResponseParser *self, BOOL isBodyStructure) { NSMutableArray *parts; NSArray *languages; NSString *kind; NSMutableDictionary *dict; parts = [NSMutableArray arrayWithCapacity:4]; while (_la(self, 0) == '(') { [parts addObject:_parseBody(self, isBodyStructure)]; } _consumeIfMatch(self, ' '); kind = _parseBodyString(self, YES); dict = [NSMutableDictionary dictionaryWithObjectsAndKeys: parts, @"parts", @"multipart", @"type", kind , @"subtype", nil]; if (isBodyStructure) { if (_la(self, 0) != ')') { _consume(self,1); [dict setObject: _parseBodyParameterList(self) forKey: @"parameterList"]; if (_la(self, 0) != ')') { _consume(self,1); [dict setObject: _parseContentDisposition(self) forKey: @"disposition"]; if (_la(self, 0) != ')') { _consume(self,1); languages = _parseLanguages(self); if ([languages count]) [dict setObject: languages forKey: @"languages"]; if (_la(self, 0) != ')') { _consume(self,1); [dict setObject: _parseBodyString(self, YES) forKey: @"location"]; }; }; }; }; } return dict; } static NSDictionary *_parseBody(NGImap4ResponseParser *self, BOOL isBodyStructure) { NSDictionary *result; _consumeIfMatch(self, '('); if (_la(self, 0) == '(') { result = _parseMultipartBody(self, isBodyStructure); } else { result = _parseSingleBody(self, isBodyStructure); } if (_la(self,0) != ')') { NSString *str; str = _parseUntil(self, ')'); NSLog(@"%s: got noparsed content %@", __PRETTY_FUNCTION__, str); } else _consume(self, 1); return result; } - (NSDictionary *)_parseBodyContent { NSData *data; unsigned char c0; c0 = _la(self, 0); if (c0 == '"') { NSString *str; _consume(self,1); str = _parseUntil(self, '"'); data = [str dataUsingEncoding:defCStringEncoding]; } else if (c0 == 'N' && _matchesString(self, "NIL")) { _consume(self, 3); return nil; } else data = [self _parseData]; if (data == nil) { [self logWithFormat:@"ERROR(%s): got no data.", __PRETTY_FUNCTION__]; return nil; } return [NSDictionary dictionaryWithObject:data forKey:@"data"]; } static NSArray *_parseFlagArray(NGImap4ResponseParser *self) { NSString *flags; _consumeIfMatch(self, '('); flags = _parseUntil(self, ')'); if (![flags isNotEmpty]) { static NSArray *emptyArray = nil; if (emptyArray == nil) emptyArray = [[NSArray alloc] init]; return emptyArray; } else return [[flags lowercaseString] componentsSeparatedByString:@" "]; } static BOOL _parseEnabledUntaggedResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_) { NSMutableArray *extensions; NSString *extension; if ((_la(self, 0) == 'E') && (_la(self, 1) == 'N') && (_la(self, 2) == 'A') && (_la(self, 3) == 'B') && (_la(self, 4) == 'L') && (_la(self, 5) == 'E') && (_la(self, 6) == 'D')) { extensions = [NSMutableArray new]; [result_ setObject: extensions forKey: @"extensions"]; [extensions release]; _consume(self, 7); while (_la(self, 0) == ' ') { _consume(self, 1); extension = _parseUntil2(self, ' ', '\n'); if ([extension length] > 0) { [extensions addObject: extension]; } } _consumeIfMatch(self, '\n'); return YES; } return NO; } static BOOL _parseFlagsUntaggedResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_) { if ((_la(self, 0) == 'F') && (_la(self, 1) == 'L') && (_la(self, 2) == 'A') && (_la(self, 3) == 'G') && (_la(self, 4) == 'S') && (_la(self, 5) == ' ')) { _consume(self, 6); [result_ addObject:_parseFlagArray(self) forKey:@"flags"]; _consumeIfMatch(self, '\n'); return YES; } return NO; } static BOOL _parseBadUntaggedResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_) { if (!((_la(self, 0)=='B') && (_la(self, 1)=='A') && (_la(self, 2)=='D') && (_la(self, 3) == ' '))) return NO; _consume(self, 4); [result_ addObject:_parseUntil(self, '\n') forKey:@"bad"]; return YES; } static BOOL _parseNoOrOkArguments(NGImap4ResponseParser *self, NGMutableHashMap *result_, NSString *_key) { id obj; obj = nil; if (_la(self, 0) == '[') { NSString *key; _consume(self, 1); key = _parseUntil2(self, ']', ' '); /* possible kinds of untagged OK responses are either * OK [ALERT] System shutdown in 10 minutes or * OK [UNSEEN 14] or * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen \*)] */ if (_la(self, 0) == ']') { _consume(self, 1); if (_la(self, 0) == ' ') { id value; _consume(self, 1); value = _parseUntil(self, '\n'); if ([value isNotEmpty]) { obj = [[NSDictionary alloc] initWithObjects:&value forKeys:&key count:1]; } else obj = [key retain]; } else { obj = [key retain]; _parseUntil(self, '\n'); } } else { /* _la(self, 0) should be ' ' */ id value; value = nil; _consume(self, 1); if (_la(self, 0) == '(') { value = _parseFlagArray(self); _consume(self, 1); /* consume ']' */ } else { value = _parseUntil(self, ']'); } { id tmp; tmp = _parseUntil(self, '\n'); obj = [[NSDictionary alloc] initWithObjectsAndKeys: value, key, tmp, @"comment", nil]; } } } else obj = [_parseUntil(self, '\n') retain]; [result_ addObject:obj forKey:_key]; [obj release]; return YES; } static BOOL _parseNoUntaggedResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_) { if (!((_la(self, 0)=='N') && (_la(self, 1)=='O') && (_la(self, 2)==' '))) return NO; _consume(self, 3); return _parseNoOrOkArguments(self, result_, @"no"); } static BOOL _parseOkUntaggedResponse(NGImap4ResponseParser *self, NGMutableHashMap *result_) { if (!((_la(self, 0)=='O') && (_la(self, 1)=='K') && (_la(self, 2)==' '))) return NO; _consume(self, 3); return _parseNoOrOkArguments(self, result_, @"ok"); } static NSNumber *_parseUnsigned(NGImap4ResponseParser *self) { unsigned n; unsigned char c; BOOL isNumber; isNumber = NO; n = 0; c = _la(self, 0); while ((c >= '0') && (c <= '9')) { _consume(self, 1); isNumber = YES; n = 10 * n + (c - 48); c = _la(self, 0); } if (!isNumber) return nil; return [NumClass numberWithUnsignedInt:n]; } static NSString *_parseUntil(NGImap4ResponseParser *self, char _c) { /* Note: this function consumes the stop char (_c)! normalize \r\n constructions */ // TODO: optimize! char buf[1024], c; NSMutableString *str; unsigned cnt; cnt = 0; str = nil; while ((c = _la(self, 0)) != _c) { if (c == '\\') { _consume(self, 1); c = _la(self, 0); } buf[cnt] = c; _consume(self, 1); cnt++; if (cnt == 1024) { if (str == nil) { str = (NSMutableString *) [NSMutableString stringWithCString:buf length:1024]; } else { NSString *s; s = [(NSString *)[StrClass alloc] initWithCString:buf length:1024]; [str appendString:s]; [s release]; } cnt = 0; } } _consume(self,1); /* consume known stop char */ if (_c == '\n' && cnt > 0) { if (buf[cnt-1] == '\r') cnt--; } if (str == nil) return [StrClass stringWithCString:buf length:cnt]; else { NSString *s, *s2; s = [(NSString *)[StrClass alloc] initWithCString:buf length:cnt]; s2 = [str stringByAppendingString:s]; [s release]; return s2; } } static NSString *_parseUntil2(NGImap4ResponseParser *self, char _c1, char _c2){ /* _parseUntil2(self, char, char) doesn`t consume the stop-chars */ char buf[1024], c; NSMutableString *str; unsigned cnt; cnt = 0; c = _la(self, 0); str = nil; while ((c != _c1) && (c != _c2)) { buf[cnt] = c; _consume(self, 1); cnt++; if (cnt == 1024) { if (str == nil) str = (NSMutableString *) [NSMutableString stringWithCString:buf length:1024]; else { NSString *s; s = [(NSString *)[StrClass alloc] initWithCString:buf length:1024]; [str appendString:s]; [s release]; } cnt = 0; } c = _la(self, 0); } if (str == nil) return [StrClass stringWithCString:buf length:cnt]; { NSString *s, *s2; s = [(NSString *)[StrClass alloc] initWithCString:buf length:cnt]; s2 = [str stringByAppendingString:s]; [s release]; return s2; } } - (NSException *)exceptionForFailedMatch:(unsigned char)_match got:(unsigned char)_avail { NSException *e; e = [NGImap4ParserException alloc]; if (self->debug) { e = [e initWithFormat:@"unexpected char <%c> expected <%c> <%@>", _avail, _match, self->serverResponseDebug]; } else { e = [e initWithFormat:@"unexpected char <%c> expected <%c>", _avail, _match]; } return [e autorelease]; } static __inline__ NSException *_consumeIfMatch(NGImap4ResponseParser *self, unsigned char _match) { NSException *e; if (_la(self,0) == _match) { _consume(self, 1); return nil; } e = [self exceptionForFailedMatch:_match got:_la(self, 0)]; [self setLastException:e]; return e; } static __inline__ void _consume(NGImap4ResponseParser *self, unsigned _cnt) { /* Normalize end of line */ if (_cnt == 0) return; _cnt += (__la(self, _cnt - 1) == '\r') ? 1 : 0; if (self->debug) { unsigned cnt; for (cnt = 0; cnt < _cnt; cnt++) { NSString *s; unichar c = _la(self, cnt); if (c == '\r') continue; s = [[StrClass alloc] initWithCharacters:&c length:1]; [self->serverResponseDebug appendString:s]; [s release]; if (c == '\n') { if ([self->serverResponseDebug lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding] > 2) { fprintf(stderr, "S[%p]: %s", self, [self->serverResponseDebug cStringUsingEncoding:NSISOLatin1StringEncoding]); } [self->serverResponseDebug release]; self->serverResponseDebug = [[NSMutableString alloc] initWithCapacity:512]; } } } [self->buffer consume:_cnt]; } @end /* NGImap4ResponseParser */ SOPE/sope-mime/NGImap4/NGImap4.h0000644000000000000000000000231415004363604014765 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGImap4_NGImap4_H__ #define __NGImap4_NGImap4_H__ #include #include #include #include #include // kit class @interface NGImap4 : NSObject @end #define LINK_NGImap4 \ static void __link_NGImap4(void) { \ [NGImap4 self]; \ __link_NGImap4(); \ } #endif /* __NGImap4_NGImap4_H__ */ SOPE/sope-mime/NGImap4/NGImap4FolderGlobalID.m0000644000000000000000000000512415004363604017466 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4FolderGlobalID.h" #include "imCommon.h" @implementation NGImap4FolderGlobalID + (id)imap4FolderGlobalIDWithServerGlobalID:(EOGlobalID *)_gid andAbsoluteName:(NSString *)_name { NGImap4FolderGlobalID *gid; gid = [[self alloc] initWithServerGlobalID:_gid andAbsoluteName:_name]; return [gid autorelease]; } - (id)initWithServerGlobalID:(EOGlobalID *)_gid andAbsoluteName:(NSString *)_name { if ((self = [super init])) { self->serverGlobalID = [_gid retain]; self->absoluteName = [_name copy]; } return self; } - (id)init { return [self initWithServerGlobalID:nil andAbsoluteName:nil]; } - (void)dealloc { [self->serverGlobalID release]; [self->absoluteName release]; [super dealloc]; } /* accessors */ - (EOGlobalID *)serverGlobalID { return self->serverGlobalID; } - (NSString *)absoluteName { return self->absoluteName; } /* comparison */ - (NSUInteger)hash { return [self->absoluteName hash]; } - (BOOL)isEqualToImap4FolderGlobalID:(NGImap4FolderGlobalID *)_other { if (_other == nil) return NO; if (self == _other) return YES; if (self->absoluteName != _other->absoluteName) { if (![self->absoluteName isEqualToString:_other->absoluteName]) return NO; } if (self->serverGlobalID != _other->serverGlobalID) { if (![self->serverGlobalID isEqual:_other->serverGlobalID]) return NO; } return YES; } - (BOOL)isEqual:(id)_otherObject { if (_otherObject == self) return YES; if (![_otherObject isKindOfClass:[self class]]) return NO; return [self isEqualToImap4FolderGlobalID:_otherObject]; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { return [self retain]; } /* support for some older code expecting only EO global IDs */ - (NSString *)entityName { return @"NGImap4Folder"; } @end /* NGImap4FolderGlobalID */ SOPE/sope-mime/NGImap4/NGImap4Connection.m0000644000000000000000000010607015004363604017016 0ustar rootroot/* Copyright (C) 2004-2007 SKYRIX Software AG This file is part of OpenGroupware.org. OGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. OGo 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with OGo; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4Connection.h" #include "NGImap4MailboxInfo.h" #include "NGImap4Client.h" #include "NGImap4Functions.h" #include "NSString+Imap4.h" #include "imCommon.h" @interface NGImap4Connection (private) - (NSArray *) _flattenedArray: (NSArray *) _array; - (void) _mergeDict: (NSDictionary *) source into: (NSMutableDictionary *) target; - (void) _mergeNGHashMap: (NGMutableHashMap *) source into: (NGMutableHashMap *) target; @end @implementation NGImap4Connection static BOOL debugOn = NO; static BOOL debugCache = NO; static BOOL debugKeys = NO; static BOOL alwaysSelect = NO; static BOOL onlyFetchInbox = NO; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; debugOn = [ud boolForKey:@"NGImap4ConnectionDebugEnabled"]; debugCache = [ud boolForKey:@"NGImap4ConnectionCacheDebugEnabled"]; debugKeys = [ud boolForKey:@"NGImap4ConnectionFolderDebugEnabled"]; alwaysSelect = [ud boolForKey:@"NGImap4ConnectionAlwaysSelect"]; //if (debugOn) NSLog(@"Note: NGImap4ConnectionDebugEnabled is enabled!"); //if (alwaysSelect) // NSLog(@"WARNING: 'NGImap4ConnectionAlwaysSelect' enabled (slow down)"); //NSLog(@"Note(NGImap4Connection): using '%@' as the IMAP4 folder separator.", // imap4Separator); } - (id)initWithClient:(NGImap4Client *)_client password:(NSString *)_pwd { if (_client == nil || _pwd == nil) { [self release]; return nil; } if ((self = [super init])) { self->client = [_client retain]; self->password = [_pwd copy]; self->creationTime = [[NSDate alloc] init]; // TODO: retrieve from IMAP4 instead of using a default self->subfolders = [NSMutableDictionary new]; self->enabledExtensions = [NSMutableDictionary new]; } return self; } - (id)init { return [self initWithClient:nil password:nil]; } - (void)dealloc { [self->urlToRights release]; [self->cachedUIDs release]; [self->uidFolderURL release]; [self->uidSortOrdering release]; [self->creationTime release]; [self->subfolders release]; [self->password release]; [self->client release]; [self->enabledExtensions release]; [super dealloc]; } /* accessors */ - (NGImap4Client *)client { return self->client; } - (BOOL)isValidPassword:(NSString *)_pwd { return [self->password isEqualToString:_pwd]; } - (NSDate *)creationTime { return self->creationTime; } - (void)cacheHierarchyResults:(NSDictionary *)_hierarchy forURL:(NSURL *)_url { [self->subfolders setObject:_hierarchy forKey:[_url absoluteString]]; } - (NSDictionary *)cachedHierarchyResultsForURL:(NSURL *)_url { return [self->subfolders objectForKey:[_url absoluteString]]; } - (void)flushFolderHierarchyCache { [self->subfolders release]; self->subfolders = [NSMutableDictionary new]; [self->urlToRights release]; self->urlToRights = nil; } /* rights */ - (NSString *)cachedMyRightsForURL:(NSURL *)_url { return (_url != nil) ? [self->urlToRights objectForKey:_url] : nil; } - (void)cacheMyRights:(NSString *)_rights forURL:(NSURL *)_url { if (self->urlToRights == nil) self->urlToRights = [[NSMutableDictionary alloc] initWithCapacity:8]; [self->urlToRights setObject:_rights forKey:_url]; } /* UIDs */ - (id)cachedUIDsForURL:(NSURL *)_url qualifier:(id)_q sortOrdering:(id)_so { if (_q != nil) return nil; if (![_so isEqual:self->uidSortOrdering]) return nil; if (![self->uidFolderURL isEqual:_url]) return nil; return self->cachedUIDs; } - (void)cacheUIDs:(NSArray *)_uids forURL:(NSURL *)_url qualifier:(id)_q sortOrdering:(id)_so { if (_q != nil) return; ASSIGNCOPY(self->uidSortOrdering, _so); ASSIGNCOPY(self->uidFolderURL, _url); ASSIGNCOPY(self->cachedUIDs, _uids); } - (void)flushMailCaches { ASSIGN(self->uidSortOrdering, nil); ASSIGN(self->uidFolderURL, nil); ASSIGN(self->cachedUIDs, nil); } /* errors */ - (NSException *)errorCouldNotSelectURL:(NSURL *)_url { NSException *e; NSDictionary *ui; NSString *r; r = [_url isNotNull] ? [@"Could not select IMAP4 folder: " stringByAppendingString: [_url absoluteString]] : (NSString *)@"Could not select IMAP4 folder!"; ui = [[NSDictionary alloc] initWithObjectsAndKeys: [NSNumber numberWithInt:404], @"http-status", _url, @"url", nil]; e = [NSException exceptionWithName:@"NGImap4Exception" reason:r userInfo:ui]; [ui release]; ui = nil; return e; } - (NSException *)errorForResult:(NSDictionary *)_result text:(NSString *)_txt { NSDictionary *ui; NSString *r; int status; if ([[_result valueForKey:@"result"] boolValue]) return nil; /* everything went fine! */ if ((r = [_result valueForKey:@"reason"]) != nil) r = [[_txt stringByAppendingString:@": "] stringByAppendingString:r]; else r = _txt; if ([r isEqualToString:@"Permission denied"]) { /* different for each server?, no error codes in IMAP4 ... */ status = 403 /* Forbidden */; } else status = 500 /* internal server error */; ui = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:status], @"http-status", _result, @"rawResult", nil]; return [NSException exceptionWithName:@"NGImap4Exception" reason:r userInfo:ui]; } /* extensions methods */ - (NSException *)enableExtensions:(NSArray *)_extensions { NSMutableArray *extensionsToEnable; NSString *s; int i, count; extensionsToEnable = [NSMutableArray arrayWithArray: _extensions]; count = [extensionsToEnable count]; /* we don't enable extensions that have already been enabled for this particular connection */ for (i = count-1; i >= 0; i--) { s = [extensionsToEnable objectAtIndex: i]; if ([enabledExtensions objectForKey: s]) [extensionsToEnable removeObjectAtIndex: i]; else [enabledExtensions setObject: [NSNumber numberWithBool: YES] forKey: s]; } if ([extensionsToEnable count]) { NSDictionary *result; result = [self->client enable: _extensions]; if (![[result valueForKey:@"result"] boolValue]) { return (id)[self errorForResult:result text:@"Failed to enable requested extension"]; } } return nil; } /* IMAP4 path/url processing methods */ NSArray *SOGoMailGetDirectChildren(NSArray *_array, NSString *_fn) { /* Scans string '_array' for strings which start with the string in '_fn'. Then split on '/'. */ NSMutableArray *ma; unsigned i, count, prefixlen; count = [_array count]; // TODO: somehow results are different on OSX // we should investigate and test all Foundation libraries and document the // differences #if __APPLE__ prefixlen = [_fn isEqualToString:@""] ? 0 : [_fn length] + 1; #else prefixlen = [_fn isEqualToString:@"/"] ? 1 : [_fn length] + 1; #endif ma = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) { NSString *p; p = [_array objectAtIndex:i]; if ([p length] <= prefixlen) continue; if (prefixlen != 0 && ![p hasPrefix:_fn]) continue; /* cut of common part */ p = [p substringFromIndex:prefixlen]; /* check whether the path is a sub-subfolder path */ if ([p rangeOfString:@"/"].length > 0) continue; [ma addObject:p]; } [ma sortUsingSelector:@selector(compare:)]; return ma; } - (NSArray *)extractSubfoldersForURL:(NSURL *)_url fromResultSet:(NSDictionary *)_result { NSString *folderName; NSDictionary *result; NSArray *names; NSArray *flags; /* Note: the result is normalized, that is, it contains / as the separator */ folderName = [_url path]; #if __APPLE__ /* normalized results already have the / in front on libFoundation?! */ if ([folderName hasPrefix:@"/"]) folderName = [folderName substringFromIndex:1]; #endif result = [_result valueForKey:@"list"]; /* Cyrus already tells us whether we need to check for children */ flags = [result objectForKey:folderName]; if ([flags containsObject:@"hasnochildren"]) { if (debugKeys) { [self logWithFormat:@"%s: folder %@ has no children.", __PRETTY_FUNCTION__,folderName]; } return nil; } if ([flags containsObject:@"noinferiors"]) { if (debugKeys) { [self logWithFormat:@"%s: folder %@ cannot contain children.", __PRETTY_FUNCTION__,folderName]; } return nil; } if (debugKeys) { [self logWithFormat:@"%s: all keys %@: %@", __PRETTY_FUNCTION__, folderName, [[result allKeys] componentsJoinedByString:@", "]]; } names = SOGoMailGetDirectChildren([result allKeys], folderName); if (debugKeys) { [self logWithFormat: @"%s: subfolders of '%@': %@", __PRETTY_FUNCTION__, folderName, [names componentsJoinedByString:@","]]; } return names; } - (NSString *)imap4FolderNameForURL:(NSURL *)_url removeFileName:(BOOL)_delfn { /* a bit hackish, but should be OK */ NSString *folderName; NSArray *names; if (_url == nil) return nil; folderName = [_url path]; if (![folderName isNotEmpty]) return nil; if ([folderName characterAtIndex:0] == '/') folderName = [folderName substringFromIndex:1]; if ([folderName hasSuffix: @"/"]) folderName = [folderName substringToIndex:[folderName length] - 1]; if (_delfn) folderName = [folderName stringByDeletingLastPathComponent]; if ([[[self client] delimiter] isEqualToString:@"/"]) if (debugKeys) { [self logWithFormat: @"imap4FolderNameForURL: %@ became %@", _url, folderName]; } return folderName; names = [folderName componentsSeparatedByString: @"/"]; folderName = [names componentsJoinedByString: [[self client] delimiter]]; if (debugKeys) { [self logWithFormat: @"imap4FolderNameForURL: %@ became %@", _url, folderName]; } return folderName; } - (NSString *)imap4FolderNameForURL:(NSURL *)_url { return [self imap4FolderNameForURL:_url removeFileName:NO]; } - (NSArray *)extractFoldersFromResultSet:(NSDictionary *)_result { /* Note: the result is normalized, that is, it contains / as the separator */ return [[_result valueForKey:@"list"] allKeys]; } /* folder selections */ - (BOOL)selectFolder:(id)_url { NSDictionary *result; NSString *newFolder; newFolder = [_url isKindOfClass:[NSURL class]] ? [self imap4FolderNameForURL:_url] : (NSString *)_url; if (!alwaysSelect) { if ([[[self client] selectedFolderName] isEqualToString:newFolder]) return YES; } result = [[self client] select:newFolder]; if (![[result valueForKey:@"result"] boolValue]) { [self errorWithFormat:@"could not select URL: %@: %@", _url, result]; return NO; } return YES; } - (BOOL)isPermissionDeniedResult:(id)_result { if ([[_result valueForKey:@"result"] intValue] != 0) return NO; return [[_result valueForKey:@"reason"] isEqualToString:@"Permission denied"]; } /* folder operations */ - (NSDictionary *)primaryFetchMailboxHierarchyForURL:(NSURL *)_url onlySubscribedFolders:(BOOL) subscribedFoldersOnly { NSDictionary *result; NSString *prefix; if ((result = [self cachedHierarchyResultsForURL:_url]) != nil) { if (debugCache) [self logWithFormat: @"primaryFetchMailboxHierarchyForURL - cache hit for URL: %@", _url]; return [result isNotNull] ? result : (NSDictionary *)nil; } if (debugCache) [self logWithFormat: @"primaryFetchMailboxHierarchyForURL - cache miss for URL: %@", _url]; prefix = [_url path]; if ([prefix hasPrefix: @"/"]) prefix = [prefix substringFromIndex:1]; if (subscribedFoldersOnly) result = [[self client] lsub:(onlyFetchInbox ? @"INBOX" : prefix) pattern:@"*"]; else result = [[self client] list:(onlyFetchInbox ? @"INBOX" : prefix) pattern:@"*"]; if (![[result valueForKey:@"result"] boolValue]) { [self errorWithFormat:@"Could not list mailbox hierarchy!"]; return nil; } /* cache results */ if ([result isNotNull]) { [self cacheHierarchyResults:result forURL:_url]; if (debugCache) { [self logWithFormat:@"cached results: 0x%p(%d)", result, [result count]]; } } return result; } - (NSDictionary *)primaryFetchMailboxHierarchyForURL:(NSURL *)_url { return [self primaryFetchMailboxHierarchyForURL: _url onlySubscribedFolders: NO]; } - (NSDictionary *) allFoldersMetadataForURL:(NSURL *)_url onlySubscribedFolders:(BOOL)_subscribedFoldersOnly { NSDictionary *result; if ((result = [self primaryFetchMailboxHierarchyForURL:_url onlySubscribedFolders:_subscribedFoldersOnly]) == nil) return nil; if ([result isKindOfClass:[NSException class]]) { [self errorWithFormat:@"failed to retrieve hierarchy: %@", result]; return nil; } return result; } - (NSArray *)allFoldersForURL:(NSURL *)_url onlySubscribedFolders:(BOOL)_subscribedFoldersOnly { NSDictionary *result; result = [self allFoldersMetadataForURL: _url onlySubscribedFolders: _subscribedFoldersOnly]; if (result) return [self extractFoldersFromResultSet:result]; return nil; } - (NSArray *)allFoldersForURL:(NSURL *)_url { return [self allFoldersForURL: _url onlySubscribedFolders: NO]; } - (NSArray *)subfoldersForURL:(NSURL *)_url onlySubscribedFolders:(BOOL)_subscribedFoldersOnly { NSDictionary *result; NSString *baseFolder; if ((result = [self cachedHierarchyResultsForURL:_url]) != nil) { if (debugCache) [self errorWithFormat: @"subfoldersForURL - cache hit for URL: %@", _url]; return [self extractSubfoldersForURL:_url fromResultSet: result]; } if (debugCache) [self errorWithFormat: @"subfoldersForURL - cache miss for URL: %@", _url]; baseFolder = [self imap4FolderNameForURL:_url removeFileName:NO]; if (_subscribedFoldersOnly) result = [[self client] lsub:baseFolder pattern:@"%"]; else result = [[self client] list:baseFolder pattern:@"%"]; if (![[result valueForKey:@"result"] boolValue]) { [self errorWithFormat:@"Could not list mailbox hierarchy!"]; return nil; } if ([result isNotNull]) [self cacheHierarchyResults:result forURL:_url]; return [self extractSubfoldersForURL:_url fromResultSet: result]; } - (NSArray *)subfoldersForURL:(NSURL *)_url { return [self subfoldersForURL:_url onlySubscribedFolders: NO]; } /* message operations */ - (NSArray *)fetchUIDsInURL:(NSURL *)_url qualifier:(id)_qualifier sortOrdering:(id)_so { /* sortOrdering can be an NSString, an EOSortOrdering or an array of EOS. */ NSDictionary *result; NSArray *uids; /* check cache */ uids = [self cachedUIDsForURL:_url qualifier:_qualifier sortOrdering:_so]; if (uids != nil) { if (debugCache) [self logWithFormat:@"reusing uid cache!"]; return [uids isNotNull] ? uids : (NSArray *)nil; } /* select folder and fetch */ if (![self selectFolder:_url]) return nil; result = [[self client] sort:_so qualifier:_qualifier encoding:@"UTF-8"]; if (![[result valueForKey:@"result"] boolValue]) { [self errorWithFormat:@"could not sort contents of URL: %@", _url]; return nil; } uids = [result valueForKey:@"sort"]; if (![uids isNotNull]) { [self errorWithFormat:@"got no UIDs for URL: %@: %@", _url, result]; return nil; } /* cache */ [self cacheUIDs:uids forURL:_url qualifier:_qualifier sortOrdering:_so]; return uids; } /** * Fetch a threaded view of the folder and sort the root messages. * @param _url the URL of the IMAP folder * @param _qualifier a EOQualifier defining a search constraint * @param _so either an NSString, an EOSortOrdering or an array of EOSortOrdering * @return a threaded view of the messages UIDs using interleaved arrays. */ - (NSArray *)fetchThreadedUIDsInURL:(NSURL *)_url qualifier:(id)_qualifier sortOrdering:(id)_so { NSDictionary *result; NSArray *uids, *threadUids; NSMutableArray *sortedThreads, *sortedThread; NSMutableDictionary *threads; NSEnumerator *threadsEnum; id rootThread; unsigned int i, j, count; // Check cache uids = [self cachedUIDsForURL:_url qualifier:_qualifier sortOrdering:_so]; if (uids != nil) { if (debugCache) [self logWithFormat:@"reusing uid cache!"]; return [uids isNotNull] ? uids : (NSArray *)nil; } // Select folder and fetch if (![self selectFolder:_url]) return nil; result = [[self client] threadBySubject: NO charset: @"UTF-8" qualifier: _qualifier]; if ([[result valueForKey:@"result"] boolValue]) { // Sort the threads in two steps : // 1. Build a dictionary with the root threads uids = [result valueForKey: @"thread"]; threads = [NSMutableDictionary dictionaryWithCapacity: [uids count]]; threadsEnum = [uids objectEnumerator]; while ((rootThread = [threadsEnum nextObject])) { threadUids = [self _flattenedArray: rootThread]; threadUids = [threadUids sortedArrayUsingSelector: @selector (compare:)]; [threads setObject: threadUids forKey: [threadUids lastObject]]; } // 2. Flatten and sort the threads based on an IMAP SORT count = [threads count]; sortedThreads = [NSMutableArray arrayWithCapacity: count]; if (count > 0) { uids = [self fetchUIDsInURL: _url qualifier: _qualifier sortOrdering: _so]; for (i = 0; i < [uids count]; i++) { threadUids = [threads objectForKey: [uids objectAtIndex: i]]; if (threadUids) { if ([threadUids count] > 1) { sortedThread = [NSMutableArray arrayWithCapacity: [threadUids count]]; for (j = 0; j < [uids count] && [sortedThread count] < [threadUids count]; j++) { if ([threadUids containsObject: [uids objectAtIndex: j]]) [sortedThread addObject: [uids objectAtIndex: j]]; } [sortedThreads addObject: sortedThread]; } else { // No sorting required [sortedThreads addObject: threadUids]; } } } } uids = sortedThreads; } else { // No THREAD support; rollback to a simple SORT [self warnWithFormat: @"No THREAD support for %@", _url]; uids = [self fetchUIDsInURL: _url qualifier: _qualifier sortOrdering: _so]; } if (![uids isNotNull]) { [self errorWithFormat: @"got no UIDs for URL: %@: %@", _url, result]; return nil; } // Update cache [self cacheUIDs:uids forURL:_url qualifier:_qualifier sortOrdering:_so]; return uids; } - (NSArray *) _flattenedArray: (NSArray *) _array { NSMutableArray *flattenedArray; NSEnumerator *objects; id currentObject; flattenedArray = [NSMutableArray array]; objects = [_array objectEnumerator]; while ((currentObject = [objects nextObject])) if ([currentObject isKindOfClass: [NSArray class]]) [flattenedArray addObjectsFromArray: [self _flattenedArray: (NSArray *)currentObject]]; else [flattenedArray addObject: currentObject]; return flattenedArray; } - (NSArray *) fetchUIDs: (NSArray *) _uids inURL: (NSURL *) _url parts: (NSArray *) _parts { // currently returns a dict?! /* Allowed fetch keys: UID BODY.PEEK[
    ]<> BODY [this is the bodystructure, supported] BODYSTRUCTURE [not supported yet!] ENVELOPE [this is a parsed header, but does not include type] FLAGS INTERNALDATE RFC822 RFC822.HEADER RFC822.SIZE RFC822.TEXT */ NSMutableDictionary *result = nil; NSUInteger i, total, step = 1000; if (_uids == nil || [_uids count] == 0) return nil; /* select folder */ if (![self selectFolder:_url]) return nil; /* fetch parts */ total = [_uids count]; for (i = 0; i < total; i += step) { NSRange range; NSArray *partial_uids; NSDictionary *partial_result; range = NSMakeRange(i, (i + step) > total ? (total - i) : step); partial_uids = [_uids subarrayWithRange: range]; /* We will only fetch "step" uids each time */ partial_result = [[self client] fetchUids:partial_uids parts:_parts]; if (![[partial_result valueForKey:@"result"] boolValue]) { [self errorWithFormat: @"Error fetching %u uids for url: %@", total, _url]; return nil; } if (result == nil) { /* First iteration, first result */ result = [[partial_result mutableCopy] autorelease]; } else { /* Merge partial_result into previous result */ [self _mergeDict: partial_result into: result]; } } return (id)result; } - (void) _mergeDict: (NSDictionary *) source into: (NSMutableDictionary *) target { NSEnumerator *keyEnumerator; id key; keyEnumerator = [source keyEnumerator]; while ((key = [keyEnumerator nextObject])) { id obj, current_obj; current_obj = [target objectForKey: key]; if (current_obj == nil) { /* This should never happen but just in case... */ [self errorWithFormat: @"Error merging fetchUids results: " @"nonexistent key %@ on current target", key]; continue; } obj = [source objectForKey: key]; if ([obj isKindOfClass: [NSArray class]]) { NSArray *data, *current_data, *new_data; data = obj; current_data = current_obj; new_data = [current_data arrayByAddingObjectsFromArray: data]; [target setObject: new_data forKey: key]; } else if ([obj isKindOfClass: [NGMutableHashMap class]]) { [self _mergeNGHashMap: obj into: current_obj]; } else if ([obj isKindOfClass: [NSNumber class]]) { if (obj != current_obj) { [self errorWithFormat: @"Error merging fetchUids results: " @"incorrect value for key %@: %@ != %@", key, obj, current_obj]; } } else { [self errorWithFormat: @"Error merging fetchUids results: " @"ignored %@ (%@) key", key, [key class]]; } } } - (void) _mergeNGHashMap: (NGMutableHashMap *) source into: (NGMutableHashMap *) target { NSEnumerator *keyEnumerator; id key; keyEnumerator = [source keyEnumerator]; while ((key = [keyEnumerator nextObject])) { NSArray *obj, *current_obj; current_obj = [target objectsForKey: key]; if (current_obj == nil) { /* This should never happen but just in case... */ [self errorWithFormat: @"Error merging fetchUids results: " @"nonexistent key %@ on current target", key]; continue; } if ([current_obj count] == 1) { /* Merge only results, that means fields with more than 1 object */ continue; } obj = [source objectsForKey: key]; [target addObjects: obj forKey: key]; } } - (id)fetchURL:(NSURL *)_url parts:(NSArray *)_parts { // currently returns a dict NSDictionary *result; NSString *uid; if (![_url isNotNull]) return nil; /* select folder */ uid = [self imap4FolderNameForURL:_url removeFileName:YES]; if (![self selectFolder:uid]) return nil; /* fetch parts */ uid = [[_url path] lastPathComponent]; result = [client fetchUids:[NSArray arrayWithObject:uid] parts:_parts]; if (![[result valueForKey:@"result"] boolValue]) { [self errorWithFormat:@"could not fetch url: %@", _url]; return nil; } //[self logWithFormat:@"RESULT: %@", result]; return (id)result; } - (NSData *)fetchContentOfBodyPart:(NSString *)_partId atURL:(NSURL *)_url { return [self fetchContentOfBodyPart:_partId atURL:_url withPeek: NO]; } - (NSData *)fetchContentOfBodyPart:(NSString *)_partId atURL:(NSURL *)_url withPeek:(BOOL)_withPeek { NSString *key; NSArray *parts; id result, body; NSUInteger count, max; if (_partId == nil) return nil; key = [NSString stringWithFormat: @"body%@[%@]", _withPeek ? @".peek" : @"", _partId]; parts = [NSArray arrayWithObject:key]; /* fetch */ result = [self fetchURL:_url parts:parts]; /* process results */ result = [(NSDictionary *)result objectForKey:@"fetch"]; if (![result isNotEmpty]) { /* did not find part */ [self errorWithFormat:@"did not find part: %@", _partId]; return nil; } max = [result count]; body = nil; /* no matter whether peek was used or not, the resulting key seems to always be "body[xxx]" */ key = [NSString stringWithFormat: @"body[%@]", _partId]; for (count = 0; !body && count < max; count++) { body = [[result objectAtIndex:count] objectForKey:key]; } if (body == nil) { [self errorWithFormat:@"did not find body in response: %@", result]; return nil; } if ((result = [(NSDictionary *)body objectForKey:@"data"]) == nil) { [self errorWithFormat:@"did not find data in body: %@", body]; return nil; } return result; } /* message flags */ - (NSException *)addOrRemove:(BOOL)_flag flags:(id)_f toURL:(NSURL *)_url { id result; if (![_url isNotNull]) return nil; if (![_f isNotNull]) return nil; if (![_f isKindOfClass:[NSArray class]]) _f = [NSArray arrayWithObjects:&_f count:1]; /* select folder */ result = [self imap4FolderNameForURL:_url removeFileName:YES]; if (![self selectFolder:result]) return [self errorCouldNotSelectURL:_url]; /* store flags */ result = [[self client] storeUid: [[[_url path] lastPathComponent] unsignedIntValue] add:[NSNumber numberWithBool:_flag] flags:_f]; if (![[result valueForKey:@"result"] boolValue]) { return [self errorForResult:result text:@"Failed to change flags of IMAP4 message"]; } /* result contains 'fetch' key with the current flags */ return nil; } - (NSException *)addFlags:(id)_f toURL:(NSURL *)_u { return [self addOrRemove:YES flags:_f toURL:_u]; } - (NSException *)removeFlags:(id)_f toURL:(NSURL *)_u { return [self addOrRemove:NO flags:_f toURL:_u]; } - (NSException *)markURLDeleted:(NSURL *)_url { return [self addOrRemove:YES flags:@"Deleted" toURL:_url]; } - (NSException *)addFlags:(id)_f toAllMessagesInURL:(NSURL *)_url { id result; if (![_url isNotNull]) return nil; if (![_f isNotNull]) return nil; if (![_f isKindOfClass:[NSArray class]]) _f = [NSArray arrayWithObjects:&_f count:1]; /* select folder */ if (![self selectFolder:[self imap4FolderNameForURL:_url]]) return [self errorCouldNotSelectURL:_url]; /* store flags */ result = [[self client] storeFlags:_f forUIDs:@"1:*" addOrRemove:YES]; if (![[result valueForKey:@"result"] boolValue]) { return [self errorForResult:result text:@"Failed to change flags of IMAP4 message"]; } return nil; } /* posting new data */ - (NSException *)postData:(NSData *)_data flags:(id)_f toFolderURL:(NSURL *)_url { id result; if (![_url isNotNull]) return nil; if (![_f isNotNull]) _f = [NSArray array]; if (![_f isKindOfClass:[NSArray class]]) _f = [NSArray arrayWithObjects:&_f count:1]; result = [[self client] append:_data toFolder:[self imap4FolderNameForURL:_url] withFlags:_f]; if (![[result valueForKey:@"result"] boolValue]) return [self errorForResult:result text:@"Failed to store message"]; /* result contains 'fetch' key with the current flags */ // TODO: need to flush any caches? return nil; } /* operations */ - (NSException *)expungeAtURL:(NSURL *)_url { NSString *p; id result; /* select folder */ p = [self imap4FolderNameForURL:_url removeFileName:NO]; if (![self selectFolder:p]) return [self errorCouldNotSelectURL:_url]; /* expunge */ result = [[self client] expunge]; if (![[result valueForKey:@"result"] boolValue]) { [self errorWithFormat:@"could not expunge url: %@", _url]; return nil; } //[self logWithFormat:@"RESULT: %@", result]; return nil; } /* copying and moving */ - (NSException *)copyMailURL:(NSURL *)_srcurl toFolderURL:(NSURL *)_desturl { NSString *srcname, *destname; unsigned uid; id result; /* names */ srcname = [self imap4FolderNameForURL:_srcurl removeFileName:YES]; uid = [[[_srcurl path] lastPathComponent] unsignedIntValue]; destname = [self imap4FolderNameForURL:_desturl]; /* select source folder */ if (![self selectFolder:srcname]) return [self errorCouldNotSelectURL:_srcurl]; /* copy */ result = [[self client] copyUid:uid toFolder:destname]; if (![[result valueForKey:@"result"] boolValue]) return [self errorForResult:result text:@"Copy operation failed"]; // TODO: need to flush some caches? return nil; } /* managing folders */ - (BOOL)doesMailboxExistAtURL:(NSURL *)_url { NSString *folderName; BOOL found; id result; folderName = [self imap4FolderNameForURL:_url]; if ([[[self->client selectedFolderName] stringByDecodingImap4FolderName] isEqualToString:folderName]) found = YES; else { /* check in hierarchy cache */ found = ([self cachedHierarchyResultsForURL: _url] != nil); if (!found) { if (debugCache) [self errorWithFormat: @"doesMailboxExistAtURL - cache miss for URL: %@", _url]; /* check using IMAP4 select */ // TODO: we should probably just fetch the whole hierarchy? result = [self->client status: folderName flags: [NSArray arrayWithObject: @"UIDVALIDITY"]]; found = ([[result valueForKey: @"result"] boolValue]); } else if (debugCache) [self errorWithFormat: @"doesMailboxExistAtURL - cache hit for URL: %@", _url]; } return found; } - (id)infoForMailboxAtURL:(NSURL *)_url { NGImap4MailboxInfo *info; NSString *folderName; id result; folderName = [self imap4FolderNameForURL:_url]; result = [[self client] select:folderName]; if (![[result valueForKey:@"result"] boolValue]) return [self errorCouldNotSelectURL:_url]; info = [[NGImap4MailboxInfo alloc] initWithURL:_url folderName:folderName selectDictionary:result]; return [info autorelease]; } - (NSException *)createMailbox:(NSString *)_mailbox atURL:(NSURL *)_url { NSString *newPath; id result; /* construct path */ newPath = [self imap4FolderNameForURL:_url]; if ([newPath length]) newPath = [newPath stringByAppendingString: [[self client] delimiter]]; newPath = [newPath stringByAppendingString:_mailbox]; /* create */ result = [[self client] create:newPath]; if (![[result valueForKey:@"result"] boolValue]) return [self errorForResult:result text:@"Failed to create folder"]; [self flushFolderHierarchyCache]; // [self debugWithFormat:@"created mailbox: %@: %@", newPath, result]; return nil; } - (NSException *)deleteMailboxAtURL:(NSURL *)_url { NSString *path; id result; /* delete */ path = [self imap4FolderNameForURL:_url]; result = [[self client] delete:path]; if (![[result valueForKey:@"result"] boolValue]) return [self errorForResult:result text:@"Failed to delete folder"]; [self flushFolderHierarchyCache]; #if 0 [self debugWithFormat:@"delete mailbox %@: %@", _url, result]; #endif return nil; } - (NSException *) deleteMailbox: (NSString *)_path { id result; /* delete */ result = [[self client] delete: _path]; if (![[result valueForKey:@"result"] boolValue]) return [self errorForResult:result text:@"Failed to delete folder"]; [self flushFolderHierarchyCache]; #if 0 [self debugWithFormat:@"delete mailbox %@: %@", _path, result]; #endif return nil; } - (NSException *)moveMailboxAtURL:(NSURL *)_srcurl toURL:(NSURL *)_desturl { NSString *srcname, *destname; id result; /* rename */ srcname = [self imap4FolderNameForURL:_srcurl]; destname = [self imap4FolderNameForURL:_desturl]; result = [[self client] rename:srcname to:destname]; if (![[result valueForKey:@"result"] boolValue]) return [self errorForResult:result text:@"Failed to move folder"]; [self flushFolderHierarchyCache]; #if 0 [self debugWithFormat:@"renamed mailbox %@: %@", _srcurl, result]; #endif return nil; } - (NSException *) moveMailbox: (NSString *)_srcname to:(NSString *)_destname { id result; /* rename */ result = [[self client] rename: _srcname to: _destname]; if (![[result valueForKey: @"result"] boolValue]) return [self errorForResult: result text:@"Failed to move folder"]; [self flushFolderHierarchyCache]; #if 0 [self debugWithFormat:@"renamed mailbox %@: %@", _srcname, result]; #endif return nil; } /* ACLs */ - (NSDictionary *)aclForMailboxAtURL:(NSURL *)_url { /* Returns a mapping of uid => permission strings, eg: guizmo.g = lrs; root = lrswipcda; */ NSString *folderName; id result; folderName = [self imap4FolderNameForURL:_url]; result = [[self client] getACL:folderName]; if (![[result valueForKey:@"result"] boolValue]) { return (id)[self errorForResult:result text:@"Failed to get ACL of folder"]; } return [result valueForKey:@"acl"]; } - (NSString *)myRightsForMailboxAtURL:(NSURL *)_url { NSString *folderName; id result; /* check cache */ if ((result = [self cachedMyRightsForURL:_url]) != nil) return result; /* run IMAP4 op */ folderName = [self imap4FolderNameForURL:_url]; result = [[self client] myRights:folderName]; if (![[result valueForKey:@"result"] boolValue]) { return (id)[self errorForResult:result text:@"Failed to get myrights on folder"]; } /* cache results */ if ((result = [result valueForKey:@"myrights"]) != nil) [self cacheMyRights:result forURL:_url]; return result; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; [ms appendFormat:@" client=0x%p", self->client]; if ([self->password isNotEmpty]) [ms appendString:@" pwd"]; [ms appendFormat:@" created=%@", self->creationTime]; if (self->subfolders != nil) [ms appendFormat:@" #cached-folders=%d", (int)[self->subfolders count]]; if (self->cachedUIDs != nil) [ms appendFormat:@" #cached-uids=%d", (int)[self->cachedUIDs count]]; [ms appendString:@">"]; return ms; } @end /* NGImap4Connection */ SOPE/sope-mime/NGImap4/TODO0000644000000000000000000000376515004363604014120 0ustar rootroot# TODO for NGImap4 TODO: update todo file! ;-) - OGo bug #660 - SkyImapMailActions does mail discovery based on an IMAP4 URL /OpenGroupware/x/SkyImapMailActions/viewImapMail?listName=MailList&\ url=imap%3A%2F%2Flocalhost%2FINBOX%2FGNUstep%2F999 - this uses NGImap4Message +messageWithURL:context: - TODO: should be invoke messageWithURL:context: on context? - done: NGImap4Message constructors deprecated, added new ctx methods - check qualifier processing, eg "flags='unseen'" etc NGImap4Message ============== - find out who actually instantiates a message - find out whether a folder is always attached to a message OpenGroupware.org> find . -name "*.m" -exec grep -l " initWithUid" \{\} \; ./SOPE/skyrix-core/NGMime/NGImap4/NGImap4Folder.m ./SOPE/skyrix-core/NGMime/NGImap4/NGImap4Message.m - where is NGImap4Message referenced?: - skyrix-core/NGMime/NGImap4 - WebUI/Common/BaseUI/SkyFavorites (why?) - calculates a "favorite" drag type - might use the entityName of the gid? - does not use message GID for activation - WebUI/Mailer/OGoWebMail - SandStorm/skymaild/DirectAction+Mail.m NGImap4Folder ============= - replace notification center - make flags array a specialized object, use bits for flag storage? - persistent custom flags are possible in Cyrus? (eg junk?) - document flags array - maybe add a "folderstate" object containing 'exists', 'recent', 'unseen' - remove all that message-cache thing?! NGImap4Context ============== - document content of capability header in @interface - find out about -folderForRefresh - move sentFolderName, trashFolderName to a separate Imap4ContextConfig object - add a more generic "capability" object - move canSort, canQuota into that - make "int" bitfield flags NGImap4Client ============= - move "normalize" stuff to a separate "normalizer" object - use NSURL for keeping connection info? - use bitfield flags for debug, useSSL or isLogin - can we remove the dependency of the back-link to NGImap4Context? - should have an async API! SOPE/sope-mime/NGImap4/NSString+Imap4.h0000644000000000000000000000224615004363604016247 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG Copyright (C) 2013 Inverse inc. This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGImap4_NSString_Imap4_H__ #define __NGImap4_NSString_Imap4_H__ #import @interface NSString(Imap4) /* WARNING: this should encode/decode to NSData !!! */ - (NSString *)stringByEncodingImap4FolderName; - (NSString *)stringByDecodingImap4FolderName; - (BOOL) is7bitSafe; // From Pantomime @end #endif /* __NGImap4_NSString_Imap4_H__ */ SOPE/sope-mime/NGImap4/NGImap4DataSource.h0000644000000000000000000000336415004363604016746 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGImap4_NGImap4DataSource_H__ #define __NGImap4_NGImap4DataSource_H__ #import #import /* NGImap4DataSource Returned by the NGImap4FileManager when -dataSourceAtPath: is called. TODO: does this also handle subfolders? If not, we should rename the datasource class (eg NGImap4MessageDataSource). */ @class NSArray; @class NGImap4Folder; @class EOFetchSpecification; @interface NGImap4DataSource : EODataSource { @protected EOFetchSpecification *fspec; NSArray *messages; NGImap4Folder *folder; int oldExists; // remember the 'exists' flag of the folder int oldUnseen; // remember the 'unseen' flag of the folder NSArray *oldUnseenMessages; } - (id)initWithFolder:(NGImap4Folder *)_folder; - (void)setFolder:(NGImap4Folder *)_folder; - (NGImap4Folder *)folder; - (int)oldExists; - (int)oldUnseen; @end /* __NGImap4_NGImap4DataSource_H__ */ #endif SOPE/sope-mime/NGImap4/NGImap4FolderMailRegistry.m0000644000000000000000000001444715004363604020474 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGImap4FolderMailRegistry.h" #include "NGImap4Message.h" #include "imCommon.h" @interface NGImap4Message(UsedPrivates) - (NSString *)_addFlagNotificationName; - (NSString *)_removeFlagNotificationName; - (void)_addFlag:(NSNotification *)_n; - (void)_removeFlag:(NSNotification *)_n; @end typedef enum { NGImap4_FlagAdd = 0, NGImap4_FlagDel = 1 } NGImap4FlagOp; @implementation NGImap4FolderMailRegistry static BOOL useObjectObserver = NO; static BOOL logFlagPostings = NO; static BOOL useFlatArray = YES; static int initialCapacity = 100; static NSNotificationCenter *nc = nil; static Class DictClass = Nil; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; BOOL useOwnNC = YES; BOOL disableNC = NO; useFlatArray = [ud boolForKey:@"ImapUseOldMailNotificationSystem"]?NO:YES; if (useFlatArray) { disableNC = YES; //NSLog(@"Note: using flat-array message notifications!"); } if (disableNC) { nc = nil; //if (!useFlatArray) // NSLog(@"WARNING: NGImap4Message notifications disabled!"); } else { nc = useOwnNC ? [[NSNotificationCenter alloc] init] : [[NSNotificationCenter defaultCenter] retain]; } DictClass = [NSDictionary class]; } - (void)dealloc { if (self->observers) free(self->observers); [super dealloc]; } /* flat array */ - (void)_ensureArraySize { if (self->capacity > self->len) return; if (self->observers == NULL) { self->capacity = initialCapacity; self->observers = calloc(self->capacity, sizeof(id)); } else { self->capacity *= 2; self->observers = realloc(self->observers, (self->capacity * sizeof(id))); } } /* operations */ - (void)registerObject:(NGImap4Message *)_mail { if (_mail == nil) return; if (useFlatArray) { if (self->capacity <= self->len) [self _ensureArraySize]; self->observers[self->len] = _mail; self->len++; } else { if (useObjectObserver) { [nc addObserver:_mail selector:@selector(_addFlag:) name:@"NGImap4MessageAddFlag" object:[_mail globalID]]; [nc addObserver:_mail selector:@selector(_removeFlag:) name:@"NGImap4MessageRemoveFlag" object:[_mail globalID]]; } else { [nc addObserver:_mail selector:@selector(_addFlag:) name:[_mail _addFlagNotificationName] object:nil]; [nc addObserver:_mail selector:@selector(_removeFlag:) name:[_mail _removeFlagNotificationName] object:nil]; } } } - (void)forgetObject:(NGImap4Message *)_mail { register signed int i; if (_mail == nil) return; if (!useFlatArray) { [nc removeObserver:_mail]; return; } /* scan for index to be deleted ... */ for (i = self->len - 1; i >= 0; i--) { if (self->observers[i] == _mail) { /* found */ break; } } if (i >= 0) { /* found */ self->observers[i] = self->observers[self->len - 1]; self->len--; } else [self logWithFormat:@"did not find object to be removed!"]; } /* notifications */ static NSString *keys[2] = { @"flag", nil }; - (void)postFlagChange:(NGImap4FlagOp)_op flag:(NSString *)_flag inMessage:(NGImap4Message *)_msg { NSDictionary *ui; if (_flag == nil) return; if (_msg == nil) return; if (logFlagPostings) { [self logWithFormat:@"%s flag '%@' msg %d (0x%p)", (_op == NGImap4_FlagAdd ? "add" : "del"), _flag, [_msg uid], _msg]; } // TODO: pretty lame ui = [[DictClass alloc] initWithObjects:&_flag forKeys:keys count:1]; if (useFlatArray) { register signed int i; register unsigned suid; NSNotification *notification = nil; suid = [_msg uid]; /* fullscan (duplicates are possible, both uid and id!) */ for (i = self->len - 1; i >= 0; i--) { if (self->observers[i] != _msg) { if ([self->observers[i] uid] != suid) // TODO: we might want to cache the selector // TODO: we even might want to cache the uid in the array? continue; } /* OK, either exact match or uid match */ if (notification == nil) { NSString *n; n = (_op == NGImap4_FlagAdd ? @"NGImap4MessageAddFlag" : @"NGImap4MessageRemoveFlag"); #if !LIB_FOUNDATION_LIBRARY notification = [NSNotification notificationWithName:n object:_msg userInfo:ui]; #else notification = [[NSNotification alloc] initWithName:n object:_msg userInfo:ui]; #endif } if (logFlagPostings) [self logWithFormat:@" post to 0x%p ...", self->observers[i]]; if (_op == NGImap4_FlagAdd) [self->observers[i] _addFlag:notification]; else [self->observers[i] _removeFlag:notification]; if (logFlagPostings) [self logWithFormat:@" done post to 0x%p.", self->observers[i]]; } #if LIB_FOUNDATION_LIBRARY if (notification) [notification release]; #endif } else if (useObjectObserver) { [nc postNotificationName: (_op == NGImap4_FlagAdd ? @"NGImap4MessageAddFlag" : @"NGImap4MessageRemoveFlag") object:[_msg globalID] userInfo:ui]; } else { [nc postNotificationName: (_op == NGImap4_FlagAdd ? [_msg _addFlagNotificationName] : [_msg _removeFlagNotificationName]) object:nil userInfo:ui]; } [ui release]; } - (void)postFlagAdded:(NSString *)_flag inMessage:(NGImap4Message *)_msg { [self postFlagChange:NGImap4_FlagAdd flag:_flag inMessage:_msg]; } - (void)postFlagRemoved:(NSString *)_flag inMessage:(NGImap4Message *)_msg { [self postFlagChange:NGImap4_FlagDel flag:_flag inMessage:_msg]; } @end /* NGImap4FolderMailRegistry */ SOPE/sope-mime/NGImap4/NGImap4Client.m0000644000000000000000000017260415004363604016143 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007-2011 Inverse inc. This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "NGImap4Client.h" #include "NGImap4Context.h" #include "NGImap4Support.h" #include "NGImap4Envelope.h" #include "NGImap4EnvelopeAddress.h" #include "NGImap4Functions.h" #include "NGImap4ResponseParser.h" #include "NGImap4ResponseNormalizer.h" #include "NGImap4ServerGlobalID.h" #include "NSString+Imap4.h" #include "imCommon.h" #include #include "imTimeMacros.h" #include #include #include @interface EOQualifier(IMAPAdditions) - (NSString *)imap4SearchString; @end @interface EOSortOrdering(IMAPAdditions) - (NSString *)imap4SortString; @end @interface NSArray(IMAPAdditions) - (NSString *)imap4SortStringForSortOrderings; @end @interface NGImap4Client(ConnectionRegistration) - (void)removeFromConnectionRegister; - (void)registerConnection; - (NGCTextStream *)textStream; @end /* NGImap4Client(ConnectionRegistration); */ // #if GNUSTEP_BASE_LIBRARY // /* FIXME: TODO: move someplace better (hh: NGExtensions...) */ // @implementation NSException(setUserInfo) // - (id)setUserInfo:(NSDictionary *)_userInfo { // ASSIGN(self->_e_info, _userInfo); // return self; // } // @end /* NSException(setUserInfo) */ // #endif @interface NGImap4Client(Private) - (NSString *)_folder2ImapFolder:(NSString *)_folder; - (void)sendCommand:(NSString *)_command; - (void)sendCommand:(NSString *)_command withTag:(BOOL)_tag; - (void)sendCommand:(NSString *)_command withTag:(BOOL)_tag logText:(NSString *)_txt; - (void)sendResponseNotification:(NGHashMap *)map; - (NSDictionary *)login; - (NSDictionary *)authenticate; - (NSDictionary *) _sopeSORT: (id)_sortSpec qualifier:(EOQualifier *)_qual encoding:(NSString *)_encoding; @end /* An implementation of an Imap4 client A folder name always looks like an absolute filename (/inbox/doof) */ @implementation NGImap4Client // TODO: replace? static inline NSArray *_flags2ImapFlags(NGImap4Client *, NSArray *); static NSNumber *YesNumber = nil; static NSNumber *NoNumber = nil; static id *ImapClients = NULL; static unsigned int CountClient = 0; static unsigned int MaxImapClients = 0; static int ProfileImapEnabled = -1; static int LogImapEnabled = -1; static int PreventExceptions = -1; static BOOL fetchDebug = NO; static BOOL ImapDebugEnabled = YES; static NSArray *Imap4SystemFlags = nil; static NSMutableDictionary *capabilities; static NSMutableDictionary *namespaces; - (BOOL)useSSL { return self->useSSL; } - (BOOL)useTLS { return self->useTLS; } + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; static BOOL didInit = NO; if (didInit) return; didInit = YES; PreventExceptions = [ud boolForKey:@"ImapPreventConnectionExceptions"]?1:0; LogImapEnabled = [ud boolForKey:@"ImapLogEnabled"]?1:0; ProfileImapEnabled = [ud boolForKey:@"ProfileImapEnabled"]?1:0; ImapDebugEnabled = [ud boolForKey:@"ImapDebugEnabled"]; YesNumber = [[NSNumber numberWithBool:YES] retain]; NoNumber = [[NSNumber numberWithBool:NO] retain]; if (MaxImapClients < 1) { MaxImapClients = [ud integerForKey:@"NGImapMaxConnectionCount"]; if (MaxImapClients < 1) MaxImapClients = 50; } if (ImapClients == NULL) ImapClients = calloc(MaxImapClients + 2, sizeof(id)); Imap4SystemFlags = [[NSArray alloc] initWithObjects: @"seen", @"answered", @"deleted", @"draft", nil]; capabilities = [[NSMutableDictionary alloc] init]; namespaces = [[NSMutableDictionary alloc] init]; } /* constructors */ + (id)clientWithURL:(NSURL *)_url { return [[(NGImap4Client *)[self alloc] initWithURL:_url] autorelease]; } + (id)clientWithAddress:(id)_address { return [[(NGImap4Client *)[self alloc] initWithAddress:_address] autorelease]; } + (id)clientWithHost:(id)_host { return [[[self alloc] initWithHost:_host] autorelease]; } - (id)initWithHost:(id)_host { NGInternetSocketAddress *a; a = [NGInternetSocketAddress addressWithPort:143 onHost:_host]; return [self initWithAddress:a]; } - (id)initWithURL:(NSURL *)_url { NGInternetSocketAddress *a; int port; id tmp; NSDictionary *queryComponents = [_url queryComponents]; NSString *value; if ((self->useSSL = [[_url scheme] isEqualToString:@"imaps"])) { if (NSClassFromString(@"NGActiveSSLSocket") == nil) { [self logWithFormat: @"no SSL support available, cannot connect: %@", _url]; [self release]; return nil; } } if ((tmp = [_url port])) { port = [tmp intValue]; if (port <= 0) port = self->useSSL ? 993 : 143; } else port = self->useSSL ? 993 : 143; value = [queryComponents valueForKey: @"tls"]; if (value && [value isEqualToString: @"YES"]) { self->useTLS = YES; if ([tmp intValue] <= 0) port = 143; } tlsVerifyMode = TLSVerifyDefault; value = [queryComponents valueForKey: @"tlsVerifyMode"]; if (value) { if ([value isEqualToString: @"allowInsecureLocalhost"]) { tlsVerifyMode = TLSVerifyAllowInsecureLocalhost; } else if ([value isEqualToString: @"none"]) { tlsVerifyMode = TLSVerifyNone; } } self->authname = nil; self->login = [[_url user] copy]; self->password = [[_url password] copy]; a = [NGInternetSocketAddress addressWithPort:port onHost:[_url host]]; return [self initWithAddress:a]; } - (id)initWithAddress:(id)_address { /* designated init */ if ((self = [super init])) { self->address = [_address retain]; self->debug = ImapDebugEnabled; self->responseReceiver = [[NSMutableArray alloc] initWithCapacity:128]; self->normer = [[NGImap4ResponseNormalizer alloc] initWithClient:self]; self->loggedIn = NO; self->context = nil; self->useUTF8 = YES; } return self; } - (void)dealloc { if (self->loggedIn) [self logout]; [self removeFromConnectionRegister]; [self->enabledExtensions release]; [self->normer release]; [self->text release]; [self->address release]; [self->socket release]; [self->previous_socket release]; [self->parser release]; [self->responseReceiver release]; [self->authname release]; [self->login release]; [self->password release]; [self->selectedFolder release]; [self->delimiter release]; [self->serverGID release]; self->context = nil; /* not retained */ [super dealloc]; } /* equality (required for adding clients to Foundation sets) */ - (BOOL)isEqual:(id)_obj { if (_obj == self) return YES; if ([_obj isKindOfClass:[NGImap4Client class]]) return [self isEqualToClient:_obj]; return NO; } - (BOOL)isEqualToClient:(NGImap4Client *)_obj { if (_obj == self) return YES; if (_obj == nil) return NO; return [[_obj address] isEqual:self->address]; } /* accessors */ - (id)socket { return self->socket; } - (id)address { return self->address; } - (NSString *)delimiter { if (self->delimiter == nil) { [self list:@"" pattern:@""]; } return self->delimiter; } - (EOGlobalID *)serverGlobalID { NGInternetSocketAddress *is; if (self->serverGID) return self->serverGID; is = (id)[self address]; self->serverGID = [[NGImap4ServerGlobalID alloc] initWithHostname:[is hostName] port:[is port] login:self->login]; return self->serverGID; } - (NSString *)selectedFolderName { return self->selectedFolder; } /* connection */ - (id)_openSocket { id sock; BOOL sslSocket = [self useSSL] && ![self useTLS]; NS_DURING { if (sslSocket) { sock = [NGActiveSSLSocket socketConnectedToAddress:self->address withVerifyMode: tlsVerifyMode]; } else { sock = [NGActiveSocket socketConnectedToAddress:self->address]; } } NS_HANDLER { [self->context setLastException:localException]; sock = nil; } NS_ENDHANDLER; return sock; } - (NSDictionary *)_receiveServerGreetingWithoutTagId { NSDictionary *res = nil; NS_DURING { NSException *e; NGHashMap *hm; hm = [self->parser parseResponseForTagId:-1 exception:&e]; [e raise]; res = [self->normer normalizeOpenConnectionResponse:hm]; // If using Courier, we disable UTF-8 if ([[res objectForKey:@"serverKind"] isEqual: @"courier"]) self->useUTF8 = NO; // If we're using TLS, we start it here if ([self useTLS]) { NSDictionary *d; d = [self->normer normalizeResponse:[self processCommand: @"STARTTLS"]]; if ([[d valueForKey:@"result"] boolValue]) { id o; o = [[NGActiveSSLSocket alloc] initWithConnectedActiveSocket: (NGActiveSocket *)self->socket withVerifyMode: tlsVerifyMode]; if ([o startTLS]) { NGBufferedStream *buffer; // We keep a reference to our previous instance of NGActiveSocket as // it's still being used. NGActiveSSLSocket's read/write methods are // being used but the rest is coming of directly from NGActiveSocket self->previous_socket = self->socket; self->socket = o; [self->text release]; [self->parser release]; buffer = [(NGBufferedStream *)[NGBufferedStream alloc] initWithSource: self->socket]; self->text = [(NGCTextStream *)[NGCTextStream alloc] initWithSource: buffer]; [buffer release]; buffer = nil; self->parser = [[NGImap4ResponseParser alloc] initWithStream: self->socket]; [self logWithFormat:@"TLS started successfully."]; } else [self logWithFormat:@"Could not start TLS."]; } else [self logWithFormat:@"Could not start TLS."]; } } NS_HANDLER [self->context setLastException:localException]; NS_ENDHANDLER; if (!_checkResult(self->context, res, __PRETTY_FUNCTION__)) return nil; return res; } - (NSDictionary *)_openConnection { /* open connection as configured */ NGBufferedStream *buffer; struct timeval tv; double ti = 0.0; if (ProfileImapEnabled == 1) { gettimeofday(&tv, NULL); ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0); } [self->socket release]; self->socket = nil; [self->previous_socket release]; self->previous_socket = nil; [self->parser release]; self->parser = nil; [self->text release]; self->text = nil; [self->context resetLastException]; if ((self->socket = [[self _openSocket] retain]) == nil) return nil; if ([self->context lastException]) return nil; buffer = [(NGBufferedStream *)[NGBufferedStream alloc] initWithSource:self->socket]; self->text = [(NGCTextStream *)[NGCTextStream alloc] initWithSource:buffer]; [buffer release]; buffer = nil; self->parser = [[NGImap4ResponseParser alloc] initWithStream:self->socket]; self->tagId = 0; if (ProfileImapEnabled == 1) { gettimeofday(&tv, NULL); ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0) - ti; fprintf(stderr, "[%s] : time needed: %4.4fs\n", __PRETTY_FUNCTION__, ti < 0.0 ? -1.0 : ti); } self->enabledExtensions = [[NSMutableArray alloc] init]; [self registerConnection]; [self->context resetLastException]; return [self _receiveServerGreetingWithoutTagId]; } - (NSDictionary *)openConnection { return [self _openConnection]; } - (NSNumber *)isConnected { // TODO: why is that an NSNummber? /* Check whether stream is already open (could be closed because server-timeout) */ return (self->socket == nil) ? NoNumber : ([(NGActiveSocket *)self->socket isAlive] ? YesNumber : NoNumber); } - (NSException *)_handleTextReleaseException:(NSException *)_ex { [self logWithFormat:@"got exception during stream dealloc: %@", _ex]; return nil; } - (NSException *)_handleSocketCloseException:(NSException *)_ex { [self logWithFormat:@"got exception during socket close: %@", _ex]; return nil; } - (NSException *)_handleSocketReleaseException:(NSException *)_ex { [self logWithFormat:@"got exception during socket deallocation: %@", _ex]; return nil; } - (void)closeConnection { /* close a connection */ // TODO: this is a bit weird, probably because of the flush // maybe just call -close on the text stream? NS_DURING [self->text release]; NS_HANDLER [[self _handleTextReleaseException:localException] raise]; NS_ENDHANDLER; self->text = nil; NS_DURING [self->socket shutdown]; [self->socket close]; [self->previous_socket shutdown]; [self->previous_socket close]; NS_HANDLER [[self _handleSocketCloseException:localException] raise]; NS_ENDHANDLER; NS_DURING [self->socket release]; [self->previous_socket release]; NS_HANDLER [[self _handleSocketReleaseException:localException] raise]; NS_ENDHANDLER; self->socket = nil; self->previous_socket = nil; [self->parser release]; self->parser = nil; [self->delimiter release]; self->delimiter = nil; [self->enabledExtensions release]; self->enabledExtensions = nil; [self removeFromConnectionRegister]; } // ResponseNotifications - (void)registerForResponseNotification:(id)_obj { [self->responseReceiver addObject:[NSValue valueWithNonretainedObject:_obj]]; } - (void)removeFromResponseNotification:(id)_obj { [self->responseReceiver removeObject: [NSValue valueWithNonretainedObject:_obj]]; } - (void)sendResponseNotification:(NGHashMap *)_map { NSValue *val; id obj; NSEnumerator *enumerator; NSDictionary *resp; resp = [self->normer normalizeResponse:_map]; enumerator = [self->responseReceiver objectEnumerator]; while ((val = [enumerator nextObject])) { obj = [val nonretainedObjectValue]; [obj responseNotificationFrom:self response:resp]; } } /* commands */ - (NSDictionary *)login:(NSString *)_login password:(NSString *)_passwd { /* login with plaintext password authenticating */ if ((_login == nil) || (_passwd == nil)) return nil; [self->login release]; self->login = nil; [self->password release]; self->password = nil; [self->serverGID release]; self->serverGID = nil; self->login = [_login copy]; self->password = [_passwd copy]; return [self login]; } - (NSDictionary *) authenticate: (NSString *) _login authname: (NSString *) _authname password: (NSString *) _passwd { [self->authname release]; self->authname = nil; self->authname = [_authname copy]; return [self authenticate: _login password: _passwd mechanism: nil]; } - (NSDictionary *)authenticate:(NSString *)_login password:(NSString *)_passwd mechanism:(NSString *)_mech { /* login with plaintext password authenticating */ if ((_login == nil) || (_passwd == nil)) return nil; if (_mech == nil) _mech = @"PLAIN"; [self->login release]; self->login = nil; [self->password release]; self->password = nil; [self->authMechanism release]; self->authMechanism = nil; [self->serverGID release]; self->serverGID = nil; self->login = _login; [_login retain]; self->password = _passwd; [_passwd retain]; self->authMechanism = _mech; [_mech retain]; return [self authenticate]; } - (void)reconnect { NSArray *extensions; if ([self->context lastException] != nil) return; extensions = self->enabledExtensions; [extensions retain]; [self closeConnection]; self->tagId = 0; [self openConnection]; if ([self->context lastException] != nil) return; if (self->useAuthenticate) [self authenticate]; else [self login]; if (self->loggedIn && [extensions count] > 0) { [self enable: extensions]; } [extensions autorelease]; } - (BOOL)passwordIsSimple { /* Password is pure printable ASCII [ -~] without quote and can thus be sent without continuation. This obviously includes the empty password which should (?) be sent directly. */ NSString *s = self->password; int i, len = [s length]; for (i = 0; i < len; i++) { unichar c = [s characterAtIndex:i]; if (c < ' ' || c == '"' || c > '~' || c == '\\') return NO; } return YES; } - (NSDictionary *)login { /* On failure returns a dictionary with those keys: 'result' - a boolean => false 'reason' - reason why login failed 'RawResponse' - the raw IMAP4 response On success: 'result' - a boolean => true 'expunge' - an array (containing what?) 'RawResponse' - the raw IMAP4 response */ NSDictionary *response; NGHashMap *map; NSString *s; NSUInteger plength; if (self->isLogin) return nil; self->isLogin = YES; if (self->useUTF8) plength = [self->password lengthOfBytesUsingEncoding: NSUTF8StringEncoding]; else plength = [self->password length]; if (![self passwordIsSimple]) s = [NSString stringWithFormat:@"login \"%@\" {%u}", self->login, (unsigned)plength]; else s = [NSString stringWithFormat:@"login \"%@\" \"%@\"", self->login, self->password]; map = [self processCommand: s withTag: YES withNotification: NO]; if (plength > 0 && [[map objectForKey:@"ContinuationResponse"] boolValue]) map = [self processCommand:self->password withTag:NO]; if (self->selectedFolder != nil) [self select:self->selectedFolder]; self->isLogin = NO; response = [self->normer normalizeResponse:map]; self->loggedIn = [[response valueForKey:@"result"] boolValue]; self->useAuthenticate = NO; return response; } - (NSDictionary *)authenticate { /* On failure returns a dictionary with those keys: 'result' - a boolean => false 'reason' - reason why authenticate failed 'RawResponse' - the raw IMAP4 response On success: 'result' - a boolean => true 'expunge' - an array (containing what?) 'RawResponse' - the raw IMAP4 response */ NSDictionary *response; NGHashMap *map; NSString *s; if (self->isLogin) return nil; self->isLogin = YES; s = [NSString stringWithFormat:@"authenticate %@", self->authMechanism]; map = [self processCommand: s withTag: YES withNotification: NO]; if ([[map objectForKey:@"ContinuationResponse"] boolValue]) { char *buffer; const char *utf8Username, *utf8Authname, *utf8Password; size_t buflen, lenUsername, lenAuthname, lenPassword; NSString *authString; if([self->authMechanism isEqualToString: @"xoauth2"]) { NSString *oauth2Password, *oauth2Username; oauth2Username = [NSString stringWithFormat: @"user=%@", self->login]; oauth2Password = [NSString stringWithFormat: @"auth=Bearer %@", self->password]; utf8Username = [oauth2Username UTF8String]; utf8Password = [oauth2Password UTF8String]; } else { utf8Username = [self->login UTF8String]; utf8Password = [self->password UTF8String]; if (!utf8Password) utf8Password = 0; } if (self->authname) utf8Authname = [self->authname UTF8String]; else utf8Authname = [self->login UTF8String]; lenUsername = strlen (utf8Username); lenAuthname = strlen (utf8Authname); lenPassword = strlen (utf8Password); if([self->authMechanism isEqualToString: @"xoauth2"]) { buflen = lenUsername + lenPassword + 3; buffer = malloc (sizeof (char) * (buflen + 1)); sprintf (buffer, "%s%c%s%c%c", utf8Username, 1, utf8Password, 1, 1); } else { buflen = lenUsername + lenAuthname + lenPassword + 2; buffer = malloc (sizeof (char) * (buflen + 1)); sprintf (buffer, "%s%c%s%c%s", utf8Username, 0, utf8Authname, 0, utf8Password); } authString = [[NSData dataWithBytesNoCopy: buffer length: buflen freeWhenDone: YES] stringByEncodingBase64]; map = [self processCommand:[authString stringByReplacingString: @"\n" withString: @""] withTag:NO]; } if (self->selectedFolder != nil) [self select:self->selectedFolder]; self->isLogin = NO; response = [self->normer normalizeResponse:map]; self->loggedIn = [[response valueForKey:@"result"] boolValue]; self->useAuthenticate = self->loggedIn; return response; } - (NSDictionary *)logout { /* logout from the connected host and close the connection */ NGHashMap *map; map = [self processCommand:@"logout"]; [self closeConnection]; [self->selectedFolder release]; self->selectedFolder = nil; self->loggedIn = NO; return [self->normer normalizeResponse:map]; } /* Authenticated State */ - (NSDictionary *)list:(NSString *)_folder pattern:(NSString *)_pattern { /* The method build statements like 'LIST "_folder" "_pattern"'. The Cyrus IMAP4 v1.5.14 server ignores the given folder. Instead of you should use the pattern to get the expected result. If folder is NIL it would be set to empty string ''. If pattern is NIL it would be set to ''. The result dict contains the following keys: 'result' - a boolean 'list' - a dictionary (key is folder name, value is flags) 'RawResponse' - the raw IMAP4 response */ NSAutoreleasePool *pool; NGHashMap *map; NSDictionary *result; NSString *s, *prefix; pool = [[NSAutoreleasePool alloc] init]; if (_folder == nil) _folder = @""; if (_pattern == nil) _pattern = @""; if ([_folder isNotEmpty]) { if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; } if ([_pattern isNotEmpty]) if (!(_pattern = [self _folder2ImapFolder:_pattern])) return nil; if ([_folder length] > 0) prefix = [NSString stringWithFormat: @"%@%@", SaneFolderName(_folder), self->delimiter]; else prefix = @""; s = [NSString stringWithFormat:@"LIST \"\" \"%@%@\"", prefix, _pattern]; map = [self processCommand:s]; if (self->delimiter == nil) { NSDictionary *rdel; rdel = [[map objectEnumeratorForKey:@"list"] nextObject]; self->delimiter = [[rdel objectForKey:@"delimiter"] copy]; } result = [[self->normer normalizeListResponse:map] copy]; [pool release]; return [result autorelease]; } - (NSDictionary *)capability { NSDictionary *result; id capres; result = [capabilities objectForKey: [self->address description]]; if (!result) { capres = [self processCommand:@"capability"]; result = [self->normer normalizeCapabilityResponse:capres]; if (result) [capabilities setObject: result forKey: [self->address description]]; } return result; } - (NSDictionary *)enable:(NSArray *)_extensions { NSDictionary *result; NSString *cmd; cmd = [NSString stringWithFormat:@"ENABLE %@", [_extensions componentsJoinedByString: @" "]]; result = [self->normer normalizeResponse:[self processCommand:cmd]]; if ([[result valueForKey:@"result"] boolValue]) { [enabledExtensions removeObjectsInArray: _extensions]; [enabledExtensions addObjectsFromArray: _extensions]; } return result; } - (NSDictionary *)namespace { NSArray *capabilities; NGHashMap *namesres; id namespace; namespace = [namespaces objectForKey: [self->address description]]; if (!namespace) { capabilities = [[self capability] objectForKey: @"capability"]; if ([capabilities containsObject: @"namespace"]) { namesres = [self processCommand: @"namespace"]; namespace = [self->normer normalizeNamespaceResponse:namesres]; } else namespace = [NSNull null]; [namespaces setObject: namespace forKey: [self->address description]]; } return ([namespace isKindOfClass: [NSNull class]] ? nil : namespace); } - (NSDictionary *)lsub:(NSString *)_folder pattern:(NSString *)_pattern { /* The method build statements like 'LSUB "_folder" "_pattern"'. The returnvalue is the same like the list:pattern: method */ NGHashMap *map; NSString *s, *prefix; if (_folder == nil) _folder = @""; if ([_folder isNotEmpty]) { if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; } if (_pattern == nil) _pattern = @""; if ([_pattern isNotEmpty]) { if ((_pattern = [self _folder2ImapFolder:_pattern]) == nil) return nil; } if ([_folder length] > 0) prefix = [NSString stringWithFormat: @"%@%@", SaneFolderName(_folder), self->delimiter]; else prefix = @""; s = [NSString stringWithFormat:@"LSUB \"\" \"%@%@\"", prefix, _pattern]; map = [self processCommand:s]; if (self->delimiter == nil) { NSDictionary *rdel; rdel = [[map objectEnumeratorForKey:@"LIST"] nextObject]; self->delimiter = [[rdel objectForKey:@"delimiter"] copy]; } return [self->normer normalizeListResponse:map]; } - (NSDictionary *)select:(NSString *)_folder { /* Select a folder (required for a lot of methods). eg: 'SELECT "INBOX"' The result dict contains the following keys: 'result' - a boolean 'access' - string (eg "READ-WRITE") 'exists' - number? (eg 1) 'recent' - number? (eg 0) 'expunge' - array (of what?) 'flags' - array of strings (eg (answered,flagged,draft,seen); 'RawResponse' - the raw IMAP4 response */ NSString *s, *newFolder; if (![_folder isNotEmpty]) return nil; if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; newFolder = [NSString stringWithString: _folder]; ASSIGN (self->selectedFolder, newFolder); s = [NSString stringWithFormat:@"select \"%@\"", SaneFolderName(self->selectedFolder)]; return [self->normer normalizeSelectResponse:[self processCommand:s]]; } - (NSDictionary *)unselect { if (self->selectedFolder != nil) { [self->selectedFolder release]; self->selectedFolder = nil; return [self->normer normalizeResponse:[self processCommand:@"unselect"]]; } return nil; } - (NSDictionary *)lstatus:(NSString *)_folder flags:(NSArray *)_flags { NSString *cmd; if (_folder == nil) return nil; if ((_flags == nil) || ([_flags count] == 0)) return nil; if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; cmd = [NSString stringWithFormat:@"list \"\" \"%@\" return (status (%@) children)", SaneFolderName(_folder), [_flags componentsJoinedByString:@" "]]; return [self->normer normalizeListStatusResponse:[self processCommand:cmd]]; } /* result dict looks like the following {FolderList = {INBOX = {"/comment" = {"value.priv" = "sogo_73c_192bd57b_d8"; }; }; "Other Users/sogo2" = {"/comment" = {"value.priv" = "sogo_c0c_192bd7dc_0"; }; }; Sent = {"/comment" = {"value.priv" = "sogo_73c_192bd57b_da"; }; }; Trash = {"/comment" = {"value.priv" = "sogo_73c_192bd57b_dc"; }; }; abczzll = {"/comment" = {"value.priv" = "sogo_73c_192bd57b_d9"; }; }; "abczzll/mmabcmm" = {"/comment" = {"value.priv" = "sogo_73c_192bd57b_de"; }; }; mf1renamedd = {"/comment" = {"value.priv" = "sogo_73c_192bd57b_dd"; }; }; tfu1 = {"/comment" = {"value.priv" = "sogo_73c_192bd57b_db"; }; }; zuk = {"/comment" = {"value.priv" = "sogo_73c_192bd57b_df"; }; }; }; RawResponse = "{FolderList = ({INBOX = {\"/comment\" = {\"value.priv\" = \"sogo_73c_192bd57b_d8\"; }; }; }, {Sent = {\"/comment\" = {\"value.priv\" = \"sogo_73c_192bd57b_da\"; }; }; }, {Trash = {\"/comment\" = {\"value.priv\" = \"sogo_73c_192bd57b_dc\"; }; }; }, {abczzll = {\"/comment\" = {\"value.priv\" = \"sogo_73c_192bd57b_d9\"; }; }; }, {\"abczzll/mmabcmm\" = {\"/comment\" = {\"value.priv\" = \"sogo_73c_192bd57b_de\"; }; }; }, {mf1renamedd = {\"/comment\" = {\"value.priv\" = \"sogo_73c_192bd57b_dd\"; }; }; }, {tfu1 = {\"/comment\" = {\"value.priv\" = \"sogo_73c_192bd57b_db\"; }; }; }, {zuk = {\"/comment\" = {\"value.priv\" = \"sogo_73c_192bd57b_df\"; }; }; }, {\"Other Users/sogo2\" = {\"/comment\" = {\"value.priv\" = \"sogo_c0c_192bd7dc_0\"; }; }; }); ResponseResult = {description = Completed; result = ok; tagId = 13; }; }"; expunge = (); result = 1; } getannotation: result = [client annotation: folderName entryName: @"/comment" attributeName: @"value.priv"]; result = [client annotation: folderName entryName: @"/comment" attributeName: @"value"]; result = [client annotation: folderName entryName: @"/*" attributeName: @"value"]; result = [client annotation: @"" entryName: @"/*" attributeName: @"value"]; */ - (NSDictionary *)annotation:(NSString *)_folder entryName:(NSString *)_entry attributeName:(NSString *)_attribute { NSString *cmd; NGHashMap *_map; NSDictionary *obj; NSMutableDictionary *result, *folderList; NSEnumerator *enumerator; if (_folder == nil) return nil; if (_entry == nil) return nil; if (_attribute == nil) return nil; if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; cmd = [NSString stringWithFormat:@"GETANNOTATION \"%@\" \"%@\" \"%@\"", SaneFolderName(_folder), _entry, _attribute]; result = [NSMutableDictionary dictionaryWithCapacity:2]; _map = [self processCommand:cmd]; result = [self->normer normalizeResponse:_map]; enumerator = [_map objectEnumeratorForKey:@"FolderList"]; folderList = [NSMutableDictionary dictionaryWithCapacity:5]; while ((obj = [enumerator nextObject]) != nil) { if ([obj objectForKey: [[obj allKeys] objectAtIndex:0]]) [folderList setObject: [obj objectForKey: [[obj allKeys] objectAtIndex:0]] forKey: [[self _imapFolder2Folder: [[obj allKeys] objectAtIndex:0]] substringFromIndex:1]]; } [result setObject: folderList forKey: @"FolderList" ]; return result; } - (NSDictionary *)annotation:(NSString *)_folder entryName:(NSString *)_entry attributeName:(NSString *)_attribute attributeValue:(NSString *)_value { NSString *cmd; NSMutableDictionary *result; if (_folder == nil) return nil; if (_entry == nil) return nil; if (_attribute == nil) return nil; if (_value == nil) return nil; if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; cmd = [NSString stringWithFormat:@"SETANNOTATION \"%@\" \"%@\" (\"%@\" \"%@\")", SaneFolderName(_folder), _entry, _attribute, _value]; result = [NSMutableDictionary dictionaryWithCapacity:2]; result = [self->normer normalizeResponse:[self processCommand:cmd]]; return result; } - (NSDictionary *)status:(NSString *)_folder flags:(NSArray *)_flags { NSString *cmd; if (_folder == nil) return nil; if ((_flags == nil) || ([_flags count] == 0)) return nil; if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; cmd = [NSString stringWithFormat:@"status \"%@\" (%@)", SaneFolderName(_folder), [_flags componentsJoinedByString:@" "]]; return [self->normer normalizeStatusResponse:[self processCommand:cmd]]; } - (NSDictionary *)noop { // at any state return [self->normer normalizeResponse:[self processCommand:@"noop"]]; } - (NSDictionary *)rename:(NSString *)_folder to:(NSString *)_newName { NSString *cmd; if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; if ((_newName = [self _folder2ImapFolder:_newName]) == nil) return nil; cmd = [NSString stringWithFormat:@"rename \"%@\" \"%@\"", SaneFolderName(_folder), SaneFolderName(_newName)]; return [self->normer normalizeResponse:[self processCommand:cmd]]; } - (NSDictionary *)_performCommand:(NSString *)_op onFolder:(NSString *)_fname { NSString *command; NSString *name; if ((_fname = [self _folder2ImapFolder:_fname]) == nil) return nil; // eg: 'delete "blah"'. We correctly encode the foldername here // as we don't do it anymore automagically everywhere in SOPE. if ([_fname is7bitSafe]) name = _fname; else name = [_fname stringByEncodingImap4FolderName]; command = [NSString stringWithFormat:@"%@ \"%@\"", _op, SaneFolderName(name)]; return [self->normer normalizeResponse:[self processCommand:command]]; } - (NSDictionary *)delete:(NSString *)_name { if ([self->selectedFolder isEqualToString:_name]) { [self unselect]; } return [self _performCommand:@"delete" onFolder:_name]; } - (NSDictionary *)create:(NSString *)_name { return [self _performCommand:@"create" onFolder:_name]; } - (NSDictionary *)subscribe:(NSString *)_name { return [self _performCommand:@"subscribe" onFolder:_name]; } - (NSDictionary *)unsubscribe:(NSString *)_name { return [self _performCommand:@"unsubscribe" onFolder:_name]; } - (NSDictionary *)expunge { return [self->normer normalizeResponse:[self processCommand:@"expunge"]]; } - (NSString *)_uidsJoinedForFetchCmd:(NSArray *)_uids { return [_uids componentsJoinedByString:@","]; } - (NSString *)_partsJoinedForFetchCmd:(NSArray *)_parts { return [_parts componentsJoinedByString:@" "]; } - (NSDictionary *)fetchUids:(NSArray *)_uids parts:(NSArray *)_parts { /* eg: 'UID FETCH 1189,1325,1326 ([TODO])' */ NSAutoreleasePool *pool; NSString *cmd; NSDictionary *result; NSString *uidsStr, *partsStr; id fetchres; pool = [[NSAutoreleasePool alloc] init]; uidsStr = [self _uidsJoinedForFetchCmd:_uids]; partsStr = [self _partsJoinedForFetchCmd:_parts]; cmd = [NSString stringWithFormat:@"uid fetch %@ (%@)", uidsStr, partsStr]; fetchres = [self processCommand:cmd]; result = [[self->normer normalizeFetchResponse:fetchres] retain]; [pool release]; return [result autorelease]; } - (NSDictionary *)fetchUid:(unsigned)_uid parts:(NSArray *)_parts { // TODO: describe what exactly this can return! NSAutoreleasePool *pool; NSString *cmd; NSDictionary *result; id fetchres; pool = [[NSAutoreleasePool alloc] init]; cmd = [NSString stringWithFormat:@"uid fetch %u (%@)", _uid, [self _partsJoinedForFetchCmd:_parts]]; fetchres = [self processCommand:cmd]; result = [[self->normer normalizeFetchResponse:fetchres] retain]; [pool release]; return [result autorelease]; } - (NSDictionary *)fetchFrom:(unsigned)_from to:(unsigned)_to parts:(NSArray *)_parts { // TODO: optimize NSAutoreleasePool *pool; NSMutableString *cmd; NSDictionary *result; NGHashMap *rawResult; if (_to == 0) return [self noop]; if (_from == 0) _from = 1; pool = [[NSAutoreleasePool alloc] init]; { unsigned i, count; cmd = [NSMutableString stringWithCapacity:256]; [cmd appendString:@"fetch "]; [cmd appendFormat:@"%u:%u (", _from, _to]; for (i = 0, count = [_parts count]; i < count; i++) { if (i != 0) [cmd appendString:@" "]; [cmd appendString:[_parts objectAtIndex:i]]; } [cmd appendString:@")"]; if (fetchDebug) NSLog(@"%s: process: %@", __PRETTY_FUNCTION__, cmd); rawResult = [self processCommand:cmd]; /* RawResult is a dict containing keys: ResponseResult: dict eg: {descripted=Completed;result=ok;tagId=8;} fetch: array of record dicts (eg "rfc822.header" key) */ if (fetchDebug) NSLog(@"%s: normalize: %@", __PRETTY_FUNCTION__,rawResult); result = [[self->normer normalizeFetchResponse:rawResult] retain]; if (fetchDebug) NSLog(@"%s: normalized: %@", __PRETTY_FUNCTION__, result); } [pool release]; if (fetchDebug) NSLog(@"%s: pool done.", __PRETTY_FUNCTION__); return [result autorelease]; } - (NSDictionary *) fetchModseqForUid: (unsigned)_uid { NSString *cmd; NSDictionary *result; id fetchres; cmd = [NSString stringWithFormat: @"UID FETCH %llu:%llu (UID) (CHANGEDSINCE 1)", (unsigned long long)_uid, (unsigned long long)_uid]; fetchres = [self processCommand:cmd]; result = [self->normer normalizeFetchResponse:fetchres]; return result; } - (NSDictionary *)fetchVanished:(uint64_t)_modseq { NSAutoreleasePool *pool; NSString *cmd; NSDictionary *result; id fetchres; pool = [[NSAutoreleasePool alloc] init]; cmd = [NSString stringWithFormat: @"UID FETCH 1:* (UID) (CHANGEDSINCE %llu VANISHED)", (unsigned long long)_modseq]; fetchres = [self processCommand:cmd]; result = [[self->normer normalizeFetchResponse:fetchres] retain]; [pool release]; return [result autorelease]; } - (NSDictionary *)storeUid:(unsigned)_uid add:(NSNumber *)_add flags:(NSArray *)_flags { NSString *icmd, *iflags; iflags = [_flags2ImapFlags(self, _flags) componentsJoinedByString:@" "]; icmd = [NSString stringWithFormat:@"uid store %u %cFLAGS (%@)", _uid, [_add boolValue] ? '+' : '-', iflags]; return [self->normer normalizeResponse:[self processCommand:icmd]]; } - (NSDictionary *)storeFrom:(unsigned)_from to:(unsigned)_to add:(NSNumber *)_add flags:(NSArray *)_flags { NSString *cmd; NSString *flagstr; if (_to == 0) return [self noop]; if (_from == 0) _from = 1; flagstr = [_flags2ImapFlags(self, _flags) componentsJoinedByString:@" "]; cmd = [NSString stringWithFormat:@"store %u:%u %cFLAGS (%@)", _from, _to, [_add boolValue] ? '+' : '-', flagstr]; return [self->normer normalizeResponse:[self processCommand:cmd]]; } - (NSDictionary *)storeFlags:(NSArray *)_flags forUIDs:(id)_uids addOrRemove:(BOOL)_flag { NSString *cmd; NSString *flagstr; NSString *seqstr; if ([_uids isKindOfClass:[NSArray class]]) { // TODO: improve by using ranges, eg 1:5 instead of 1,2,3,4,5 _uids = [_uids valueForKey:@"stringValue"]; seqstr = [_uids componentsJoinedByString:@","]; } else seqstr = [_uids stringValue]; flagstr = [_flags2ImapFlags(self, _flags) componentsJoinedByString:@" "]; cmd = [NSString stringWithFormat:@"UID STORE %@ %cFLAGS (%@)", seqstr, _flag ? '+' : '-', flagstr]; return [self->normer normalizeResponse:[self processCommand:cmd]]; } - (NSDictionary *)copyFrom:(unsigned)_from to:(unsigned)_to toFolder:(NSString *)_folder { NSString *cmd; if (_to == 0) return [self noop]; if (_from == 0) _from = 1; if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; cmd = [NSString stringWithFormat:@"copy %u:%u \"%@\"", _from, _to, SaneFolderName(_folder)]; return [self->normer normalizeResponse:[self processCommand:cmd]]; } - (NSDictionary *)copyUid:(unsigned)_uid toFolder:(NSString *)_folder { NSString *cmd; if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; cmd = [NSString stringWithFormat:@"uid copy %u \"%@\"", _uid, SaneFolderName(_folder)]; return [self->normer normalizeResponse:[self processCommand:cmd]]; } - (NSDictionary *)copyUids:(NSArray *)_uids toFolder:(NSString *)_folder { NSString *cmd; if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; cmd = [NSString stringWithFormat:@"uid copy %@ \"%@\"", [_uids componentsJoinedByString:@","], SaneFolderName(_folder)]; return [self->normer normalizeResponse:[self processCommand:cmd]]; } - (NSDictionary *) moveUids: (NSArray *)_uids toFolder: (NSString *)_folder { NSArray *capa; NSString *cmd; if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; capa = [[self capability] objectForKey: @"capability"]; if (![capa containsObject: @"move"]) return nil; cmd = [NSString stringWithFormat:@"uid move %@ \"%@\"", [_uids componentsJoinedByString:@","], SaneFolderName(_folder)]; return [self->normer normalizeResponse:[self processCommand:cmd]]; } - (NSDictionary *)getQuotaRoot:(NSString *)_folder { NSString *cmd; if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; cmd = [NSString stringWithFormat:@"getquotaroot \"%@\"", _folder]; return [self->normer normalizeQuotaResponse:[self processCommand:cmd]]; } - (NSDictionary *)append:(NSData *)_message toFolder:(NSString *)_folder withFlags:(NSArray *)_flags { NSArray *flags; NGHashMap *result; NSString *message, *icmd; NSData *rfc822Data; flags = _flags2ImapFlags(self, _flags); if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; /* Remove bare newlines */ rfc822Data = [_message dataByEnsuringCRLFLineEndings]; icmd = [NSString stringWithFormat:@"append \"%@\" (%@) {%u}", SaneFolderName(_folder), [flags componentsJoinedByString:@" "], (unsigned)[rfc822Data length]]; result = [self processCommand:icmd withTag:YES withNotification:NO]; // TODO: explain that if ([[result objectForKey:@"ContinuationResponse"] boolValue]) { // TODO: fix this junk, do not treat the message as a string, its NSData message = [[NSString alloc] initWithData: rfc822Data encoding: NSISOLatin1StringEncoding]; [[self textStream] setEncoding: NSISOLatin1StringEncoding]; result = [self processCommand:message withTag:NO]; [message release]; message = nil; } return [self->normer normalizeResponse:result]; } - (void)_handleSearchExprIssue:(NSString *)reason qualifier:(EOQualifier *)_q { NSString *descr; NSException *exception = nil; NSDictionary *ui; if (PreventExceptions != 0) return; if (_q == nil) _q = (id)[NSNull null]; descr = @"Could not process qualifier for imap search "; descr = [descr stringByAppendingString:reason]; ui = [NSDictionary dictionaryWithObject:_q forKey:@"qualifier"]; exception = [NGImap4SearchException exceptionWithName: @"NGImap4SearchException" reason: descr userInfo: ui]; [self->context setLastException:exception]; } - (NSString *)_searchExprForQual:(EOQualifier *)_qualifier { /* samples: ' ALL' ' SINCE 1-Feb-1994' ' TEXT "why SOPE rocks"' */ id result; if (_qualifier == nil) return @" ALL"; result = [_qualifier imap4SearchString]; if ([result isKindOfClass:[NSException class]]) { [self _handleSearchExprIssue:[(NSException *)result reason] qualifier:_qualifier]; return nil; } return [@" " stringByAppendingString:result]; } - (NSDictionary *)threadBySubject: (BOOL)_bySubject charset: (NSString *)_charSet qualifier: (EOQualifier *)_qual { /* http://www.ietf.org/proceedings/03mar/I-D/draft-ietf-imapext-thread-12.txt Returns an array of uids in sort order. Parameters: _bySubject - if yes, use "REFERENCES" else "ORDEREDSUBJECT" _charSet - default: "UTF-8" Generates: UID THREAD REFERENCES|ORDEREDSUBJECT UTF-8 ALL */ NSString *threadStr; NSString *threadAlg; NSArray *capa; threadAlg = (_bySubject) ? @"ORDEREDSUBJECT" : @"REFERENCES"; if (![_charSet isNotEmpty]) _charSet = @"UTF-8"; // Verify server capablities capa = [[self capability] objectForKey: @"capability"]; if ([capa indexOfObject: [NSString stringWithFormat: @"thread=%@", [threadAlg lowercaseString]]] == NSNotFound) { [self logWithFormat: @"WARNING: No support for THREAD %@ for %@", threadAlg, [self->address description]]; threadAlg = (_bySubject) ? @"REFERENCES" : @"ORDEREDSUBJECT"; if ([capa indexOfObject: [NSString stringWithFormat: @"thread=%@", [threadAlg lowercaseString]]] == NSNotFound) { [self errorWithFormat: @"No support for THREAD %@ for %@", threadAlg, [self->address description]]; return nil; } } threadStr = [NSString stringWithFormat:@"UID THREAD %@ %@ (%@)", threadAlg, _charSet, [[self _searchExprForQual: _qual] substringFromIndex: 1]]; return [self->normer normalizeThreadResponse: [self processCommand: threadStr]]; } - (NSString *)_generateIMAP4SortOrdering:(EOSortOrdering *)_sortOrdering { // TODO: still called by anything? return [_sortOrdering imap4SortString]; } - (NSString *)_generateIMAP4SortOrderings:(NSArray *)_sortOrderings { return [_sortOrderings imap4SortStringForSortOrderings]; } - (NSDictionary *)primarySort:(NSString *)_sort qualifierString:(NSString *)_qualString encoding:(NSString *)_encoding { /* http://www.ietf.org/internet-drafts/draft-ietf-imapext-sort-17.txt The result dict contains the following keys: 'result' - a boolean 'expunge' - array (of what?) 'sort' - array of uids in sort order 'RawResponse' - the raw IMAP4 response Eg: UID SORT ( DATE REVERSE SUBJECT ) UTF-8 TODO */ NSMutableString *sortStr; NSUserDefaults *ud; if (![_encoding isNotNull]) _encoding = @"UTF-8"; if (![_qualString isNotNull]) _qualString = @" ALL"; // Prior sending the SORT command, we make sure it really supports // SORT UTF-8. We could have received that no matter what is supported if (!self->useUTF8) _encoding = @"US-ASCII"; // If we forced an encoding, we ignore everything and uses that ud = [NSUserDefaults standardUserDefaults]; if ([ud stringForKey:@"ImapSortEncoding"]) _encoding = [ud stringForKey:@"ImapSortEncoding"]; sortStr = [NSMutableString stringWithCapacity:128]; [sortStr appendString:@"UID SORT ("]; if (_sort != nil) [sortStr appendString:_sort]; [sortStr appendString:@") "]; [sortStr appendString:_encoding]; /* eg 'UTF-8' or '' */ /* Note: this is _space sensitive_! to many spaces lead to error! */ [sortStr appendString:_qualString]; /* eg ' ALL' or ' TEXT "abc"' */ return [self->normer normalizeSortResponse:[self processCommand:sortStr]]; } - (NSDictionary *)sort:(id)_sortSpec qualifier:(EOQualifier *)_qual encoding:(NSString *)_encoding { /* http://www.ietf.org/internet-drafts/draft-ietf-imapext-sort-17.txt The _sortSpec can be: - a simple 'raw' IMAP4 sort string - an EOSortOrdering - an array of EOSortOrderings The result dict contains the following keys: 'result' - a boolean 'expunge' - array (of what?) 'sort' - array of uids in sort order 'RawResponse' - the raw IMAP4 response If no sortable key was found, the sort will run against 'DATE'. => TODO: this is inconsistent. If none are passed in, false will be returned Eg: UID SORT ( DATE REVERSE SUBJECT ) UTF-8 TODO */ NSString *tmp; NSArray *capa; // We first check to see if our server supports IMAP SORT. If not // we'll sort ourself the results. capa = [[self capability] objectForKey: @"capability"]; if ([capa indexOfObject: @"sort"] == NSNotFound) { return [self _sopeSORT: _sortSpec qualifier: _qual encoding: _encoding]; } if ([_sortSpec isKindOfClass:[NSArray class]]) tmp = [self _generateIMAP4SortOrderings:_sortSpec]; else if ([_sortSpec isKindOfClass:[EOSortOrdering class]]) tmp = [self _generateIMAP4SortOrdering:_sortSpec]; else tmp = [_sortSpec stringValue]; if (![tmp isNotEmpty]) { /* found no valid key use date sorting */ [self logWithFormat:@"Note: no key found for sorting, using 'DATE': %@", _sortSpec]; tmp = @"DATE"; } return [self primarySort: tmp qualifierString: [self _searchExprForQual:_qual] encoding: _encoding]; } - (NSDictionary *)sort:(NSArray *)_sortOrderings qualifier:(EOQualifier *)_qual { return [self sort:_sortOrderings qualifier:_qual encoding: (self->useUTF8 ? @"UTF-8" : nil)]; } - (NSDictionary *)searchWithQualifier:(EOQualifier *)_qualifier { NSString *s; s = [self _searchExprForQual:_qualifier]; if (![s isNotEmpty]) { // TODO: should set last-exception? [self logWithFormat:@"ERROR(%s): could not process search qualifier: %@", __PRETTY_FUNCTION__, _qualifier]; return nil; } s = [@"UID SEARCH" stringByAppendingString:s]; return [self->normer normalizeSearchResponse:[self processCommand:s]]; } /* ACLs */ - (NSDictionary *)getACL:(NSString *)_folder { NSString *cmd; if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; cmd = [NSString stringWithFormat:@"getacl \"%@\"", SaneFolderName(_folder)]; return [self->normer normalizeGetACLResponse:[self processCommand:cmd]]; } - (NSDictionary *)setACL:(NSString *)_folder rights:(NSString *)_r uid:(NSString *)_uid { NSString *cmd; if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; cmd = [NSString stringWithFormat:@"setacl \"%@\" \"%@\" \"%@\"", SaneFolderName(_folder), _uid, _r]; return [self->normer normalizeResponse:[self processCommand:cmd]]; } - (NSDictionary *)deleteACL:(NSString *)_folder uid:(NSString *)_uid { NSString *cmd; if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; cmd = [NSString stringWithFormat:@"deleteacl \"%@\" \"%@\"", SaneFolderName(_folder), _uid]; return [self->normer normalizeResponse:[self processCommand:cmd]]; } - (NSDictionary *)listRights:(NSString *)_folder uid:(NSString *)_uid { NSString *cmd; if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; cmd = [NSString stringWithFormat:@"listrights \"%@\" \"%@\"", SaneFolderName(_folder), _uid]; return [self->normer normalizeListRightsResponse:[self processCommand:cmd]]; } - (NSDictionary *)myRights:(NSString *)_folder { NSString *cmd; if ((_folder = [self _folder2ImapFolder:_folder]) == nil) return nil; cmd = [NSString stringWithFormat:@"myrights \"%@\"", SaneFolderName(_folder)]; return [self->normer normalizeMyRightsResponse:[self processCommand:cmd]]; } /* Private Methods */ - (NSDictionary *) _sopeSORT: (id)_sortSpec qualifier:(EOQualifier *)_qual encoding:(NSString *)_encoding { NSMutableDictionary *result; NSDictionary *d; NSCalendarDate *envDate; result = [NSMutableDictionary dictionary]; [result setObject: [NSNumber numberWithBool: NO] forKey: @"result"]; // _sortSpec: [REVERSE] {DATE,FROM,SUBJECT} d = [self searchWithQualifier: _qual]; if ((d = [d objectForKey: @"RawResponse"])) { NSMutableDictionary *dict; NSArray *a, *s_a; BOOL b; int i; a = [d objectForKey: @"search"]; if ([a isNotEmpty]) { // If we are sorting by DATE or REVERSE DATE, we do NOT fetch all the body envelope // and we assume the server returns us the fetched UIDs in the right order. if ([_sortSpec caseInsensitiveCompare: @"DATE"] == NSOrderedSame || [_sortSpec caseInsensitiveCompare: @"REVERSE DATE"] == NSOrderedSame) { s_a = a; } else { d = [self fetchUids: a parts: [NSArray arrayWithObjects: @"ENVELOPE", @"RFC822.SIZE", nil]]; a = [d objectForKey: @"fetch"]; dict = [NSMutableDictionary dictionary]; b = YES; for (i = 0; i < [a count]; i++) { NGImap4Envelope *env; id o, uid, s; o = [a objectAtIndex: i]; env = [o objectForKey: @"envelope"]; uid = [o objectForKey: @"uid"]; if ([_sortSpec rangeOfString: @"SUBJECT"].length) { s = [env subject]; if ([s isKindOfClass: [NSData class]]) s = [[[NSString alloc] initWithData: s encoding: NSUTF8StringEncoding] autorelease]; [dict setObject: (s != nil ? s : (id)@"") forKey: uid]; } else if ([_sortSpec rangeOfString: @"FROM"].length) { s = [[[env from] lastObject] email]; [dict setObject: (s != nil ? s : (id)@"") forKey: uid]; } else if ([_sortSpec rangeOfString: @"SIZE"].length) { s = [o objectForKey: @"size"]; [dict setObject: (s != nil ? (NSNumber *)s : [NSNumber numberWithInt: 0]) forKey: uid]; b = NO; } else { envDate = [env date]; if (!envDate) envDate = [NSCalendarDate date]; [dict setObject: envDate forKey: uid]; b = NO; } } if (b) s_a = [dict keysSortedByValueUsingSelector: @selector(caseInsensitiveCompare:)]; else s_a = [dict keysSortedByValueUsingSelector: @selector(compare:)]; } if ([_sortSpec rangeOfString: @"REVERSE"].length) { s_a = [[s_a reverseObjectEnumerator] allObjects]; } } else { s_a = [NSArray array]; } [result setObject: [NSNumber numberWithBool: YES] forKey: @"result"]; [result setObject: s_a forKey: @"sort"]; } return result; } - (NSException *)_processCommandParserException:(NSException *)_exception { [self logWithFormat:@"ERROR(%s): catched IMAP4 parser exception %@: %@", __PRETTY_FUNCTION__, [_exception name], [_exception reason]]; [self closeConnection]; [self->context setLastException:_exception]; return nil; } - (NSException *)_processUnknownCommandParserException:(NSException *)_ex { [self logWithFormat:@"ERROR(%s): catched non-IMAP4 parsing exception %@: %@", __PRETTY_FUNCTION__, [_ex name], [_ex reason]]; return nil; } - (NSException *)_handleShutdownDuringCommandException:(NSException *)_ex { [self logWithFormat: @"ERROR(%s): IMAP4 socket was shut down by server %@: %@", __PRETTY_FUNCTION__, [_ex name], [_ex reason]]; [self closeConnection]; [self->context setLastException:_ex]; return nil; } - (BOOL)_isShutdownException:(NSException *)_ex { return [[_ex name] isEqualToString:@"NGSocketShutdownDuringReadException"]; } - (BOOL)_isLoginCommand:(NSString *)_command { return [_command hasPrefix:@"login"] || [_command hasPrefix:@"authenticate"]; } - (NGHashMap *)processCommand:(NSString *)_command withTag:(BOOL)_tag withNotification:(BOOL)_notification logText:(NSString *)_txt { NGHashMap *map; BOOL tryReconnect; int reconnectCnt; NSException *exception; struct timeval tv; double ti = 0.0; if (ProfileImapEnabled == 1) { gettimeofday(&tv, NULL); ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0); fprintf(stderr, "{"); } tryReconnect = NO; reconnectCnt = 0; map = nil; exception = nil; do { tryReconnect = NO; [self->context resetLastException]; NS_DURING { NSException *e = nil; // TODO: try to remove exception handler [self sendCommand:_command withTag:_tag logText:_txt]; map = [self->parser parseResponseForTagId:self->tagId exception:&e]; [e raise]; tryReconnect = NO; } NS_HANDLER { if ([localException isKindOfClass:[NGImap4ParserException class]]) { [[self _processCommandParserException:localException] raise]; } else if ([self _isShutdownException:localException]) { [[self _handleShutdownDuringCommandException:localException] raise]; } else { [[self _processUnknownCommandParserException:localException] raise]; if (reconnectCnt == 0) { if (![self _isLoginCommand:_command]) { reconnectCnt++; tryReconnect = YES; exception = localException; } } else { [self closeConnection]; } [self->context setLastException:localException]; } } NS_ENDHANDLER; if (tryReconnect) { [self reconnect]; } else if ([map objectForKey:@"bye"] && ![_command hasPrefix:@"logout"] && ![self _isLoginCommand:_command]) { if (reconnectCnt == 0) { reconnectCnt++; tryReconnect = YES; [self reconnect]; } } } while (tryReconnect); if ([self->context lastException]) { if (exception) { [self->context setLastException:exception]; } return nil; } if (_notification) [self sendResponseNotification:map]; if (ProfileImapEnabled == 1) { gettimeofday(&tv, NULL); ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0) - ti; fprintf(stderr, "}[%s] : time needed: %4.4fs\n", __PRETTY_FUNCTION__, [_command cString], ti < 0.0 ? -1.0 : ti); } return map; } - (NGHashMap *)processCommand:(NSString *)_command withTag:(BOOL)_tag withNotification:(BOOL)_notification { return [self processCommand:_command withTag:_tag withNotification:_notification logText:_command]; } - (NGHashMap *)processCommand:(NSString *)_command withTag:(BOOL)_tag { return [self processCommand:_command withTag:_tag withNotification:YES logText:_command]; } - (NGHashMap *)processCommand:(NSString *)_command { return [self processCommand:_command withTag:YES withNotification:YES logText:_command]; } - (NGHashMap *)processCommand:(NSString *)_command logText:(NSString *)_txt { return [self processCommand:_command withTag:YES withNotification:YES logText:_txt]; } - (void)sendCommand:(NSString *)_command withTag:(BOOL)_tag logText:(NSString *)_txt { NSString *command; NGCTextStream *txtStream; txtStream = [self textStream]; if (_tag) { self->tagId++; command = [NSString stringWithFormat:@"%u %@", self->tagId, _command]; if (self->debug) { _txt = [NSString stringWithFormat:@"%u %@", self->tagId, _txt]; } } else command = _command; if (self->debug) { fprintf(stderr, "C[%p]: %s\n", self, [_txt cString]); } if (![txtStream writeString:command]) [self->context setLastException:[txtStream lastException]]; else if (![txtStream writeString:@"\r\n"]) [self->context setLastException:[txtStream lastException]]; else if (![txtStream flush]) [self->context setLastException:[txtStream lastException]]; } - (void)sendCommand:(NSString *)_command withTag:(BOOL)_tag { [self sendCommand:_command withTag:_tag logText:_command]; } - (void)sendCommand:(NSString *)_command { [self sendCommand:_command withTag:YES logText:_command]; } - (NSArray *)_flags2ImapFlags:(NSArray *)_flags { /* adds backslashes in front of the flags */ NSEnumerator *enumerator; NSArray *result; id obj; id *objs; unsigned cnt; objs = calloc([_flags count] + 2, sizeof(id)); cnt = 0; enumerator = [_flags objectEnumerator]; while ((obj = [enumerator nextObject])) { if ([Imap4SystemFlags containsObject: [obj lowercaseString]]) objs[cnt] = [@"\\" stringByAppendingString:obj]; else objs[cnt] = obj; cnt++; } result = [NSArray arrayWithObjects:objs count:cnt]; if (objs != NULL) free(objs); return result; } static inline NSArray *_flags2ImapFlags(NGImap4Client *self, NSArray *_flags) { return [self _flags2ImapFlags:_flags]; } - (NSString *)_folder2ImapFolder:(NSString *)_folder { NSArray *array; NSString *folderName; if (self->delimiter == nil) { NSDictionary *res; res = [self list:@"" pattern:@""]; if (!_checkResult(self->context, res, __PRETTY_FUNCTION__)) return nil; } // array = [_folder pathComponents]; array = [_folder componentsSeparatedByString:@"/"]; if ([array count]) { NSString *o; o = [array objectAtIndex:0]; if ([o length] == 0) array = [array subarrayWithRange:NSMakeRange(1, [array count] - 1)]; if ([array count]) { o = [array lastObject]; if ([o length] == 0) array = [array subarrayWithRange:NSMakeRange(0, [array count] - 1)]; } } folderName = [array componentsJoinedByString:self->delimiter]; if (self->debug) { NSLog(@"IMAP folder made: %@ from %@ with separator: %@", folderName, _folder, self->delimiter); } return folderName; } - (NSString *)_imapFolder2Folder:(NSString *)_folder { NSArray *array; array = [NSArray arrayWithObject:@""]; if ([self delimiter] == nil) { NSDictionary *res; res = [self list:@"" pattern:@""]; // fill the delimiter ivar? if (!_checkResult(self->context, res, __PRETTY_FUNCTION__)) return nil; } if ([_folder hasPrefix: self->delimiter]) _folder = [_folder substringFromIndex: 1]; if ([_folder hasSuffix: self->delimiter]) _folder = [_folder substringToIndex: [_folder length] - 1]; array = [array arrayByAddingObjectsFromArray: [_folder componentsSeparatedByString:[self delimiter]]]; return [array componentsJoinedByString: @"/"]; } - (void)setContext:(NGImap4Context *)_ctx { self->context = _ctx; } - (NGImap4Context *)context { return self->context; } /* ConnectionRegistration */ - (void)removeFromConnectionRegister { unsigned cnt; for (cnt = 0; cnt < MaxImapClients; cnt++) { if (ImapClients[cnt] == self) ImapClients[cnt] = nil; } } - (void)registerConnection { int cnt; cnt = CountClient % MaxImapClients; if (ImapClients[cnt]) { [(NGImap4Context *)ImapClients[cnt] closeConnection]; } ImapClients[cnt] = self; CountClient++; } - (NGCTextStream *)textStream { if (self->text == nil) { if ([self->context lastException] == nil) [self reconnect]; } return (NGCTextStream *)self->text; } /* description */ - (NSString *)description { NSMutableString *ms; id tmp; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if (self->login != nil) [ms appendFormat:@" login=%@%s", self->login, self->password?"(pwd)":""]; if ((tmp = [self socket]) != nil) [ms appendFormat:@" socket=%@", tmp]; else if (self->address) [ms appendFormat:@" address=%@", self->address]; [ms appendString:@">"]; return ms; } @end /* NGImap4Client; */ SOPE/sope-mime/NGImap4/GNUmakefile.preamble0000644000000000000000000000154115004363604017256 0ustar rootroot# compilation settings SOPE_ROOT=../.. ADDITIONAL_CPPFLAGS += -Wall ifeq ($(PRECOMPILED_HEADERS),yes) ADDITIONAL_CPPFLAGS += -Winvalid-pch endif NGImap4_INCLUDE_DIRS += \ -I.. -I$(SOPE_ROOT) \ -I$(SOPE_ROOT)/sope-core/NGStreams/ \ -I$(SOPE_ROOT)/sope-core/NGExtensions/ \ -I$(SOPE_ROOT)/sope-core/ ifeq ($(frameworks),yes) NGImap4_LIBRARIES_DEPEND_UPON += \ -framework NGMime -framework NGMail \ -framework NGStreams -framework NGExtensions -framework EOControl \ -framework DOM -framework SaxObjC endif # library/framework search pathes DEP_DIRS = \ .. \ ../NGMail \ $(SOPE_ROOT)/sope-core/EOControl $(SOPE_ROOT)/sope-core/NGExtensions \ $(SOPE_ROOT)/sope-core/NGStreams \ $(SOPE_ROOT)/sope-xml/DOM $(SOPE_ROOT)/sope-xml/SaxObjC ifeq ($(frameworks),yes) ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir)) endif SOPE/sope-mime/NGImap4/NGImap4Client.h0000644000000000000000000001612615004363604016132 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SOPE_NGImap4_NGImap4Client_H__ #define __SOPE_NGImap4_NGImap4Client_H__ #import #include #include #include /* NGImap4Client An IMAP4 client object. This object is a thin wrapper around the TCP/IP socket (id object) connecting to the IMAP4 server. While it is pretty near to the IMAP4 raw protocol, it already does some normalization of responses. We might want to have something which is even lower level in the future. Responses are send to all registered response receivers. TODO: explain notification system. */ @class NSMutableArray, NSString, NSNumber, NSDictionary, NSArray, NSURL; @class EOGlobalID, EOQualifier; @class NGHashMap; @class NGImap4ResponseParser, NGImap4Client, NGImap4ResponseNormalizer; typedef enum { UnConnected_NGImap4State = 1, NonAuthenticated_NGImap4State, Authenticated_NGImap4State, Selected_NGImap4State, } NGImap4State; @interface NGImap4Client : NSObject { id socket; id previous_socket; id text; id address; NGImap4ResponseParser *parser; NGImap4ResponseNormalizer *normer; NSMutableArray *responseReceiver; BOOL loggedIn; BOOL useAuthenticate; BOOL isLogin; unsigned tagId; NSString *delimiter; NSString *selectedFolder; NSString *authname; NSString *login; NSString *password; NSString *authMechanism; NSMutableArray *enabledExtensions; BOOL debug; BOOL useSSL; BOOL useTLS; BOOL useUTF8; int tlsVerifyMode; NGImap4Context *context; /* not retained, used to store exceptions */ EOGlobalID *serverGID; } + (id)clientWithURL:(NSURL *)_url; + (id)clientWithAddress:(id)_address; + (id)clientWithHost:(id)_host; - (id)initWithURL:(NSURL *)_url; - (id)initWithHost:(id)_host; - (id)initWithAddress:(id)_address; /* equality */ - (BOOL)isEqualToClient:(NGImap4Client *)_obj; /* accessors */ - (id)socket; - (id)address; - (NSString *)delimiter; - (EOGlobalID *)serverGlobalID; - (NSString *)selectedFolderName; /* notifications */ - (void)registerForResponseNotification:(id)_obj; - (void)removeFromResponseNotification:(id)_obj; /* connection */ - (NSDictionary *)openConnection; - (void)closeConnection; - (NSNumber *)isConnected; - (void)reconnect; /* commands */ - (NSDictionary *)login:(NSString *)_login password:(NSString *)_passwd; - (NSDictionary *)authenticate:(NSString *)_login authname:(NSString *)_authname password:(NSString *)_passwd; - (NSDictionary *)authenticate:(NSString *)_login password:(NSString *)_passwd mechanism:(NSString *)_mech; - (NSDictionary *)logout; - (NSDictionary *)noop; - (NSDictionary *)capability; - (NSDictionary *)enable:(NSArray *)_extensions; - (NSDictionary *)namespace; - (NSDictionary *)list:(NSString *)_folder pattern:(NSString *)_pattern; - (NSDictionary *)lsub:(NSString *)_folder pattern:(NSString *)_pattern; - (NSDictionary *)select:(NSString *)_folder; - (NSDictionary *)unselect; - (NSDictionary *)status:(NSString *)_folder flags:(NSArray *)_flags; - (NSDictionary *)lstatus:(NSString *)_folder flags:(NSArray *)_flags; - (NSDictionary *)annotation:(NSString *)_folder entryName:(NSString *)_entry attributeName:(NSString *)_attribute; - (NSDictionary *)annotation:(NSString *)_folder entryName:(NSString *)_entry attributeName:(NSString *)_attribute attributeValue:(NSString *)_value; - (NSDictionary *)rename:(NSString *)_folder to:(NSString *)_newName; - (NSDictionary *)delete:(NSString *)_folder; - (NSDictionary *)create:(NSString *)_name; - (NSDictionary *)subscribe:(NSString *)_name; - (NSDictionary *)unsubscribe:(NSString *)_name; - (NSDictionary *)expunge; - (NSDictionary *)sort:(id)_sortOrderings qualifier:(EOQualifier *)_qual encoding:(NSString *)_encoding; - (NSDictionary *)fetchUids:(NSArray *)_uids parts:(NSArray *)_parts; - (NSDictionary *)fetchUid:(unsigned)_uid parts:(NSArray *)_parts; - (NSDictionary *) fetchModseqForUid: (unsigned)_uid; - (NSDictionary *)fetchVanished:(uint64_t)_modseq; - (NSDictionary *)fetchFrom:(unsigned)_from to:(unsigned)_to parts:(NSArray *)_parts; - (NSDictionary *)storeUid:(unsigned)_uid add:(NSNumber *)_add flags:(NSArray *)_flags; - (NSDictionary *)storeFrom:(unsigned)_from to:(unsigned)_to add:(NSNumber *)_add flags:(NSArray *)_flags; - (NSDictionary *)storeFlags:(NSArray *)_flags forUIDs:(id)_uids addOrRemove:(BOOL)_flag; - (NSDictionary *)copyUid:(unsigned)_uid toFolder:(NSString *)_folder; - (NSDictionary *)copyUids:(NSArray *)_uids toFolder:(NSString *)_folder; - (NSDictionary *)copyFrom:(unsigned)_from to:(unsigned)_to toFolder:(NSString *)_folder; - (NSDictionary *)moveUids:(NSArray *)_uids toFolder:(NSString *)_folder; - (NSDictionary *)append:(NSData *)_message toFolder:(NSString *)_folder withFlags:(NSArray *)_flags; - (NSDictionary *)threadBySubject:(BOOL)_bySubject charset:(NSString *)_charSet qualifier:(EOQualifier *)_qual; - (NSDictionary *)getQuotaRoot:(NSString *)_folder; - (NSDictionary *)searchWithQualifier:(EOQualifier *)_qualifier; /* ACLs */ - (NSDictionary *)getACL:(NSString *)_folder; - (NSDictionary *)setACL:(NSString *)_folder rights:(NSString *)_r uid:(NSString *)_uid; - (NSDictionary *)deleteACL:(NSString *)_folder uid:(NSString *)_uid; - (NSDictionary *)listRights:(NSString *)_folder uid:(NSString *)_uid; - (NSDictionary *)myRights:(NSString *)_folder; /* context accessors (DEPRECATED) */ - (void)setContext:(NGImap4Context *)_ctx; - (NGImap4Context *)context; /* raw methods */ - (NSDictionary *)primarySort:(NSString *)_sortString qualifierString:(NSString *)_qualString encoding:(NSString *)_encoding; /* Previously in Private category, but required by SoObjects/Mailer/SOGoMailBaseObject.m */ - (NGHashMap *)processCommand:(NSString *)_command; - (NGHashMap *)processCommand:(NSString *)_command withTag:(BOOL)_tag; - (NGHashMap *)processCommand:(NSString *)_command withTag:(BOOL)_tag withNotification:(BOOL)_notification; - (NGHashMap *)processCommand:(NSString *)_command logText:(NSString *)_txt; @end #endif /* __SOPE_NGImap4_NGImap4Client_H__ */ SOPE/sope-mime/NGImap4/NGImap4Context.h0000644000000000000000000001147315004363604016340 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __OGo_NGImap4_NGImap4Context_H__ #define __OGo_NGImap4_NGImap4Context_H__ #import #include /* NGImap4Context This object is a higher level client object build on top of the NGImap4Client object which represents the connection to the IMAP4 server and handles the raw IMAP4 processing. The NGImap4Context adds to that higher level functionality like caching of folders. */ @class NSDictionary, NGHashMap, NSMutableArray, NSURL, NSException; @class EOGlobalID; @class NGImap4Client, NGImap4Folder, NGImap4ServerRoot; @interface NGImap4Context : NSObject { NSDictionary *connectionDictionary; NSMutableArray *folderForRefresh; NGImap4Client *client; NGImap4Folder *selectedFolder; /* not retained */ NGImap4Folder *trashFolder; /* not retained */ NGImap4Folder *sentFolder; /* not retained */ NGImap4Folder *draftsFolder; /* not retained */ NGImap4Folder *inboxFolder; /* not retained */ NGImap4ServerRoot *serverRoot; /* not retained */ NSArray *capability; // TODO: array of what? NSString *sentFolderName; NSString *trashFolderName; NSString *draftsFolderName; NSString *serverName; NSString *serverKind; NSNumber *serverVersion; NSNumber *serverSubVersion; NSNumber *serverTag; BOOL syncMode; NSException *lastException; NSURL *url; int canSort; int canQuota; NSString *sortEncoding; int subscribeFolderFailed; int showOnlySubscribedInRoot; int showOnlySubscribedInSubFolders; } + (id)imap4ContextWithURL:(id)_url; + (id)imap4ContextWithConnectionDictionary:(NSDictionary *)_connection; - (id)initWithNSURL:(NSURL *)_url; - (id)initWithURL:(id)_url; - (id)initWithConnectionDictionary:(NSDictionary *)_connection; /* accessors */ - (NGImap4Client *)client; - (EOGlobalID *)serverGlobalID; - (NSURL *)url; /* folder tracking */ - (BOOL)isSelectedFolder:(NGImap4Folder *)_folder; - (BOOL)registerAsSelectedFolder:(NGImap4Folder *)_folder; - (BOOL)removeSelectedFolder:(NGImap4Folder *)_folder; - (BOOL)openConnection; - (BOOL)closeConnection; // NGImap4ResponseReceiver protocol - (void)responseNotificationFrom:(NGImap4Client *)_client response:(NSDictionary *)_dict; /* special folders */ - (id)trashFolder; - (id)sentFolder; - (id)draftsFolder; - (id)inboxFolder; - (id)serverRoot; - (void)setSentFolder:(NGImap4Folder *)_folder; - (void)setTrashFolder:(NGImap4Folder *)_folder; - (void)setDraftsFolder:(NGImap4Folder *)_folder; - (void)resetSpecialFolders; - (BOOL)hasNewMessages; /* returns all new messages from registered folder and inbox */ - (NSArray *)newMessages; // TODO: should be a datasource and/or qual instead! - (BOOL)registerForRefresh:(NGImap4Folder *)_folder; - (BOOL)removeFromRefresh:(NGImap4Folder *)_folder; - (BOOL)removeAllFromRefresh; - (BOOL)refreshFolder; - (NGImap4Folder *)folderWithName:(NSString *)_name; - (NGImap4Folder *)folderWithName:(NSString *)_name caseInsensitive:(BOOL)_b; - (BOOL)createFolderWithPath:(NSString *)_name; - (NSString *)host; - (NSString *)login; - (id)serverName; - (id)serverKind; - (id)serverVersion; - (id)serverSubVersion; - (id)serverTag; - (BOOL)isInSyncMode; - (void)enterSyncMode; - (void)leaveSyncMode; - (void)resetSync; - (void)setLastException:(NSException *)_exception; - (NSException *)lastException; - (void)resetLastException; /* server depending defaults */ - (BOOL)subscribeFolderFailed; - (BOOL)showOnlySubscribedInRoot; - (BOOL)showOnlySubscribedInSubFolders; - (NSString *)sortEncoding; - (void)setSortEncoding:(NSString *)_str; - (void)setSubscribeFolderFailed:(BOOL)_b; - (void)setShowOnlySubscribedInRoot:(BOOL)_b; - (void)setShowOnlySubscribedInSubFolders:(BOOL)_b; /* URL based factory */ + (id)messageWithURL:(id)_url; /* create context, then message */ - (id)messageWithURL:(id)_url; - (id)folderWithURL:(id)_url; @end @interface NGImap4Context(Capability) - (BOOL)canSort; - (BOOL)canQuota; @end /* NGImap4Context(Capability) */ #endif /* __OGo_NGImap4_NGImap4Context_H__ */ SOPE/sope-mime/README-OSX.txt0000644000000000000000000000064515004363604014370 0ustar rootrootPlease refer to ../README-OSX.txt for compilation directives. Building Notes ============== Prerequisites: - sope-xml - sope-core Prebinding Notes (DEPRECATED, for reference only) ================================================= sope-core: 0xC1000000 - 0xC2FFFFFF 0xC1600000 NGImap4 [not available with gstep-make] 0xC1800000 NGMail [not available with gstep-make] 0xC1A00000 NGMime [used as base in gstep-make] SOPE/sope-mime/GNUmakefile.preamble0000644000000000000000000000263015004363604016057 0ustar rootroot# compilation settings SOPE_ROOT=.. ADDITIONAL_CPPFLAGS += -DLIBRARY_MAJOR_VERSION=${MAJOR_VERSION} \ -DLIBRARY_MINOR_VERSION=${MINOR_VERSION} \ -DLIBRARY_SUBMINOR_VERSION=${SUBMINOR_VERSION} \ ADDITIONAL_CPPFLAGS += -Wall ifeq ($(PRECOMPILED_HEADERS),yes) ADDITIONAL_CPPFLAGS += -Winvalid-pch endif libNGMime_INCLUDE_DIRS += \ -I$(SOPE_ROOT) \ -I$(SOPE_ROOT)/sope-core/NGStreams/ \ -I$(SOPE_ROOT)/sope-core/NGExtensions/ libNGMime_LIBRARIES_DEPEND_UPON += \ -lNGStreams -lNGExtensions -lEOControl \ $(BASE_LIBS) NGMime_LIBRARIES_DEPEND_UPON += \ -framework NGStreams -framework NGExtensions -framework EOControl \ -framework DOM -framework SaxObjC # library/framework search pathes DEP_DIRS = \ $(SOPE_ROOT)/sope-core/EOControl $(SOPE_ROOT)/sope-core/NGExtensions \ $(SOPE_ROOT)/sope-core/NGStreams \ $(SOPE_ROOT)/sope-xml/DOM $(SOPE_ROOT)/sope-xml/SaxObjC ifneq ($(frameworks),yes) ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),\ -L$(GNUSTEP_BUILD_DIR)/$(dir)/$(GNUSTEP_OBJ_DIR_NAME)) else ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir)) endif ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) SYSTEM_LIB_DIR += -L/usr/local/lib64 -L/usr/lib64 else SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib endif # Apple ifeq ($(FOUNDATION_LIB),apple) libNGMime_PREBIND_ADDR="0xC1A00000" libNGMime_LDFLAGS += -seg1addr $(libNGMime_PREBIND_ADDR) endif SOPE/sope-mime/NGMime/0000755000000000000000000000000015004363604013332 5ustar rootrootSOPE/sope-mime/NGMime/NGPart.m0000644000000000000000000000461015004363604014644 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGPart.h" #include "NGMimeType.h" #include "common.h" #include @implementation NSData(DataPart) /* NGPart */ - (NSEnumerator *)valuesOfHeaderFieldWithName:(NSString *)_name { id value = nil; static NGMimeHeaderNames *Fields = NULL; if (!Fields) Fields = (NGMimeHeaderNames *)[NGMimePartParser headerFieldNames]; if ([_name isEqualToString:Fields->contentLength]) value = [NSNumber numberWithUnsignedInt:[self length]]; else if ([_name isEqualToString:Fields->contentType]) value = [self contentType]; else if ([_name isEqualToString:@"content-id"]) value = [self contentId]; else if ([_name isEqualToString:@"content-m5"]) value = [self contentMd5]; else if ([_name isEqualToString:@"content-language"]) value = [self contentLanguage]; if (value) return [[NSArray arrayWithObject:value] objectEnumerator]; return nil; } - (NSEnumerator *)headerFieldNames { return nil; } - (void)setBody:(id)_body { [self doesNotRecognizeSelector:_cmd]; } - (id)body { return self; } /* NGMimePart */ - (NGMimeType *)contentType { static NGMimeType *defType = nil; if (defType == nil) defType = [[NGMimeType mimeType:@"application/octet-stream"] retain]; return defType; } - (NSString *)contentId { return nil; } - (NSArray *)contentLanguage { return nil; } - (NSString *)contentMd5 { return nil; } - (NSString *)encoding { return nil; } @end /* NSData(DataPart) */ @implementation NSMutableData(DataPart) - (void)setBody:(id)_body { [self setData:_body]; } @end /* NSMutableData(DataPart) */ void __link_NGPart(void) { __link_NGPart(); } SOPE/sope-mime/NGMime/NGMimeAddressHeaderFieldGenerator.m0000644000000000000000000001245715004363604022067 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeHeaderFieldGenerator.h" #include "NGMimeHeaderFields.h" #include #include #include "common.h" #include #if MOVED_TO_NGMAIL # include #else @interface NSObject(MailAddressParser) + (id)mailAddressParserWithString:(NSString *)_string; + (id)mailAddressParserWithData:(NSData *)_data; - (id)parseAddressList; @end #endif @interface NSObject(UsedProtocols) - (NSString *)displayName; // hh: where is that implemented ? @end @implementation NGMimeAddressHeaderFieldGenerator static int UseLFSeperatedAddressEntries = -1; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; if (UseLFSeperatedAddressEntries == -1) { id o; if ((o = [ud objectForKey:@"UseLFSeperatedAddressEntries"])) UseLFSeperatedAddressEntries = [o boolValue]?1:0; else UseLFSeperatedAddressEntries = 1; } } /* operation */ - (NSData *)generateDataForHeaderFieldNamed:(NSString *)_headerField value:(id)_value { // TODO: produces a reference to NGMailAddressParser which is in NGMail! #if MOVED_TO_NGMAIL NGMailAddressParser *parser; #else id parser; #endif NSMutableString *result; NSData *data; NGMailAddress *address; NSEnumerator *enumerator; #if MOVED_TO_NGMAIL parser = ([_value isKindOfClass:[NSString class]]) ? [NGMailAddressParser mailAddressParserWithString:_value] : [NGMailAddressParser mailAddressParserWithData:_value]; #else parser = ([_value isKindOfClass:[NSString class]]) ? [NSClassFromString(@"NGMailAddressParser") mailAddressParserWithString:_value] : [NSClassFromString(@"NGMailAddressParser") mailAddressParserWithData:_value]; #endif enumerator = [[parser parseAddressList] objectEnumerator]; result = [[NSMutableString alloc] initWithCapacity:128]; while ((address = [enumerator nextObject]) != nil) { NSString *tmp; char *buffer; unsigned bufLen; BOOL doEnc; if ([result length] > 0) { if (UseLFSeperatedAddressEntries == 1) [result appendString:@",\n "]; else [result appendString:@", "]; } tmp = [address displayName]; doEnc = NGEncodeQuotedPrintableMimeNeeded((unsigned char *)[tmp UTF8String], [tmp length]); buffer = NULL; if (doEnc) { /* FIXME - better use UTF8 encoding! */ #if NeXT_Foundation_LIBRARY unsigned char iso[] = "=?iso-8859-15?q?"; unsigned isoLen = 16; #else unsigned char iso[] = "=?utf-8?q?"; unsigned isoLen = 10; #endif unsigned char isoEnd[] = "?="; unsigned isoEndLen = 2; unsigned desLen; unsigned char *des; { NSData *data; #if NeXT_Foundation_LIBRARY data = [tmp dataUsingEncoding:NSISOLatin1StringEncoding]; #else data = [tmp dataUsingEncoding:NSUTF8StringEncoding]; #endif bufLen = [data length]; buffer = malloc(bufLen + 10); [data getBytes:buffer]; buffer[bufLen] = '\0'; } desLen = bufLen * 3 + 20; des = calloc(desLen + 10, sizeof(char)); memcpy(des, iso, isoLen); memcpy(des + isoLen, buffer, bufLen); desLen = NGEncodeQuotedPrintableMime((unsigned char *)buffer, bufLen, des + isoLen, desLen - isoLen); if ((int)desLen != -1) { memcpy(des + isoLen + desLen, isoEnd, isoEndLen); tmp = [[NSString alloc] initWithData: [NSData dataWithBytes:(char *)des length:(isoLen + desLen + isoEndLen)] encoding: NSISOLatin1StringEncoding]; [tmp autorelease]; } else { [self warnWithFormat: @"%s:%i: An error occour during quoted-printable decoding", __PRETTY_FUNCTION__, __LINE__]; } if (des) free(des); } if (buffer) free(buffer); buffer = NULL; if ([tmp length] > 0) { /* do not place encoded strings in quotes [RFC 2045, RFC 2047, RFC 2822] */ if (!doEnc) [result appendString:@"\""]; [result appendString:tmp]; if (!doEnc) [result appendString:@"\""]; if ((tmp = [(NSHost *)address address])) { [result appendString:@" <"]; [result appendString:tmp]; [result appendString:@">"]; } } else if ((tmp = [(NSHost *)address address])) { [result appendString:tmp]; } } data = [result dataUsingEncoding:NSISOLatin1StringEncoding]; [result release]; return data; } @end /* NGMimeAddressHeaderFieldGenerator */ SOPE/sope-mime/NGMime/NGMimeHeaderFieldGenerator.m0000644000000000000000000002140415004363604020551 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeHeaderFieldGenerator.h" #include "NGMimeHeaderFields.h" #include "common.h" static BOOL isPrintable(char ch) { // match printable ASCII-characters according to https://tools.ietf.org/html/rfc2047#section-4.2 return ch >= 32 && ch < 127 && ch != '=' && ch != '?' && ch != '_' && ch != '.' && ch != ',' && ch != ';' && ch != ':' && ch != '@' && ch != '"'; } @implementation NGMimeHeaderFieldGenerator + (id)headerFieldGenerator { return [[[self alloc] init] autorelease]; } #define MAX_LENGTH_QP_ENCODED 75 #define QP_ENCODE_PREFIX "=?utf-8?q?" #define QP_ENCODE_SUFFIX "?=" /* Encodes a string into q-printable format (RFC-2047): * hello world: =?utf-8?q?hello_world?= * hëllö: =?utf-8?q?h=C3=ABll=C3=B6=?= */ + (NSString *)encodeQuotedPrintableWord:(NSString *)word { NSString *prefix = @QP_ENCODE_PREFIX; NSString *suffix = @QP_ENCODE_SUFFIX; NSUInteger max_length = 3 * [word lengthOfBytesUsingEncoding: NSUTF8StringEncoding]; unsigned char *qencoded = calloc(max_length + 1, sizeof(char)); if (!qencoded) return nil; NSData *word_data = [word dataUsingEncoding: NSUTF8StringEncoding]; int ret = NGEncodeQuotedPrintableMime ([word_data bytes], [word_data length], qencoded, max_length); if (ret == -1) { free(qencoded); return nil; } NSString *result = [NSString stringWithFormat:@"%@%s%@", prefix, qencoded, suffix]; free(qencoded); return result; } /* According to RFC 2047 an encoded word may not be more than 75 characters long, this method split the given string into several chunks that won't be longer than 75 characters long after being qp encoded */ static NSArray *splitWordIfQPEncodingTooBig(NSString *s) { NSUInteger max_length = MAX_LENGTH_QP_ENCODED - strlen(QP_ENCODE_PREFIX) - strlen(QP_ENCODE_SUFFIX); // First, quick way for short words (most of the times) if (3 * [s lengthOfBytesUsingEncoding: NSUTF8StringEncoding] < max_length) return [NSArray arrayWithObjects: s, nil]; NSData *data = [s dataUsingEncoding: NSUTF8StringEncoding]; NSUInteger size = [data length]; const unsigned char *bytes = [data bytes]; NSMutableArray *chunks = [NSMutableArray array]; NSUInteger i, chunk_size = 0, chunk_start = 0; for (i = 0; i < size; i++) { if (!isPrintable(bytes[i])) chunk_size += 3; else chunk_size++; if (chunk_size > max_length) { // This part is tricky because utf8 characters can have 1..4 bytes to // encode the full character NSData *subdata = [data subdataWithRange: NSMakeRange(chunk_start, i-1-chunk_start)]; NSString *chunk_string = [[NSString alloc] initWithBytes: [subdata bytes] length: [subdata length] encoding: NSUTF8StringEncoding]; if (chunk_string) { // Ok, we made the chunk just at the end of a full character chunk_start = i-1; } else { // Let's make the chunk shorted until we can create an ok utf8 string // This means we have a partial codepoint not forming a full character NSUInteger backtrack; for (backtrack = 1; !chunk_string && backtrack <= 3; backtrack++) { subdata = [data subdataWithRange: NSMakeRange(chunk_start, i-1-chunk_start-backtrack)]; chunk_string = [[NSString alloc] initWithBytes: [subdata bytes] length: [subdata length] encoding: NSUTF8StringEncoding]; } chunk_start = i-backtrack; } [chunk_string autorelease]; [chunks addObject: chunk_string]; chunk_size = 0; } } // The last chunk should be ok, because we are ending the string so no // partial codepoints at the end of the chunk NSData *subdata = [data subdataWithRange: NSMakeRange(chunk_start, size-chunk_start)]; NSString *chunk_string = [[NSString alloc] initWithBytes: [subdata bytes] length: [subdata length] encoding: NSUTF8StringEncoding]; [chunk_string autorelease]; [chunks addObject: chunk_string]; return chunks; } /* Encodes given string into q-printable format (RFC-2047). It takes into account that text could be a long string and adds CRLF SPACE to split into lines no longer than 75 characters long. */ + (NSString *)encodeQuotedPrintableText:(NSString *)input { NSMutableString *line, *text; NSString *word, *part; NSArray *words; BOOL encodedLastWord, needsEncode; NSUInteger spaces; int i, j; words = [input componentsSeparatedByString: @" "]; text = [NSMutableString string]; line = [NSMutableString string]; encodedLastWord = needsEncode = NO; spaces = 0; for (i = 0; i < [words count]; i++) { word = [words objectAtIndex: i]; // Count number of spaces from the previous encoded word if ([line length] > 0 || [word length] == 0) spaces++; // If word is empty means we had a space (which we've already counted it) if ([word length] == 0) continue; NSData *data = [word dataUsingEncoding: NSUTF8StringEncoding]; needsEncode = NGEncodeQuotedPrintableMimeNeeded ([data bytes], [data length]); NSArray *parts = splitWordIfQPEncodingTooBig(word); for (j = 0; j < [parts count]; j++) { part = [parts objectAtIndex: j]; NSString *encoded = part; if (needsEncode) { NSMutableString *toEncode = [part mutableCopy]; if (encodedLastWord) { // Add spaces between words. As both words are encoded we need to // also encode those spaces, because whitespace between encoded words // will be ignored for decoders NSUInteger n; for (n = 0; n < spaces; n++) [toEncode insertString: @" " atIndex: 0]; spaces = 0; } encoded = [[self class] encodeQuotedPrintableWord: toEncode]; } // Insert pending spaces from last word. Normally it will be 1 or // 0 in case needsEncode && encodedLastWord (becase the spaces are // already in `encoded` string) NSUInteger n; for (n = 0; n < spaces; n++) [line appendString: @" "]; spaces = 0; if ([line length] + [encoded length] <= MAX_LENGTH_QP_ENCODED) { [line appendString: encoded]; } else { if ([text length] > 0) [text appendString: @"\n "]; [text appendString: line]; line = [NSMutableString stringWithString: encoded]; } } encodedLastWord = needsEncode; } // Add last line to result. Add \n and spaces if needed if ([text length] > 0) [text appendString: @"\n "]; NSUInteger n; for (n = 0; n < spaces; n++) [line appendString: @" "]; [text appendString: line]; return text; } - (NSData *)generateDataForHeaderFieldNamed:(NSString *)_headerField value:(id)_value { [self subclassResponsibility:_cmd]; return nil; } @end /* NGMimeHeaderFieldGenerator */ BOOL NGEncodeQuotedPrintableMimeNeeded(const unsigned char *src, unsigned srcLen) { unsigned i = 0; for (i = 0; i < srcLen; i++) { if (!isPrintable(src[i])) { return YES; } } return NO; } int NGEncodeQuotedPrintableMime(const unsigned char *src, unsigned srcLen, unsigned char *dest, unsigned destLen) { unsigned cnt = 0; unsigned destCnt = 0; unsigned char hexT[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; if (srcLen > destLen) return -1; for (cnt = 0; cnt < srcLen && destCnt < destLen; cnt++) { register unsigned char c = src[cnt]; if (isPrintable(c)) { // no quoting dest[destCnt++] = (c == ' ') ? '_' : c; } else { // need to be quoted if (destLen - destCnt <= 2) break; dest[destCnt++] = '='; dest[destCnt++] = hexT[(c >> 4) & 15]; dest[destCnt++] = hexT[c & 15]; } } if (cnt < srcLen) return -1; return destCnt; } SOPE/sope-mime/NGMime/NGMimeContentTypeHeaderFieldGenerator.m0000644000000000000000000000712015004363604022745 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeHeaderFieldGenerator.h" #include "NGMimeHeaderFields.h" #include "common.h" #include @implementation NGMimeContentTypeHeaderFieldGenerator - (NSData *)generateDataForHeaderFieldNamed:(NSString *)_headerField value:(id)_value { NGMimeType *type = nil; // only one content-type field NSString *tmp = nil; NSMutableData *data = nil; NSData *valueData; type = _value; if (type == nil) { NSLog(@"WARNING(%s): empty content type field", __PRETTY_FUNCTION__); return [NSData dataWithBytes:"application/octet-stream" length:24]; } if ([_value isKindOfClass:[NSString class]]) { return [_value dataUsingEncoding:NSUTF8StringEncoding]; } if (![type isKindOfClass:[NGMimeType class]]) { NSLog(@"WARNING(%s): invalid MIME type value (%@) !", __PRETTY_FUNCTION__, type); return [NSData dataWithBytes:"application/octet" length:24]; } data = [NSMutableData dataWithCapacity:64]; tmp = [type type]; NSAssert(tmp, @"type should not be nil"); valueData = [tmp dataUsingEncoding: NSISOLatin1StringEncoding]; [data appendData: valueData]; [data appendBytes:"/" length:1]; tmp = [type subType]; if (tmp != nil) { valueData = [tmp dataUsingEncoding: NSISOLatin1StringEncoding]; [data appendData:valueData]; } else [data appendBytes:"*" length:1]; { // parameters NSEnumerator *enumerator = [type parameterNames]; NSString *name = nil; NSString *value = nil; while ((name = [enumerator nextObject])) { value = [type valueOfParameter:name]; if (![value isKindOfClass:[NSString class]]) { NSLog(@"ERROR[%s]: parameter should be a NSString headerField: %@ " @"value %@", __PRETTY_FUNCTION__, _headerField, _value); continue; } [data appendBytes:"; " length:2]; valueData = [name dataUsingEncoding: NSUTF8StringEncoding]; [data appendData: valueData]; /* this confuses GroupWise: "= \"" (a space) */ [data appendBytes:"=\"" length:2]; /* check for encoding */ { unsigned cnt, max; const char *dataBytes; BOOL doEnc; valueData = [value dataUsingEncoding:NSUTF8StringEncoding]; dataBytes = [valueData bytes]; max = [valueData length]; doEnc = NO; cnt = 0; while (!doEnc && cnt < max) { if ((unsigned char)dataBytes[cnt] > 127) doEnc = YES; else cnt++; } if (doEnc) { [data appendBytes:"=?utf-8?q?" length:10]; [data appendData: [valueData dataByEncodingQuotedPrintable]]; [data appendBytes:"?=" length:2]; } else { [data appendData: valueData]; } } [data appendBytes:"\"" length:1]; } } return data; } @end /* NGMimeContentTypeHeaderFieldGenerator */ SOPE/sope-mime/NGMime/NGMimeMultipartBody.m0000644000000000000000000000731315004363604017350 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeMultipartBody.h" #include "NGMimeBodyParser.h" #include "common.h" @implementation NGMimeMultipartBody - (id)initWithPart:(id)_part { if ((self = [super init])) { self->flags.isParsed = YES; } return self; } - (id)initWithPart:(id)_part data:(NSData *)_data delegate:(id)_del { if ((self = [self initWithPart:_part])) { self->flags.isParsed = NO; self->rawData = [_data retain]; self->delegate = _del; } return self; } - (id)init { return [self initWithPart:nil]; } - (void)dealloc { [self->rawData release]; [self->prefix release]; [self->suffix release]; [self->bodyParts release]; [super dealloc]; } /* parsing */ - (void)parse { NGMimeMultipartBodyParser *parser = [[NGMimeMultipartBodyParser alloc] init]; self->flags.isParsed = YES; if (![parser parseBody: self ofMultipart:self->part data: self->rawData delegate: self->delegate]) NSLog(@"%@: error during parsing of multipart body (ignored)", self); self->delegate = nil; [parser release]; parser = nil; } static inline void _checkParse(NGMimeMultipartBody *self) { if (!self->flags.isParsed) [self parse]; } static inline void _checkArray(NGMimeMultipartBody *self) { if (!self->flags.isParsed) [self parse]; if (self->bodyParts == nil) self->bodyParts = [[NSMutableArray alloc] init]; } /* accessors */ - (id)part { // the part the body belongs to return self->part; } - (NSArray *)parts { return self->bodyParts; } - (void)addBodyPart:(id)_part { _checkArray(self); [self->bodyParts addObject:_part]; } - (void)addBodyPart:(id)_part atIndex:(int)_idx { _checkArray(self); [self->bodyParts insertObject:_part atIndex:_idx]; } - (void)removeBodyPart:(id)_part { _checkArray(self); [self->bodyParts removeObject:_part]; } - (void)removeBodyPartAtIndex:(int)_idx { _checkArray(self); [self->bodyParts removeObjectAtIndex:_idx]; } - (void)setPrefix:(NSString *)_prefix { if (self->prefix != _prefix) { [self->prefix release]; self->prefix = [_prefix copy]; } } - (NSString *)prefix { return self->prefix; } - (void)setSuffix:(NSString *)_suffix { if (self->suffix != _suffix) { [self->suffix release]; self->suffix = [_suffix copy]; } } - (NSString *)suffix { return self->suffix; } /* description */ - (NSString *)description { NSMutableString *d = [NSMutableString stringWithCapacity:64]; [d appendFormat:@"<%@[0x%p]:", NSStringFromClass([self class]), self]; if (self->flags.isParsed) { if (self->prefix) [d appendFormat:@" prefix=%@", self->prefix]; if (self->suffix) [d appendFormat:@" suffix=%@", self->suffix]; if (self->bodyParts) [d appendFormat:@" parts=%@", self->bodyParts]; } if (self->rawData) [d appendFormat:@" data=%@", self->rawData]; [d appendString:@">"]; return d; } @end /* NGMimeMultipartBody */ SOPE/sope-mime/NGMime/NGMimeBodyPartParser.m0000644000000000000000000000234715004363604017454 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeBodyPartParser.h" #include "NGMimeBodyPart.h" #include "common.h" @implementation NGMimeBodyPartParser - (NGMimeType *)defaultContentTypeForPart:(id)_part { return [NGMimeType mimeType:@"text/plain"]; } - (id)producePartWithHeader:(NGHashMap *)_header { return [NGMimeBodyPart bodyPartWithHeader:_header]; } - (void)parseBodyOfPart:(id)_part { [super parseBodyOfPart:_part]; } @end /* NGMimeBodyPartParser */ SOPE/sope-mime/NGMime/NGPart.h0000644000000000000000000000326515004363604014644 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGPart_H__ #define __NGMime_NGPart_H__ #import #import /* NGPart / NGMimePart Represents a MIME part, that is, a data block with associated header fields. */ @class NSEnumerator, NSString, NSArray; @class NGMimeType; @protocol NGPart < NSObject > - (NSEnumerator *)valuesOfHeaderFieldWithName:(NSString *)_name; - (NSEnumerator *)headerFieldNames; - (void)setBody:(id)_body; - (id)body; @end @protocol NGMimePart < NGPart > - (NGMimeType *)contentType; // the content-type - (NSString *)contentId; // get the Content-ID of this part - (NSArray *)contentLanguage; // get the language tags from Content-Language - (NSString *)contentMd5; // get the Content-MD5 digest of this part - (NSString *)encoding; // get the transfer encoding of this part @end @interface NSData(DataPart) < NGMimePart > @end #endif /* __NGMime_NGPart_H__ */ SOPE/sope-mime/NGMime/NGConcreteMimeType.m0000644000000000000000000005015415004363604017156 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGConcreteMimeType.h" #include "common.h" @implementation NGParameterMimeType - (id)initWithType:(NSString *)_type subType:(NSString *)_subType parameters:(NSDictionary *)_parameters { self->subType = [_subType copy]; self->parameters = [_parameters copy]; return self; } - (void)dealloc { [self->subType release]; [self->parameters release]; [super dealloc]; } /* types */ - (NSString *)type { [self subclassResponsibility:_cmd]; return nil; } - (NSString *)subType { return self->subType; } - (BOOL)isCompositeType { return NO; } /* parameters */ - (NSEnumerator *)parameterNames { return [self->parameters keyEnumerator]; } - (id)valueOfParameter:(NSString *)_parameterName { return [self->parameters objectForKey:_parameterName]; } /* representations */ - (NSDictionary *)parametersAsDictionary { return self->parameters; } - (NSString *)stringValue { NSMutableString *str = [NSMutableString stringWithCapacity:20]; NSString *paras; [str appendString:[self type]]; [str appendString:@"/"]; [str appendString:[self subType]]; paras = [self parametersAsString]; if (paras) [str appendString:paras]; return str; } @end /* NGParameterMimeType */ @implementation NGConcreteTextMimeType static NGConcreteTextMimeType *textPlainNoCharset = nil; + (void)initialize { BOOL isInitialized = NO; if (isInitialized) return; isInitialized = YES; textPlainNoCharset = [[NGConcreteTextMimeType alloc] initWithType:NGMimeTypeText subType:@"plain" parameters:nil]; } - (id)initWithType:(NSString *)_type subType:(NSString *)_subType parameters:(NSDictionary *)_parameters { NSAssert([_type isEqualToString:NGMimeTypeText], @"invalid use of concrete subclass .."); if (textPlainNoCharset) { if (_parameters == nil) { if ([_subType isEqualToString:@"plain"]) { [self release]; return [textPlainNoCharset retain]; // init returns retained objects ! } } } delsp = NO; subType = [_subType copy]; NSAssert(subType, @"subtype may not be nil"); { NSEnumerator *keys; NSString *key; keys = [_parameters keyEnumerator]; while ((key = [keys nextObject]) != nil) { NSAssert([key isKindOfClass:[NSString class]], @"parameter name has to be a NSString"); if ([key isEqualToString:NGMimeParameterTextCharset]) { id tc = [[_parameters objectForKey:key] lowercaseString]; ASSIGN(self->charset, tc); tc = nil; } else if ([key isEqualToString:@"name"]) { [self->name release]; self->name = nil; self->name = [[_parameters objectForKey:key] copy]; } else if ([key isEqualToString:@"q"]) { id v; if ((v = [_parameters objectForKey:key])) self->quality = [v floatValue]; else self->quality = 1.0; } else if ([key isEqualToString:@"format"]) { [self->format release]; self->format = nil; self->format = [[_parameters objectForKey:key] copy]; } else if ([key isEqualToString:@"method"]) { [self->method release]; self->method = nil; self->method = [[_parameters objectForKey:key] copy]; } else if ([key isEqualToString:@"reply-type"]) { [self->replyType release]; self->replyType = nil; self->replyType = [[_parameters objectForKey:key] copy]; } else if ([key isEqualToString:@"delsp"]) { self->delsp = [[_parameters objectForKey:key] boolValue]; } else { // TODO: how do we want to deal with extra parameters? BOOL printWarn = YES; if ([key hasPrefix:@"x-"]) { if ([key hasPrefix:@"x-mac"]) printWarn = NO; else if ([key hasPrefix:@"x-unix-mode"]) printWarn = NO; else if ([key hasPrefix:@"x-avg-checked"]) // eg: 'x-avg-checked: avg-ok-12CD4A13' printWarn = NO; } if (printWarn) { NSLog(@"MimeType 'text/*' does not support a parameter named " @"'%@' with value '%@'", key, [_parameters objectForKey:key]); } } } } NSAssert(self, @"self is nil !"); return self; } - (void)dealloc { [self->replyType release]; [self->method release]; [self->format release]; [self->name release]; [self->subType release]; [self->charset release]; [super dealloc]; } /* type */ - (NSString *)type { return NGMimeTypeText; } - (NSString *)subType { return self->subType; } - (BOOL)isCompositeType { return NO; } /* comparing types */ - (BOOL)isEqualToMimeType:(NGMimeType *)_type { NSDictionary *paras = nil; if (_type == nil) return NO; if (_type == self) return YES; if (![self hasSameType:_type]) return NO; paras = [_type parametersAsDictionary]; switch ([paras count]) { case 0: if (self->charset) return NO; break; case 1: { id ocs = nil; if (self->charset == nil) return NO; ocs = [paras objectForKey:NGMimeParameterTextCharset]; if (ocs == nil) return NO; if (![ocs isEqual:self->charset]) return NO; break; } case 2: { id ocs = nil; if (self->charset == nil) return NO; if (self->name == nil) return NO; ocs = [paras objectForKey:NGMimeParameterTextCharset]; if (ocs == nil) return NO; if (![ocs isEqual:self->charset]) return NO; ocs = [paras objectForKey:@"name"]; if (ocs == nil) return NO; if (![ocs isEqual:self->name]) return NO; break; } case 3: { id ocs = nil; if (self->charset == nil) return NO; if (self->name == nil) return NO; if (self->format == nil) return NO; ocs = [paras objectForKey:NGMimeParameterTextCharset]; if (ocs == nil) return NO; if (![ocs isEqual:self->charset]) return NO; ocs = [paras objectForKey:@"name"]; if (ocs == nil) return NO; if (![ocs isEqual:self->name]) return NO; ocs = [paras objectForKey:@"format"]; if (ocs == nil) return NO; if (![ocs isEqual:self->format]) return NO; break; } default: return NO; } return YES; } - (BOOL)hasSameGeneralType:(NGMimeType *)_other { // only the 'type' must match if (_other == nil) return NO; if (_other == self) return YES; if ([_other isCompositeType]) return NO; if (![[_other type] isEqualToString:NGMimeTypeText]) return NO; return YES; } - (BOOL)hasSameType:(NGMimeType *)_other { // parameters need not match if (_other == nil) return NO; if (_other == self) return YES; if ([_other isCompositeType]) return NO; if (![[_other type] isEqualToString:NGMimeTypeText]) return NO; if (![[_other subType] isEqualToString:self->subType]) return NO; return YES; } - (BOOL)doesMatchType:(NGMimeType *)_other { // interpretes wildcards NSString *ot = [_other type]; NSString *ost = [_other subType]; if ([ot isEqualToString:@"*"]) ot = NGMimeTypeText; if (![NGMimeTypeText isEqualToString:ot]) return NO; if ([ost isEqualToString:@"*"]) ost = self->subType; if (![self->subType isEqualToString:ost]) return NO; return YES; } /* parameters */ - (NSString *)characterSet { return self->charset; } - (NSString *)name { return self->name; } - (NSString *)format { return self->format; } - (NSString *)method { return self->method; } - (NSString *)replyType { return self->replyType; } - (float)quality { return self->quality; } - (BOOL)delsp { return self->delsp; } - (NSEnumerator *)parameterNames { id args[6]; int argCount = 0; if (self->charset) { args[argCount] = NGMimeParameterTextCharset; argCount++; } if (self->name) { args[argCount] = @"name"; argCount++; } if (self->format) { args[argCount] = @"format"; argCount++; } if (self->method) { args[argCount] = @"method"; argCount++; } if (self->replyType) { args[argCount] = @"reply-type"; argCount++; } if (argCount == 0) return nil; return [[NSArray arrayWithObjects:args count:argCount] objectEnumerator]; } - (id)valueOfParameter:(NSString *)_parameterName { if ([_parameterName isEqualToString:NGMimeParameterTextCharset]) return self->charset; if ([_parameterName isEqualToString:@"name"]) return self->name; if ([_parameterName isEqualToString:@"format"]) return self->format; if ([_parameterName isEqualToString:@"method"]) return self->method; if ([_parameterName isEqualToString:@"reply-type"]) return self->replyType; return nil; } /* representations */ - (NSDictionary *)parametersAsDictionary { NSMutableDictionary *d; d = [NSMutableDictionary dictionaryWithCapacity:4]; if (self->charset) [d setObject:self->charset forKey:NGMimeParameterTextCharset]; if (self->name) [d setObject:self->name forKey:@"name"]; if (self->format) [d setObject:self->format forKey:@"format"]; if (self->method) [d setObject:self->method forKey:@"method"]; if (self->replyType) [d setObject:self->replyType forKey:@"reply-type"]; return d; } - (NSString *)stringValue { NSMutableString *str; str = [NSMutableString stringWithCapacity:20]; [str appendString:NGMimeTypeText]; [str appendString:@"/"]; [str appendString:self->subType]; if (self->charset) { [str appendString:@"; "]; [str appendString:NGMimeParameterTextCharset]; [str appendString:@"="]; [str appendString:self->charset]; } if (self->name) { [str appendString:@"; name="]; [str appendString:self->name]; } if (self->format) { [str appendString:@"; format="]; [str appendString:self->format]; } if (self->method) { [str appendString:@"; method="]; [str appendString:self->method]; } if (self->replyType) { [str appendString:@"; reply-type="]; [str appendString:self->replyType]; } return str; } @end /* NGConcreteTextMimeType */ @implementation NGConcreteTextVcardMimeType @end /* NGConcreteTextVcardMimeType */ // application type @implementation NGConcreteApplicationMimeType - (NSString *)type { return NGMimeTypeApplication; } - (BOOL)isCompositeType { return NO; } @end /* NGConcreteApplicationMimeType */ @implementation NGConcreteAppOctetMimeType - (id)initWithType:(NSString *)_type subType:(NSString *)_subType parameters:(NSDictionary *)_parameters { NSEnumerator *keys = [_parameters keyEnumerator]; NSString *key = nil; while ((key = [keys nextObject])) { NSAssert([key isKindOfClass:[NSString class]], @"parameter name has to be a NSString"); if ([key isEqualToString:@"type"]) self->type = [[_parameters objectForKey:@"type"] retain]; else if ([key isEqualToString:@"padding"]) self->padding = [[_parameters objectForKey:@"padding"] unsignedIntValue]; else if ([key isEqualToString:@"conversions"]) self->conversions = [[_parameters objectForKey:@"conversions"] retain]; else if ([key isEqualToString:@"name"]) self->name = [[_parameters objectForKey:@"name"] copy]; else { if (![key hasPrefix:@"x-mac"]) { NSLog(@"MimeType 'application/*' does not support a parameter" @" named '%@'", key); } } } return self; } - (void)dealloc { [self->type release]; [self->conversions release]; [self->name release]; [super dealloc]; } /* accessors */ - (NSString *)type { return NGMimeTypeApplication; } - (NSString *)subType { return @"octet"; } - (BOOL)isCompositeType { return NO; } /* parameters */ - (NSString *)typeDescription { return self->type; } - (NSEnumerator *)parameterNames { NSMutableArray *array = [NSMutableArray arrayWithCapacity:5]; if (self->type) [array addObject:@"type"]; if (self->padding) [array addObject:@"padding"]; if (self->conversions) [array addObject:@"conversions"]; if (self->name) [array addObject:@"name"]; return [array isNotEmpty] ? [array objectEnumerator] : (NSEnumerator *)nil; } - (id)valueOfParameter:(NSString *)_parameterName { if ([_parameterName isEqualToString:@"type"]) return self->type; if ([_parameterName isEqualToString:@"padding"]) return [NSNumber numberWithUnsignedInt:self->padding]; if ([_parameterName isEqualToString:@"conversions"]) return self->conversions; if ([_parameterName isEqualToString:@"name"]) return self->name; return nil; } - (NSString *)stringValue { NSMutableString *str; NSString *paras; str = [NSMutableString stringWithCapacity:20]; [str appendString:NGMimeTypeApplication]; [str appendString:@"/"]; [str appendString:@"octet"]; paras = [self parametersAsString]; if (paras != nil) [str appendString:paras]; return str; } @end /* NGConcreteAppOctetMimeType */ /* other types */ @implementation NGConcreteImageMimeType - (NSString *)type { return NGMimeTypeImage; } // description - (NSString *)stringValue { return [@"image/" stringByAppendingString:[self subType]]; } @end /* NGConcreteImageMimeType */ @implementation NGConcreteAudioMimeType - (NSString *)type { return NGMimeTypeAudio; } // description - (NSString *)stringValue { return [@"audio/" stringByAppendingString:[self subType]]; } @end /* NGConcreteAudioMimeType */ @implementation NGConcreteVideoMimeType - (NSString *)type { return NGMimeTypeVideo; } // description - (NSString *)stringValue { return [@"video/" stringByAppendingString:[self subType]]; } @end /* NGConcreteVideoMimeType */ @implementation NGConcreteMultipartMimeType - (NSString *)type { return NGMimeTypeMultipart; } - (BOOL)isCompositeType { return YES; } @end /* NGConcreteMultipartMimeType */ @implementation NGConcreteMessageMimeType - (NSString *)type { return NGMimeTypeMessage; } - (BOOL)isCompositeType { return NO; } @end /* NGConcreteMessageMimeType */ // generic mime type @implementation NGConcreteGenericMimeType - (id)initWithType:(NSString *)_type subType:(NSString *)_subType parameters:(NSDictionary *)_parameters { self->type = [_type retain]; self->subType = [_subType copy]; self->parameters = [_parameters retain]; return self; } - (void)dealloc { [self->type release]; [self->subType release]; [self->parameters release]; [super dealloc]; } /* accessors */ - (NSString *)type { return self->type; } - (NSString *)subType { return self->subType; } - (BOOL)isCompositeType { return NO; } /* comparing types */ - (BOOL)isEqualToMimeType:(NGMimeType *)_type { id p; if (_type == nil) return NO; if (_type == self) return YES; if (![self hasSameType:_type]) return NO; p = [_type parametersAsDictionary]; if ((p == nil) && (self->parameters == nil)) return YES; if (![p isNotEmpty] && ![self->parameters isNotEmpty]) return YES; if ((p == nil) || (self->parameters == nil)) return NO; if (![p isEqual:self->parameters]) return NO; return YES; } - (BOOL)hasSameGeneralType:(NGMimeType *)_other { // only the 'type' must match if (_other == nil) return NO; if (_other == self) return YES; if ([_other isCompositeType]) return NO; if (![[_other type] isEqualToString:self->type]) return NO; return YES; } - (BOOL)hasSameType:(NGMimeType *)_other { // parameters need not match if (_other == nil) return NO; if (_other == self) return YES; if ([_other isCompositeType]) return NO; if (![[_other type] isEqualToString:self->type]) return NO; if (![[_other subType] isEqualToString:self->subType]) return NO; return YES; } - (BOOL)doesMatchType:(NGMimeType *)_other { // interpretes wildcards NSString *ot = [_other type]; NSString *ost = [_other subType]; if ([ot isEqualToString:@"*"]) ot = self->type; if (![self->type isEqualToString:ot]) return NO; if ([ost isEqualToString:@"*"]) ost = self->subType; if (![self->subType isEqualToString:ost]) return NO; return YES; } /* parameters */ - (NSEnumerator *)parameterNames { return [self->parameters keyEnumerator]; } - (id)valueOfParameter:(NSString *)_parameterName { return [self->parameters objectForKey:_parameterName]; } - (NSDictionary *)parametersAsDictionary { return self->parameters; } /* description */ - (NSString *)stringValue { NSMutableString *str = [NSMutableString stringWithCapacity:128]; [str appendString:self->type]; [str appendString:@"/"]; [str appendString:self->subType]; if ([self->parameters isNotEmpty]) { NSEnumerator *keys; id key; keys = [self->parameters keyEnumerator]; while ((key = [keys nextObject]) != nil) { [str appendString:@"; "]; [str appendString:key]; [str appendString:@"=\""]; [str appendString:[self->parameters objectForKey:key]]; [str appendString:@"\""]; } } return str; } @end /* NGConcreteGenericMimeType */ @implementation NGConcreteWildcardType - (id)initWithType:(NSString *)_type subType:(NSString *)_subType parameters:(NSDictionary *)_parameters { self->parameters = [_parameters copy]; self->type = [_type isEqualToString:@"*"] ? nil : [_type copy]; self->subType = [_subType isEqualToString:@"*"] ? nil : [_subType copy]; return self; } - (void)dealloc { [self->parameters release]; [self->type release]; [self->subType release]; [super dealloc]; } /* accessors */ - (NSString *)type { return self->type != nil ? self->type : (NSString *)@"*"; } - (NSString *)subType { return self->subType != nil ? self->subType : (NSString *)@"*"; } - (BOOL)isCompositeType { return NO; } /* parameters */ - (NSEnumerator *)parameterNames { return [self->parameters keyEnumerator]; } - (id)valueOfParameter:(NSString *)_parameterName { return [self->parameters objectForKey:_parameterName]; } /* representations */ - (NSDictionary *)parametersAsDictionary { return self->parameters; } /* comparing types */ - (BOOL)isEqualToMimeType:(NGMimeType *)_type { if (_type == nil) return NO; if (_type == self) return YES; if (![self hasSameType:_type]) return NO; if (![[_type parametersAsDictionary] isEqual:[self parametersAsDictionary]]) return NO; return YES; } - (BOOL)hasSameGeneralType:(NGMimeType *)_other { // only the 'type' must match if (_other == nil) return NO; if (_other == self) return YES; if (![[_other type] isEqualToString:[self type]]) return NO; return YES; } - (BOOL)hasSameType:(NGMimeType *)_other { // parameters need not match if (_other == nil) return NO; if (_other == self) return YES; if (![[_other type] isEqualToString:[self type]]) return NO; if (![[_other subType] isEqualToString:[self subType]]) return NO; return YES; } - (BOOL)doesMatchType:(NGMimeType *)_other { // interpretes wildcards if (self->type) { NSString *ot = [_other type]; if ([ot isEqualToString:@"*"]) ot = self->type; if (![self->type isEqualToString:ot]) return NO; } if (self->subType) { NSString *ost = [_other subType]; if ([ost isEqualToString:@"*"]) ost = self->subType; if (![self->subType isEqualToString:ost]) return NO; } return YES; } /* description */ - (NSString *)stringValue { NSMutableString *str = [NSMutableString stringWithCapacity:128]; NSString *paras; [str appendString:[self type]]; [str appendString:@"/"]; [str appendString:[self subType]]; paras = [self parametersAsString]; if (paras) [str appendString:paras]; return str; } @end /* NGConcreteWildcardType */ SOPE/sope-mime/NGMime/NGMime.h0000644000000000000000000000314615004363604014623 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGMime_H__ #define __NGMime_NGMime_H__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // kit class @interface NGMime : NSObject + (NSString *)libraryVersion; @end #define LINK_NGMime \ static void __link_NGMime(void) { \ [NGMime self]; \ __link_NGMime(); \ } #endif /* __NGMime_NGMime_H__ */ SOPE/sope-mime/NGMime/NGMimeContentLengthHeaderFieldParser.m0000644000000000000000000000317715004363604022563 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeHeaderFieldParser.h" #include "NGMimeHeaderFields.h" #include "NGMimeUtilities.h" #include "common.h" @implementation NGMimeContentLengthHeaderFieldParser - (id)parseValue:(id)_data ofHeaderField:(NSString *)_field { const char *buf, *ptr; _data = [self removeCommentsFromValue:_data]; buf = [_data cString]; ptr = buf; while (!isRfc822_DIGIT(*ptr) && (*ptr != '\0')) ptr++; if (isRfc822_DIGIT(*ptr)) return [NSNumber numberWithUnsignedInt:atol(ptr)]; else { NSLog(@"WARNING(%s): invalid content-length field value (value='%s')", __PRETTY_FUNCTION__, buf); return nil; } } /* description */ - (NSString *)description { return [NSString stringWithFormat: @"", self]; } @end /* NGMimeContentLengthHeaderFieldParser */ SOPE/sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m0000644000000000000000000002316515004363604021452 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "NGMimeHeaderFieldParser.h" #include "NGMimeHeaderFields.h" #include "NGMimeUtilities.h" #include "common.h" @implementation NGMimeRFC822DateHeaderFieldParser static NSTimeZone *gmt = nil; static NSTimeZone *met = nil; + (void)initialize { static BOOL didInit = NO; if (didInit) return; didInit = YES; gmt = [[NSTimeZone timeZoneWithName:@"GMT"] retain]; met = [[NSTimeZone timeZoneWithName:@"MET"] retain]; } /* All the date formats are more or less the same. If they start with a char those can be skipped to the first digit (since it is the weekday name that is unnecessary for date construction). TODO: use an own parser for that. */ static int parseMonthOfYear(char *s, unsigned int len) { /* This one is *extremely* forgiving, it only checks what is necessary for the set below. This should work for both, English and German. English: Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec J F M A M J J A S O N D */ if (len < 3) { NSLog(@"RFC822 Parser: cannot process month name: '%s'", s); return 0; } switch (toupper(*s)) { case 'A': // April, August if (toupper(s[1]) == 'P') return 4; // Apr return 8; // Aug case 'D': return 12; // Dec case 'F': return 2; // Feb case 'J': // Jan, Jun, Jul if (toupper(s[1]) == 'A') return 1; // Jan if (toupper(s[2]) == 'N') return 6; // Jun return 7; // Jul case 'M': // Mar, May if (toupper(s[2]) == 'Y' || toupper(s[2]) == 'I') // May or Mai (German ;-) return 5; return 3; // Mar case 'N': return 11; // Nov case 'O': return 10; // Oct case 'S': return 9; // Sep default: NSLog(@"RFC822 Parser: cannot process month name: '%s'", s); return 0; } } static int offsetFromTZAbbreviation(const char *s, size_t len, size_t *next_pos) { NSString *abbreviation; NSTimeZone *offsetTZ; size_t length; length = 0; while (length < len && isalpha(*(s+length))) length++; abbreviation = [[NSString alloc] initWithBytes: s length: length encoding: NSISOLatin1StringEncoding]; offsetTZ = [NSTimeZone timeZoneWithAbbreviation: abbreviation]; [abbreviation release]; *next_pos = length; return [offsetTZ secondsFromGMT]; } static inline size_t findDigitsString(const char *s, size_t len) { size_t pos; for (pos = 0; pos < len && !isdigit(*(s+pos));) pos++; return pos; } static NSTimeZone *parseTimeZone(const char *s, size_t len) { /* WARNING: failed to parse RFC822 timezone: '+0530' \ (value='Tue, 13 Jul 2004 21:39:28 +0530') TODO: this is because libFoundation doesn't accept 'GMT+0530' as input. */ NSTimeZone *tz; register size_t pos; size_t new_pos; NSInteger hours, minutes, seconds, remaining; int sign; sign = 1; hours = 0; minutes = 0; seconds = 0; pos = 0; if (isalpha(s[pos])) { seconds = offsetFromTZAbbreviation (s+pos, len-pos, &new_pos); pos = new_pos; } while (pos < len && isspace(*(s+pos))) pos++; while (pos < len && (*(s+pos) == '+' || *(s+pos) == '-')) { if (*(s+pos) == '-') sign = -sign; pos++; } if (pos < len) { pos += findDigitsString(s+pos, len-pos); } remaining = len - pos; switch(remaining) { case 6: /* hhmmss */ seconds += (10 * (*(s + pos + remaining - 2) - 48) + *(s + pos + remaining - 1) - 48); case 4: /* hhmm */ hours += 10 * (*(s + pos) - 48); pos++; case 3: /* hmm */ hours += *(s + pos) - 48; pos++; minutes += 10 * (*(s + pos) - 48) + *(s + pos + 1) - 48; break; case 2: /* hh */ hours += 10 * (*(s + pos) - 48) + *(s + pos + 1) - 48; break; default: if(!(len == 3 && *s == 'G' && *(s+1) == 'M' && *(s+2) == 'T')) NSLog (@"parseTimeZone: cannot parse time notation '%.*s'", (int)len, s); } seconds += sign * (3600 * hours + 60 * minutes); tz = [NSTimeZone timeZoneForSecondsFromGMT: seconds]; return tz; } - (id)parseValue:(id)_data ofHeaderField:(NSString *)_field { // TODO: use UNICODE NSCalendarDate *date = nil; char *allocBytes, *bytes, *pe; unsigned length = 0; NSTimeZone *tz = nil; char dayOfMonth, monthOfYear, hour, minute, second; short year; BOOL flag; length = [_data lengthOfBytesUsingEncoding: NSUTF8StringEncoding]; if (length == 0) { NSLog(@"WARNING(%s): empty value for header field %@ ..", __PRETTY_FUNCTION__, _field); return [NSCalendarDate date]; } allocBytes = strdup ([_data cStringUsingEncoding: NSUTF8StringEncoding]); bytes = allocBytes; /* remove leading chars (skip to first digit, the day of the month) */ while (length > 0 && (!isdigit(*bytes))) { bytes++; length--; } // TODO: should be a category on NSCalendarDate // TODO: optimize much further! // first part: '16 Jun 2002' // snd part: '12:28[:11]' // trd part: 'GMT' '+0000' '(MET)' '(+0200)' /* defaults for early aborts */ tz = gmt; second = 0; minute = 0; /* parse day of month */ for (pe = bytes; isdigit(*pe); pe++) ; if (*pe == 0) goto failed; *pe = '\0'; dayOfMonth = atoi((char *)bytes); bytes = pe + 1; /* parse month-abbrev (should be English, could be other langs) */ while (!isalpha(*bytes)) { /* go to first char */ if (*bytes == '\0') goto failed; bytes++; } for (pe = bytes; isalpha(*pe); pe++) /* find end of string */ ; if (*pe == 0) goto failed; *pe = '\0'; if ((monthOfYear = parseMonthOfYear(bytes, (pe - bytes))) == 0) { [self logWithFormat:@"WARNING(%s): cannot parse month in date: %@", __PRETTY_FUNCTION__, _data]; } bytes = pe + 1; /* parse year */ while (!isdigit(*bytes)) { /* go to first digit */ if (*bytes == '\0') goto failed; bytes++; } for (pe = bytes; isdigit(*pe); pe++) /* find end of number */ ; if (*pe == 0) goto failed; *pe = '\0'; year = atoi((char *)bytes); bytes = pe + 1; if (year >= 70 && year < 135) // Y2K year += 1900; else if (year >= 0 && year < 70) // Y2K year += 2000; #if LIB_FOUNDATION_LIBRARY if (year > 2030) { NSLog(@"ERROR(%s): got invalid year in date header %d: '%s'", __PRETTY_FUNCTION__, year, buf); year = 2000; /* no choice is good ..., maybe return nil? */ } #endif /* parse hour */ while (!isdigit(*bytes)) { /* go to first digit */ if (*bytes == '\0') goto failed; bytes++; } for (pe = bytes; isdigit(*pe); pe++) /* find end of number */ ; flag = (*pe == 0); *pe = '\0'; hour = bytes != pe ? atoi((char *)bytes) : 0; if (flag) goto finished; // this is: '12\0' bytes = pe + 1; /* parse minute */ while (!isdigit(*bytes)) { /* go to first digit */ if (*bytes == '\0') goto finished; // this is: '12 \0' bytes++; } for (pe = bytes; isdigit(*pe); pe++) /* find end of number */ ; flag = (*pe == 0); *pe = '\0'; minute = bytes != pe ? atoi((char *)bytes) : 0; if (flag) goto finished; // this is: '12:23\0' bytes = pe + 1; /* parse second - if available '13:13:23' vs '12:23\0' or '12:12 (MET)' */ while (isspace(*bytes)) /* skip spaces */ bytes++; if (*bytes == 0) goto finished; // this is: '12:23 \0' if (isdigit(*bytes) || *bytes == ':') { /* parse second */ while (!isdigit(*bytes)) { /* go to first digit, skip the ':' */ if (*bytes == '\0') goto finished; bytes++; } for (pe = bytes; isdigit(*pe); pe++) /* find end of number */ ; flag = (*pe == 0); *pe = '\0'; second = bytes != pe ? atoi((char *)bytes) : 0; if (flag) goto finished; // this is: '12:23:12\0' bytes = pe + 1; } /* parse timezone: 'GMT' '+0000' '(MET)' '(+0200)' */ // TODO: do we need to parse: "-0700 (PDT)" as "PDT"? while (isspace(*bytes) || *bytes == '(') /* skip spaces */ bytes++; if (*bytes == 0) goto finished; // this is: '12:23:12 \0' or '12:12 (' for (pe = bytes; isalnum(*pe) || *pe == '-' || *pe == '+'; pe++) ; *pe = '\0'; if (pe == bytes || (tz = parseTimeZone((const char *) bytes, (pe - bytes))) == nil) { [self logWithFormat: @"WARNING: failed to parse RFC822 timezone: '%s' (value='%@')", bytes, _data]; tz = gmt; } free (allocBytes); /* construct and return */ finished: date = [NSCalendarDate dateWithYear:year month:monthOfYear day:dayOfMonth hour:hour minute:minute second:second timeZone:tz]; if (date == nil) goto failed; #if 0 printf("parsed '%s' to date: %s\n", [_data cString], [[date description] cString]); //[self logWithFormat:@"parsed '%@' to date: %@", _data, date]; #endif return date; failed: // TODO: 'Sun, May 18 2003 14:20:55 -0700' - why does this fail? [self logWithFormat:@"WARNING: failed to parse RFC822 date field: '%@'", _data]; return nil; } @end /* NGMimeRFC822DateHeaderFieldParser */ SOPE/sope-mime/NGMime/NGMimeTextBodyGenerator.m0000644000000000000000000000617315004363604020165 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeBodyGenerator.h" #include "NGMimePartGenerator.h" #include #include "common.h" @implementation NGMimeTextBodyGenerator - (NSStringEncoding)_encodingFromContentType:(NGMimeType *)_type { NSStringEncoding encoding; NSString *charset; encoding = [NSString defaultCStringEncoding]; if (_type != nil) { charset = [_type valueOfParameter: @"charset"]; if ([charset length] > 0) { if ([charset isEqualToString: @"utf-8"]) encoding = NSUTF8StringEncoding; else if ([charset isEqualToString: @"iso-8859-1"]) encoding = NSISOLatin1StringEncoding; /* more should be handled here */ } } return encoding; } - (NSData *)generateBodyOfPart:(id)_part additionalHeaders:(NGMutableHashMap *)_addHeaders delegate:(id)_delegate { NSData *data; id body; body = [_part body]; data = nil; if ([body isKindOfClass:[NSString class]]) { NSString *charset = [[_part contentType] valueOfParameter:@"charset"]; if ([charset isNotEmpty]) data = [body dataUsingEncodingNamed:charset]; if (data == nil) /* either no charset given or the charset failed */ data = [body dataUsingEncoding:[NSString defaultCStringEncoding]]; } else if ([body respondsToSelector:@selector(bytes)]) { /* an NSData, but why not check the class?!, we can't just cast it */ data = body; } else if ([body respondsToSelector:@selector(dataUsingEncoding:)]) { /* hm, whats that?, NSString is covered before */ NSStringEncoding encoding = 0; NSString *charset = [[_part contentType] valueOfParameter:@"charset"]; if ([charset isNotEmpty]) { #if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY encoding = [NSString stringEncodingForEncodingNamed:charset]; #else encoding = [self _encodingFromContentType:[_part contentType]]; #endif } data = [body dataUsingEncoding: (encoding != 0 ? encoding : NSISOLatin1StringEncoding)]; } else if (body != nil) { [self errorWithFormat:@"unexpected part body %@: %@", [body class], body]; return nil; } if (data == nil) { [self warnWithFormat:@"%s: generate empty body", __PRETTY_FUNCTION__]; data = [NSData data]; } return [self encodeData:data forPart:_part additionalHeaders:_addHeaders]; } @end /* NGMimeTextBodyGenerator */ SOPE/sope-mime/NGMime/GNUmakefile0000644000000000000000000000415215004363604015406 0ustar rootroot# GNUstep makefile include ../../config.make include $(GNUSTEP_MAKEFILES)/common.make include ../Version SUBPROJECT_NAME = NGMime #NGMime_PCH_FILE = common.h NGMime_HEADER_FILES_DIR = . NGMime_HEADER_FILES_INSTALL_DIR = /NGMime NGMime_HEADER_FILES = \ NGMimeDecls.h \ NGMime.h \ \ NGConcreteMimeType.h \ NGMimeBodyGenerator.h \ NGMimeBodyParser.h \ NGMimeBodyPart.h \ NGMimeBodyPartParser.h \ NGMimeExceptions.h \ NGMimeGeneratorProtocols.h \ NGMimeHeaderFieldGenerator.h \ NGMimeHeaderFieldParser.h \ NGMimeHeaderFields.h \ NGMimeMultipartBody.h \ NGMimePartGenerator.h \ NGMimePartParser.h \ NGMimeType.h \ NGMimeUtilities.h \ NGPart.h \ NGMimeFileData.h \ NGMimeJoinedData.h \ \ NSData+RFC822.h NGMime_OBJC_FILES = \ NGMime.m \ \ NGConcreteMimeType.m \ NGMimeBodyGenerator.m \ NGMimeBodyParser.m \ NGMimeBodyPart.m \ NGMimeBodyPartParser.m \ NGMimeExceptions.m \ NGMimeHeaderFieldGenerator.m \ NGMimeHeaderFieldParser.m \ NGMimeHeaderFields.m \ NGMimeMultipartBody.m \ NGMimeMultipartBodyParser.m \ NGMimePartGenerator.m \ NGMimePartParser.m \ NGMimeType.m \ NGPart.m \ NGMimeFileData.m \ NGMimeJoinedData.m \ NGMimeUtilities.m \ \ NGMimeContentDispositionHeaderFieldParser.m \ NGMimeContentLengthHeaderFieldParser.m \ NGMimeContentTypeHeaderFieldParser.m \ NGMimeHeaderFieldParserSet.m \ NGMimeRFC822DateHeaderFieldParser.m \ NGMimeStringHeaderFieldParser.m \ NSCalendarDate+RFC822.m \ \ NGMimeAddressHeaderFieldGenerator.m \ NGMimeContentDispositionHeaderFieldGenerator.m \ NGMimeContentLengthHeaderFieldGenerator.m \ NGMimeContentTypeHeaderFieldGenerator.m \ NGMimeHeaderFieldGeneratorSet.m \ NGMimeRFC822DateHeaderFieldGenerator.m \ NGMimeStringHeaderFieldGenerator.m \ \ NGMimeMultipartBodyGenerator.m \ NGMimeTextBodyGenerator.m \ NGMimeRfc822BodyGenerator.m \ \ NSData+RFC822.m -include GNUmakefile.preamble ifneq ($(FHS_INSTALL_ROOT),) GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include endif include $(GNUSTEP_MAKEFILES)/subproject.make -include GNUmakefile.postamble SOPE/sope-mime/NGMime/NGMimePartParser.h0000644000000000000000000002175315004363604016633 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGMimePartParser_H__ #define __NGMime_NGMimePartParser_H__ #import #import #import #import #include #include #include /* NGMimePartParser This is an abstract class for parsing MIME parts. Known Subclasses: NGMimeMessageParser (parses RFC 822 MIME messages) NGMimeBodyPartParser (parses the parts contained in a multipart structure) NGHttpMessageParser (parses HTTP messages) */ @class NSString, NSData; @class NGMutableHashMap, NGHashMap; @class NGByteBuffer; typedef struct _NGMimeHeaderNames { NSString *accept; NSString *acceptLanguage; NSString *acceptEncoding; NSString *acceptCharset; NSString *cacheControl; NSString *cc; NSString *connection; NSString *contentDisposition; NSString *contentLength; NSString *contentTransferEncoding; NSString *contentType; NSString *cookie; NSString *date; NSString *from; NSString *host; NSString *keepAlive; NSString *messageID; NSString *mimeVersion; NSString *organization; NSString *received; NSString *returnPath; NSString *referer; NSString *replyTo; NSString *subject; NSString *to; NSString *userAgent; NSString *xMailer; } NGMimeHeaderNames; @interface NGMimePartParser : NSObject /* abstract */ { @protected NSData *sourceData; /* for parsing with imutable data */ const char *sourceBytes; int dataIdx; /* data parsing index */ int byteLen; NGByteBuffer *source; // for parsing with LA /* cached selectors */ int (*readByte)(id, SEL); int (*la)(id, SEL, unsigned); void (*consume)(id, SEL); void (*consumeCnt)(id, SEL, unsigned); /* buffer-capacity and LA (has to be at least 4) */ int bufLen; /* is set to the value of content-length header field if contentLength == -1 -> read until EOF */ int contentLength; BOOL useContentLength; // should be set in subclasses NSString *contentTransferEncoding; id delegate; // not retained to avoid retain cycles struct { BOOL parserWillParseHeader:1; BOOL parserDidParseHeader:1; BOOL parserKeepHeaderFieldData:1; BOOL parserKeepHeaderFieldValue:1; BOOL parserParseHeaderFieldData:1; BOOL parserFoundCommentInHeaderField:1; BOOL parserWillParseBodyOfPart:1; BOOL parserDidParseBodyOfPart:1; BOOL parserParseRawBodyDataOfPart:1; BOOL parserBodyParserForPart:1; BOOL parserDecodeBodyOfPart:1; BOOL parserContentTypeOfPart:1; } delegateRespondsTo; } + (NSStringEncoding)defaultHeaderFieldEncoding; + (NGMimeHeaderNames *)headerFieldNames; /* setting the delegate */ - (void)setDelegate:(id)_delegate; - (id)delegate; /* parsing the whole part */ - (id)parsePartFromStream:(id)_stream; - (id)parsePartFromData:(NSData *)_data; /* header field parsing */ - (id)parserForHeaderField:(NSString *)_name; /* perform further parsing of the header value */ - (id)valueOfHeaderField:(NSString *)_name data:(id)_data; // Parse headers until an empty line is seen, the delegate // can reject header fields from being included in the HashMap // This method can return to abort the parsing process. - (NGHashMap *)parseHeader; /* body parsing */ - (id)producePartWithHeader:(NGHashMap *)_header; - (NSData *)decodeBody:(NSData *)_data ofPart:(id)_part; - (id) parserForBodyOfPart:(id)_part data:(NSData *)_dt; - (NGMimeType *)defaultContentTypeForPart:(id)_part; - (void)parseBodyOfPart:(id)_part; /* hooks for subclasses */ - (BOOL)parsePrefix; // returns NO to abort parsing - (void)parseSuffix; - (BOOL)prepareForParsingFromStream:(id)_stream; - (void)finishParsingOfPart:(id)_part; /* accessors */ - (void)setUseContentLength:(BOOL)_use; - (BOOL)doesUseContentLength; - (NSData *)applyTransferEncoding:(NSString *)_encoding onData:(NSData *)_data; @end /* NGMimePartParser */ @interface NSObject(NGMimePartParserDelegate) /* Called before the parsing of the headers begins. The delegate can return NO to stop parsing or YES to continue parsing. */ - (BOOL)parserWillParseHeader:(NGMimePartParser *)_parser; /* This method is invoked when the parser finished parsing the complete header. Those headers are available in the HashMap which is given to the delegate. */ - (void)parser:(NGMimePartParser *)_parser didParseHeader:(NGHashMap *)_headers; /* This method is invoked when a header field was read in. The field value is as raw data which may be further processed by a field-value-parser. With this method the delegate becomes to opportunity to parse the value itself. When implementing this method the delegate takes over full responsibility for parsing the field-value, no header-parser is invoked by the MIME parser automatically. */ - (id)parser:(NGMimePartParser *)_parser parseHeaderField:(NSString *)_name data:(NSData *)_data; /* The delegate is asked whether the parser should proceed processing the header field or whether the header field should be thrown away. Throwing away a header field does not stop the parsing, it just ignores this field. */ - (BOOL)parser:(NGMimePartParser *)_parser keepHeaderField:(NSString *)_name data:(NSData *)_value; /* The delegate is asked whether the parser should proceed processing the header field or whether the header field should be thrown away. Throwing away a header field does not stop the parsing, it just ignores this field. The value of the header is already parsed (this means in effect that the delegate either didn't implement parser:keepHeader:data: or that it returned YES in this method). */ - (BOOL)parser:(NGMimePartParser *)_parser keepHeaderField:(NSString *)_name value:(id)_value; /* The parser found a comment in a header field. This comment could be stored for further processing by the delegate. Comment are usually ignored. */ - (void)parser:(NGMimePartParser *)_parser foundComment:(NSString *)_comment // can be nil, if keepComments==NO inHeaderField:(NSString *)_name; /* When the body of a part is read in appropriate content or content-transfer encodings may need to be applied. Use this method to perform this operation. */ - (NSData *)parser:(NGMimePartParser *)_parser decodeBody:(NSData *)_body ofPart:(id)_part; /* After the headers were parsed the parser creates an NGMimePart object which containes the headers. It will then begin to read in the body of the MIME message, usually first as an NSData object. You can return NO if you want to stop parsing (eg based on some values in the headers or YES if you want to have the parser read in the data of the body. */ - (BOOL)parser:(NGMimePartParser *)_parser willParseBodyOfPart:(id)_part; /* The parser successfully read in the body of the part. */ - (void)parser:(NGMimePartParser *)_parser didParseBodyOfPart:(id)_part; /* After the MIME parser read in the body as an NSData object the delegate can parse the body data and assign the result to the _part. The delegate can return NO if it decides not to parse the body. The builtin parser sequence is applied in this case. Instead of parsing the body itself the delegate can select an appropriate parser for the body using the -parser:bodyParserForPart: delegate method. */ - (BOOL)parser:(NGMimePartParser *)_parser parseRawBodyData:(NSData *)_data ofPart:(id)_part; /* If the delegate does not parse the body itself, it can still select an appropriate body parser using this method. */ - (id)parser:(NGMimePartParser *)_parser bodyParserForPart:(id)_part; - (NGMimeType *)parser:(id)_parser contentTypeOfPart:(id)_part; @end /* NSObject(NGMimePartParserDelegate) */ @interface NSObject(NGMimePartParser) - (void)parser:(NGMimePartParser *)_parser setOriginalHeaderFieldName:(NSString *)_name; @end @interface NSData(MIMEContentTransferEncoding) - (NSData *)dataByApplyingMimeContentTransferEncoding:(NSString *)_enc; @end #endif /* __NGMime_NGMimePartParser_H__ */ SOPE/sope-mime/NGMime/NGMimeExceptions.h0000644000000000000000000000202315004363604016656 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGMimeExceptions_H__ #define __NGMime_NGMimeExceptions_H__ #import @interface NGMimeException : NSException @end @interface NGMimeParserException : NGMimeException @end #endif /* __NGMime_NGMimeExceptions_H__ */ SOPE/sope-mime/NGMime/NGMimeUtilities.m0000644000000000000000000001560515004363604016527 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include typedef struct { NSString *charset; NSString *q; NSString *boundary; NSString *name; NSString *fileName; NSString *reportType; } NGMimeParameterConstants; static NGMimeParameterConstants *MimeParameterConstants = NULL; static Class NSStringClass = Nil; static int MimeLogEnabled = -1; static NSString *_stringForParameterName(char *_type, int _len) { if (NSStringClass == Nil) NSStringClass = [NSString class]; if (MimeLogEnabled == -1) { MimeLogEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"MimeLogEnabled"]?1:0; } if (MimeParameterConstants == NULL) { MimeParameterConstants = malloc(sizeof(NGMimeParameterConstants)); MimeParameterConstants->charset = NGMimeParameterTextCharset; MimeParameterConstants->q = @"q"; MimeParameterConstants->name = @"name"; MimeParameterConstants->boundary = @"boundary"; MimeParameterConstants->fileName = @"filename"; MimeParameterConstants->reportType = @"report-type"; } switch (_len) { case 0: return @""; case 1: if (_type[0] == 'q') return MimeParameterConstants->q; break; case 4: if (strncmp(_type, "name", 4) == 0) return MimeParameterConstants->name; break; case 7: if (strncmp(_type, "charset", 7) == 0) return MimeParameterConstants->charset; break; case 8: if (strncmp(_type, "boundary", 8) == 0) return MimeParameterConstants->boundary; if (strncmp(_type, "filename", 8) == 0) return MimeParameterConstants->fileName; break; case 11: if (strncmp(_type, "report-type", 11) == 0) return MimeParameterConstants->reportType; break; } return [NSStringClass stringWithCString:_type length:_len]; } NSDictionary *parseParameters(id self, NSString *_str, unichar *cstr) { if (*cstr != '\0') { NSMutableDictionary *paras; paras = [[NSMutableDictionary alloc] initWithCapacity:8]; do { unsigned len; unichar *tmp; NSString *attrName, *attrValue; attrValue = nil; attrName = nil; // consume end of previous entry (spaces and ';') while ((*cstr == ';') || isRfc822_LWSP(*cstr)) cstr++; // parse attribute tmp = cstr; len = 0; while ((*cstr != '\0') && (isMime_ValidTypeAttributeChar(*cstr))) { cstr++; len++; } if (len == 0) break; { unsigned char buf[len + 1]; register unsigned i; buf[len] = '\0'; for (i = 0; i < len; i++) buf[i] = tolower(tmp[i]); attrName = _stringForParameterName((char *)buf, len); } // skip spaces while ((*cstr != '\0') && (isRfc822_LWSP(*cstr))) { cstr++; } // no value was given for attribute if (*cstr == '\0') { if (MimeLogEnabled) [self logWithFormat:@"WARNING(%s): attribute '%@' has no value in " @"MimeType '%@'", __PRETTY_FUNCTION__, attrName, _str]; break; // exit loop } // expect '=' if (*cstr != '=') { if (MimeLogEnabled) [self logWithFormat:@"WARNING(%s): attribute '%@', missing '=' " @"in MimeType '%@'", __PRETTY_FUNCTION__, attrName, _str]; break; // exit loop } cstr++; // skip spaces while ((*cstr != '\0') && (isRfc822_LWSP(*cstr))) cstr++; /* no value was given for parameter */ if (*cstr == '\0') { if (MimeLogEnabled) [self logWithFormat:@"WARNING(%s): attribute '%@' has no value " @"in MimeType '%@'", __PRETTY_FUNCTION__, attrName, _str]; break; // exit loop } /* now parameter read value */ if (isRfc822_QUOTE(*cstr)) { // quoted value cstr++; tmp = cstr; len = 0; while ( (!(isRfc822_QUOTE(*cstr) && *(cstr - 1) != '\\')) && (*cstr != '\0')) { cstr++; len++; } attrValue = [[[NSString alloc] initWithCharacters:tmp length:len] autorelease]; /* webkit hack: "urldecode" quotes only. @seealso: https://bugs.webkit.org/show_bug.cgi?id=62107 https://www.w3.org/Bugs/Public/show_bug.cgi?id=16909 */ attrValue = [attrValue stringByReplacingOccurrencesOfString:@"%22" withString:@"\\\""]; if (*cstr == '\0') { // quote was not closed if (MimeLogEnabled) [self logWithFormat:@"WARNING(%s): value-quotes in attribute " @"'%@' were not closed in MimeType '%@'", __PRETTY_FUNCTION__, attrName, _str]; break; // exit loop } cstr++; // skip closing quote } else { /* value without quotes */ tmp = cstr; len = 0; while (*cstr != '\0') { if (isRfc822_SPACE(*cstr)) break; if (isRfc822_CTL(*cstr)) break; if (*cstr == ';') break; /* parameter separator */ cstr++; len++; } attrValue = [[[NSString alloc] initWithCharacters:tmp length:len] autorelease]; } /* store attr/value pair in dictionary */ [paras setObject:attrValue forKey:attrName]; attrName = nil; attrValue = nil; /* skip spaces */ while ((*cstr != '\0') && (isRfc822_LWSP(*cstr))) cstr++; if (*cstr == ';') // skip ';' (attribute separator) cstr++; else if (*cstr == '\0') /* parsing is finished, exit loop */ break; // exit loop else { if (MimeLogEnabled) [self logWithFormat:@"WARNING(%s): expected end of string or ';', " @"got '%c'%i (str='%@')", __PRETTY_FUNCTION__, *cstr, *cstr, _str]; break; // exit loop } /* skip spaces */ while ((*cstr != '\0') && (isRfc822_LWSP(*cstr))) cstr++; } while (YES); return [paras autorelease]; } return nil; } SOPE/sope-mime/NGMime/NGMimeHeaderFieldGeneratorSet.m0000644000000000000000000001045115004363604021225 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeHeaderFieldGenerator.h" #include "NGMimeHeaderFields.h" #include "NGMimePartParser.h" #include "common.h" @implementation NGMimeHeaderFieldGeneratorSet static NGMimeHeaderFieldGeneratorSet *rfc822Set = nil; + (id)headerFieldGenerator { return [[[self alloc] init] autorelease]; } + (id)headerFieldGeneratorSet { return [[[self alloc] init] autorelease]; } + (id)defaultRfc822HeaderFieldGeneratorSet { static NGMimeHeaderNames *Fields = NULL; id gen; if (!Fields) Fields = (NGMimeHeaderNames *)[NGMimePartParser headerFieldNames]; if (rfc822Set) return rfc822Set; rfc822Set = [[self alloc] init]; gen = [NGMimeContentDispositionHeaderFieldGenerator headerFieldGenerator]; if (gen) [rfc822Set setGenerator:gen forField:Fields->contentDisposition]; if ((gen = [NGMimeContentLengthHeaderFieldGenerator headerFieldGenerator])) [rfc822Set setGenerator:gen forField:Fields->contentLength]; if ((gen = [NGMimeContentTypeHeaderFieldGenerator headerFieldGenerator])) [rfc822Set setGenerator:gen forField:Fields->contentType]; if ((gen = [NGMimeRFC822DateHeaderFieldGenerator headerFieldGenerator])) [rfc822Set setGenerator:gen forField:Fields->date]; if ((gen = [NGMimeAddressHeaderFieldGenerator headerFieldGenerator])) { /* FIXME - following additional fields containing an address may be added here: * - sender (RFC 2822, sect. 3.6.2) * - resent-sender, resent-cc, resent-bcc (RFC 2822, sect. 3.6.6) * Are the values case-insensitive, so "Reply-To" and "reply-to" will both * be detected? */ [rfc822Set setGenerator:gen forField:@"resent-from"]; [rfc822Set setGenerator:gen forField:@"resent-to"]; [rfc822Set setGenerator:gen forField:Fields->to]; [rfc822Set setGenerator:gen forField:Fields->cc]; [rfc822Set setGenerator:gen forField:@"bcc"]; [rfc822Set setGenerator:gen forField:Fields->from]; [rfc822Set setGenerator:gen forField:@"reply-to"]; [rfc822Set setGenerator:gen forField:@"Disposition-Notification-To"]; } if ((gen = [NGMimeStringHeaderFieldGenerator headerFieldGenerator])) [rfc822Set setDefaultGenerator:gen]; return rfc822Set; } - (id)init { return [self initWithDefaultGenerator:nil]; } - (id)initWithDefaultGenerator:(id)_gen { if ((self = [super init])) { self->fieldNameToGenerate = [[NSMutableDictionary allocWithZone:[self zone]] initWithCapacity:16]; self->defaultGenerator = [_gen retain]; } return self; } - (void)dealloc { [self->fieldNameToGenerate release]; [self->defaultGenerator release]; [super dealloc]; } /* accessors */ - (void)setGenerator:(id)_gen forField:(NSString *)_name { [self->fieldNameToGenerate setObject:_gen forKey:_name]; } - (void)setDefaultGenerator:(id)_gen { ASSIGN(self->defaultGenerator, _gen); } - (id)_gen { return self->defaultGenerator; } /* operation */ - (NSData *)generateDataForHeaderFieldNamed:(NSString *)_headerField value:(id)_value { NGMimeHeaderFieldGenerator *gen = nil; if ((gen = [self->fieldNameToGenerate objectForKey:_headerField]) == nil) gen = (NGMimeHeaderFieldGenerator *)self->defaultGenerator; if (gen == nil) { NSLog(@"WARNING(%s): no defaultGenerator is set", __PRETTY_FUNCTION__); return [NSData data]; } return [gen generateDataForHeaderFieldNamed:_headerField value:_value]; } @end /* NGMimeHeaderFieldGeneratorSet */ SOPE/sope-mime/NGMime/NGMimeBodyGenerator.h0000644000000000000000000000472715004363604017316 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMimeGenerator_NGMimeBodyGenerator_H__ #define __NGMimeGenerator_NGMimeBodyGenerator_H__ #import #import #import @class NSData, NSString, NSArray, NGMutableHashMap; @class NGMimeMultipartBodyGenerator, NGMimeMultipartBody; @interface NGMimeBodyGenerator : NSObject { BOOL useMimeData; } - (NSData *)generateBodyOfPart:(id)_part additionalHeaders:(NGMutableHashMap *)_addHeaders delegate:(id)_delegate; - (NSData *)encodeData:(NSData *)_data forPart:(id)_part additionalHeaders:(NGMutableHashMap *)_addHeaders; - (BOOL)useMimeData; - (void)setUseMimeData:(BOOL)_b; @end @interface NGMimeTextBodyGenerator : NGMimeBodyGenerator @end @interface NGMimeRfc822BodyGenerator : NGMimeBodyGenerator - (id)generatorForPart:(id)_part; @end @interface NGMimeMultipartBodyGenerator : NGMimeBodyGenerator + (NSString *)boundaryPrefix; - (NSString *)multipartBodyGenerator:(NGMimeMultipartBodyGenerator *)_gen prefixForPart:(id)_part mimeMultipart:(NGMimeMultipartBody *)_body; - (NSString *)multipartBodyGenerator:(NGMimeMultipartBodyGenerator *)_gen suffixForPart:(id)_part mimeMultipart:(NGMimeMultipartBody *)_body; - (id)multipartBodyGenerator:(NGMimeBodyGenerator *)_gen generatorForPart:(id)_part; - (NSData *)buildDataWithBoundary:(NSString *)_boundary partsData:(NSArray *)_parts; - (NSString *)buildBoundaryForPart:(id)_part data:(NSArray *)_data additionalHeaders:(NGMutableHashMap *)_addHeaders; @end #endif // __NGMimeGenerator_NGMimeBodyGenerator_H__ SOPE/sope-mime/NGMime/ChangeLog0000644000000000000000000012506215004363604015112 0ustar rootroot2008-09-08 Wolfgang Sourdeau * NGMimeRFC822DateHeaderFieldParser.m ([NGMimeRFC -parseValue:ofHeaderField:]): don't parse timezone with a length of 0. 2008-09-01 Wolfgang Sourdeau * NGMimeRFC822DateHeaderFieldParser.m ([NGMimeRFC -parseValue:ofHeaderField:]): use an 8-bit safe encoding when parsing dates. Since we only consider 7-bits characters, we ensure that bad user-agents can be handled more properly. * NGMimeType.m ([NGMimeType +stringEncodingForCharset:]): x-unknown encoding is now translated to an 8-bit safe encoding (NSISOLatin1StringEncoding). * NGMimeAddressHeaderFieldGenerator.m ([NGMimeAddressHeaderFieldGenerator -generateDataForHeaderFieldNamed:value:]): encode resulting string in an 8-bit safe encoding (NSISOLatin1StringEncoding). 2008-01-29 Albrecht Dress * fixes for OGo bug #789 (reply-to QP encoding) 2007-08-29 Helge Hess * NGMimeFileData.m ([NGMimeFileData -initWithBytes:length:]): do not call [super init] on gnustep-base. This should fix (hack around) OGo bug #1890 2007-06-01 Helge Hess * NGMimePartParser.m: moved processing of content-transfer-encoding to an NSData category, fixed OGo bug #1856 (use correct quoted printable decoder!) 2007-05-28 Helge Hess * NGMimeTextBodyGenerator.m: fixed compilation on gnustep-base 2007-05-28 Helge Hess * NGMimeTextBodyGenerator.m: reworked body contents encoding using the character encoding support in NGExtension/NSString+Encoding * NGMimeBodyGenerator.m: moved contained classes to own .m files 2007-05-15 Wolfgang Sourdeau * NGMimeBodyGenerator.m: encode string body contents using the charset of the content-type (when available) (OGo bug #1873) 2006-02-22 Helge Hess * NGMimeRFC822DateHeaderFieldParser.m: added hardcoded detection for CET and UTC in addition to GMT and MET 2005-12-16 Marcus Mueller * NGMime.xcodeproj: synced with GNUmakefile 2005-12-13 Helge Hess * NGMimeAddressHeaderFieldGenerator.m: use -warnWithFormat: * NGMimeUtilities.h: code cleanups 2005-11-17 Helge Hess * properly include string.h where required to avoid warnings 2005-09-18 Helge Hess * NGMimeAddressHeaderFieldGenerator.m: fixed some strict dependencies on NGMail (this generator should be moved to NGMail) 2005-07-20 Helge Hess * NGMimeBodyPart.m: added some convinience methods to access the header fields of a part 2005-07-13 Marcus Mueller * NGMime.xcodeproj: synced with GNUmakefile 2005-07-11 Helge Hess * NGMimeBodyGenerator.m: improved reliability against invalid body objects 2005-04-24 Helge Hess * fixed gcc 4.0 warnings 2005-03-24 Helge Hess * NGMimePartGenerator.m: minor improvement in field generation API, added support for multivalue headers (related to #1324) 2005-03-05 Helge Hess * NGMimePartGenerator.m: properly terminate header fields with \r\n (OGo bug #1282) 2005-01-30 Helge Hess * NGMimeContentTypeHeaderFieldGenerator.m, NGPart.m: fixed default type ("application/octet-stream", not "application/octet") * NGMimePartGenerator.m: code cleanups, added support for 'NGMimeGeneratorDebugEnabled' default, properly generate \r\n instead of just \n as a header/body separator, add a hack to avoid duplicate generation of the \r\n header/body separator (needs to get tested) * NGMimeJoinedData.m: code cleanups, added a -length method * NGMimeMultipartBodyGenerator.m: enable debug logs when 'NGMimeGeneratorDebugEnabled' default is enabled * NGMimeBodyGenerator.m: moved NGMimeMultipartBodyGenerator to own file, added support for 'NGMimeGeneratorDebugEnabled' default 2004-12-14 Marcus Mueller * NGMime.xcode: minor fixes and updated 2004-12-09 Helge Hess * NGMimeRFC822DateHeaderFieldParser.m: fix spam mail date header parsing for libFoundation 2004-11-13 Helge Hess * NGConcreteMimeType.m: added support for 'reply-type' parameter in text MIME types 2004-10-27 Marcus Mueller * NGMime.xcode: added NGSendMail files to Xcode build 2004-10-06 Helge Hess * NGMimeRFC822DateHeaderFieldParser.m: added special case for +0530 timezone which seems to be common (v4.3.188) 2004-10-04 Marcus Mueller * NGMime.xcode: added new files to Xcode build 2004-09-30 Helge Hess * NGMime: minor cleanups (v4.3.187) * NGMimePartParser.m: fixed an issue with unlimited length parsing, fixes OGo bug #936 (v4.3.182) 2004-09-21 Marcus Mueller * NGMime.xcode: Fixed dependencies to resemble the make process more closely. Our aim should be to stick to the make process as closely as possible, so we shouldn't introduce dependencies in non-toplevel projects. * NGMime.xcode: fixes 2004-08-31 Helge Hess * GNUmakefile: define library version (v4.3.176) * NGMime.m: use 4.3.0 as fallback library version 2004-08-29 Marcus Mueller * NGMime.xcode: new Xcode project 2004-08-27 Helge Hess * NGMimeRFC822DateHeaderFieldParser.m: always use custom date parser instead of the NSCalendarDate format parser (closes OGo bug #562) (v4.3.174) 2004-08-20 Helge Hess * now is a subproject of the sope-mime library just like NGImap4 and NGMail (v4.3.173) * moved to sope-mime * moved to SOPE 4.3 (v4.3.172) 2004-08-02 Frank Reppin * NGMimeRFC822DateHeaderFieldParser.m: fixed OGo Bug #861 (August mails were reported as April mails) (v4.2.171) 2004-07-22 Helge Hess * v4.2.170 * NGMimeHeaderFieldParser.h: fixed prototypes of NGMimeHeaderFieldParser protocol * NGMimeFileData.m, NGMail: fixed a gcc 3.4 warning 2004-07-15 Helge Hess * NGImap4: fixed OGo bug #840 (introduced in v4.2.166), code cleanups, fixed some gcc 3.4 warnings (v4.2.169) 2004-07-13 Helge Hess * NGImap4: fixed some compilation issue with older gcc's (v4.2.168) * NGImap4: minor improvements to exception handling (v4.2.167) * NGImap4: some changes to body response parser which might fix OGo bug 800, some speed improvements in the fetch response normalizer (v4.2.166) * NGImap4: added more logging output (v4.2.165) 2004-06-21 Helge Hess * NGImap4: fixed a gstep-base warning (v4.2.164) 2004-06-20 Helge Hess * v4.2.163 * NGImap4/NGImap4Message.m: minor optimization * NGMimeAddressHeaderFieldGenerator.m, NGMimeBodyParser.m, NGMimeHeaderFields.m, NGMimeMultipartBodyParser.m, NGMimePartParser.m, NGMimeUtilities.m: minor cleanups to default processing * NGMimeFileData.m, NGMimeBodyGenerator.m: per default generate temporary files in /tmp/OGo/ instead of /tmp/Skyrix/ 2004-06-14 Helge Hess * NGImap4: fixed some gcc 3.4 warnings (v4.2.162) 2004-06-10 Helge Hess * NGMail: fixed some gcc 3.4 warnings (v4.2.161) 2004-06-09 Helge Hess * NGMail: minor tweaks (v4.2.160) * GNUmakefile.preamble: added prebinding (v4.2.159) 2004-05-16 Helge Hess * NGImap4: various cleanups (v4.2.158) * NGMimeAddressHeaderFieldGenerator.m, NGMimeBodyGenerator.m, NGMimeContentDispositionHeaderFieldGenerator.m, NGMimeContentTypeHeaderFieldGenerator.m, NGMimeMultipartBodyParser.m, NGMimePartParser.m: various code cleanups (v4.2.157) 2004-05-05 Marcus Mueller * GNUmakefile.preamble: added support for building with GNUSTEP_BUILD_DIR environment variable set for recent gnustep-make package. (v4.2.156) 2004-04-19 Marcus Mueller * NGMimeRFC822DateHeaderFieldParser.m: ported RFC822 timezone parser to gnustep-base and Apple's Foundation. Using abbreviations for timezone names turned out to be non-portable across foundations. Also enhanced the range of GMT timezones understood - this is now from GMT-1400 until GMT+1200 (v4.2.155) 2004-04-02 Helge Hess * NGImap4: some code cleanups, fixed OGo bug #660 (premature dealloc) (v4.2.154) 2004-03-19 Helge Hess * v4.2.153 * NGMimeRFC822DateHeaderFieldParser.m: improved RFC822 timezone parser to deal with timezone strings as submitted by MultiMail (-05-500) * NGConcreteMimeType.m: detect x-avg-checked MIME type parameter 2004-02-17 Helge Hess * NGImap4: fixed OGo bug #582 (mail searching was broken) (v4.2.152) 2004-02-10 Helge Hess * NGImap4, NGMail: fixed compilation warnings on OSX (v4.2.151) 2004-02-08 Helge Hess * v4.2.150 * NGMail/NGMimeMessageGenerator.m: expose _base64Encoding function * NGMail/GNUmakefile, NGMail/NGMimeMessageGenerator.m: moved body generator subclass to separate source files * GNUmakefile, NGMimeHeaderFieldGenerator.m: moved out field generator subclasses to own source files * NGMimeHeaderFieldGenerator.h: export NGEncodeQuotedPrintableMime function (should be a NSString category?!) 2004-01-24 Helge Hess * NGImap4: various improvements, parsing optimization (v4.2.149) * NGMimeRFC822DateHeaderFieldParser.m: improved performance, see NGImap4 ChangeLog for details (v4.2.146) 2004-01-22 Helge Hess * NGImap4: cleanups, fixed OGo bug #537 (v4.2.145) 2004-01-21 Helge Hess * NGImap4: cleanups, cleanups, cleanups (v4.2.144) 2004-01-20 Helge Hess * NGImap4: cleaned up API (v4.2.143) 2004-01-20 Helge Hess * NGImap4Message: optimization (v4.2.142) 2004-01-19 Helge Hess * NGImap4: various optimizations and cleanups (see NGImap4 ChangeLog for details) (v4.2.141) 2004-01-19 Helge Hess * added global-id classes in NGImap4 (v4.2.140) 2004-01-12 Helge Hess * v4.2.139 * NGMimeRFC822DateHeaderFieldParser.m: optimized date parsing - additional optimizations lined out * NGMimeHeaderFieldParser.m: moved the various parser classes to separate files (maybe should be moved to a subproject in the long run), minor code cleanups * NGMimePartParser.m: cache defaultRfc822HeaderFieldParserSet for speed * NGImap4: major cleanups, see NGImap4/ChangeLog for details 2004-01-11 Helge Hess * v4.2.138 * NGImap4: major cleanups * NGImap4: renamed common.h to imCommon.h, fixed other files to include that (v4.2.137) Tue Nov 11 15:04:18 2003 Jan Reichmann * NGImap4ResponseParser.m: add parsing of capability entries without value (v4.2.136) 2003-11-10 Helge Hess * v4.2.135 * NGMime.m: use some defaults for the NGMime version in case we are not compiling using gstep-make * NGImap4ResponseParser.m: explicitly marked the lastChar variable as being a signed char to avoid compiler errors Thu Nov 6 16:41:13 2003 Jan Reichmann * v4.2.134 * NGSieveClient: fixed a bug in normalizeResponse, return NSMutableDictionary * NGImap4ResponseParser.m: remove CYRUS_2_0 constant, don`t now what it should be :( Mon Nov 3 15:42:37 2003 Jan Reichmann * NGImap4Context: temporary set selected folder befor the select action to prevent notification confusions (v4.2.133) 2003-10-17 Helge Hess * NGImap4: small code cleanups to Sieve client (v4.2.132) 2003-10-12 Helge Hess * GNUmakefile.preamble: added libEOControl as a dependency (required on MacOSX) (v4.2.131) 2003-09-06 Helge Hess * removed various dependencies to FoundationExt (v4.2.130) * various fixes to remove warnings on MacOSX (v4.2.129) Tue Jul 22 15:19:34 2003 Jan Reichmann * NGImap4ResponseParser.m: check for empty quota reponses (v4.2.128) 2003-07-18 Helge Hess * NGImap4: fixed some gstep-base issues, patch provided by Filip Van Raemdonck and cleaned up a bit (v4.2.127) Thu Jul 17 10:37:22 2003 Jan Reichmann * NGImap4ServerRoot: add a missing method (bulkFetchHeadersFor:inRange:withAllUnread:) (v4.2.126) Fri Jun 27 18:08:49 2003 Jan Reichmann * NGImap4Message.m: improve flag handling (v4.2.124) * NGImap4Message.m: code cleanups (v4.2.123) Thu Jun 26 13:23:30 2003 Jan Reichmann * v.4.2.122 * NGImap4Message.m: add messageWithURL: methods * NGImap4Context.m: execute select-command before setting selectet folder * NGImap4Folder: add a struct do store failed select, status, getQuota responses, set selectet folder after successfully select response Fri Jun 20 18:51:24 2003 Jan Reichmann * v4.2.121 * NGImap4Client.m: cleanups * NGImap4ServerRoot, NGImap4Folder.m, NGImap4Functions: fetch status (new/unseen) of subfolders on demand only if Default: FetchNewUnseenMessagesInSubFoldersOnDemand = 'YES' * NGImap4ServerRoot, NGImap4Folder.m: improve folder-flag analysing, nonexistent folders will be ignored (Default: ShowNonExistentFolder), no 'list' request for folder with hasnochildren flag (Default: IgnoreHasNoChildrenFlag) (v4.2.120) * 4.2.119 * NGImap4Functions: cleanups * NGImap4Context.m: cleanups * NGImap4Folder.m: only reset subfolders if -resetSubFolders called (prev. behavior: -resetFolder called -resetSubFolders), cleanups Tue Jun 17 11:53:46 2003 Jan Reichmann * NGImap/NGImap4Message+BodyStructure.h: check whether parsing of date headerfield failed (v4.2.118) Fri Jun 13 17:37:37 2003 Jan Reichmann * NGMimeType.m: add charset 'unknown' (use us-ascii) (v4.2.117) Wed Jun 11 14:49:05 2003 Jan Reichmann * v4.2.116 * NGMimeMultipartBodyParser.m: improve multipart-body parsing behavior (parse bodies with no content) * NGMimeType.m: use ASCII string encoding for "x-unknown" encoding type * NGMimePartParser: add unknown-8bit content-transfer encoding * v4.2.115 * NGMimePartParser.m, NGMimeMultipartBodyParser.m: code cleanups * NGConcreteMimeType: added "x-unix-mode" as a known text mime-type parameter * NGMimePartParser: add 'binary' content transfer encoding (v4.2.114) * v4.2.113 * NGMail/NGMimeMessageParser: use unicode, use named encoding to encode header fields (if default 'UseFoundationStringEncodingForMimeHeader' = YES, libFoundation string encoding will be used) * NGMimeUtilities: add parseParameters() (parse the same kind of parameter for NGMimeType and NGMimeContentDispositionType), use unicode * NGMimeType.m: use unicode, parse parameters in NGMimeUtilities * NGMimeHeaderFields.m: use unicode, parse parameters in NGMimeUtilities * NGMimeHeaderFieldParser.m: code cleanups, add default whether to strip leading spaces or not (StripLeadingSpaces), use unicode for content-type, content-disposition and string type header-fields, wrap some comments with MimeLogEnabled, some speed optimization, * NGMimePartParser.m: ignore leading white spaces for header values (speed optimization) * NGMimeHeaderFieldParser.m: use unicode to remove comments, improve comment parsing behavior, strip leading spaces only if default 'StripLeadingSpaces' is set (currently be done during header-field parsing for speed optimization) * NGMimeBodyParser.m: use named encoding (currently iconv) to encode text bodies, (if default 'UseFoundationStringEncodingForMimeText' is set, libFoundation string encoding will be used) 2003-06-06 Helge Hess * NGConcreteMimeType.m: added support for 'delsp' attribute (delete space ?) on text/... mime-types (v4.2.113) Mo Jun 02 15:55:20 2003 Jan Reichmann * NGImap4Folder, NGImap4Functions: add notification for subfolder-resets (v4.2.112) 2003-05-28 Helge Hess * fixed a linking bug in NGImap4 (due to a ignored warning ...) (v4.2.111) Tue May 27 17:39:20 2003 Jan Reichmann * NGImap4Folder.m: check for quota only if folder is selectable (v4.2.110) Tue May 20 18:03:12 2003 Jan Reichmann * NGImap4Context; add accessor to set edit default values (v4.2.108) Wed May 14 12:54:08 2003 Jan Reichmann * v4.2.107 * NGMimeType.m: code cleanups, hide some logs behind 'MimeLogEnabled' * NGMimeMessageParser.m: code cleanups, fix a decode quoted printable bug (sometimes last char was ignored) * v4.2.106 * NGImap4ResponseParser.m: use lowercase string to determine whether fetch body reponse is 'text' or 'message' (courier imap use lowercase letters for the body description) (bug 1611) * Info: move rfc, drafts and other information files to 'Info' Thu May 13 17:59:25 2003 Jan Reichmann * NGImap4Folder.m: add notification for folder reset, if more than one folder for the same folderpath exist (v4.2.105) (bug 1612) Fri May 9 10:35:42 2003 Jan Reichmann * media-types: add (v4.2.104) Mon May 5 17:59:25 2003 Jan Reichmann * NGImap4Folder.m: improve error log, fix a bug regarding multiple mail copy from and to the same folder (v4.2.103) Wed Apr 30 15:24:26 2003 Jan Reichmann * v4.2.102 * NGMimeHeaderFieldParser.m: add some time zone format fields (bug 943) * NGImap4ServerRoot: noinferiors depends on serverkind (bug 932) * NGImap4ResponseParser.m: improve parsing of server greeting * NGImap4Folder, NGImap4ServerRoot: take ShowOnlySubscribedIn* from context * NGImap4Context.m: set ShowOnlySubscribedIn* Defaults (depends on server) * NGImap4Client.m: detect washington imap server * v4.2.101 * NGImap4ServerRoot: fixed retain bug * NGImap4Folder.m: NSLog -> logWithFormat, fixed release (bug 1559), * NGImap4Context: accessors for server defaults * NGImap4Client.m: code cleanups, some logs depends LogDefault, try to get server name (cyrus, courier) - set some server-depending Defaults, fixed special folder subscribe/create behavior (bug 1540) Thu Apr 17 11:13:44 2003 Jan Reichmann * NGMimeFileData.m: fixed bug which occurs during hh cleanups (self->path = [path copy] --> self->path = [_path copy] (v4.2.100) Fri Apr 11 10:59:45 2003 Jan Reichmann * v4.2.99 * NGImap4Functions.m: add ImapLogEnabled' default bind some logs to ImapLogEnabled' * NGMimeType.m: create MimeLogEnabled' 'WARNING(%s): expected end of string or' - occurs only if MimeLogEnabled (bug 1430) 2003-04-09 Helge Hess * v4.2.98 * various fixed of new gcc 3.3 warnings in all modules * NGMimeType.m: fixed gcc 3.3 signed/unsigned warnings * NGMimeFileData.m: small cleanups, signed-warnings * NGMail: fixed more gcc 3.3 signed/unsigned warnings (v4.2.97) * v4.2.96 * NGMail: some gcc 3.3 signed/unsigned warnings fixed * NGMimeUtilities.h: some gcc 3.3 signed/unsigned warnings fixed * NGImap4: small speed improvements Mon Apr 7 20:02:29 2003 Jan Reichmann * v4.2.95 * NGImap4Message.m: check whether encoding was set -> set encoding during body-structure fetch * NGImap4Message+BodyStructure.h: body-structuree component is no rfc822 or multipart --> body url got 'part=1' 2003-04-01 Helge Hess * NGImap4: added compilation support for GNUstep base (v4.2.94) Fri Feb 28 18:32:53 2003 Jan Reichmann * NGImap4/NGImap4Functions.m: add support for Washington Imap Server, (delete folders in server root) (v4.2.93) Wed Feb 26 17:47:53 2003 Jan Reichmann * v4.2.92 * NGImap/NGImap4ServerRoot.m: read also inbox folder if it is not subscribed * NGImap/NGImap4Client.m: check whether no sequence contains 'ALERT', reconnect also if the server repsonse an unexpecte 'bye' sequence * (Changes for Washington Imap Server support) * NGImap/NGImap4Client.m: remove NXConstStr in Excep. Handler (v4.2.91) * NGMimePartParser.h: add headers (v4.2.90) Wed Feb 26 11:37:18 2003 Jan Reichmann * NGImap/NGImap4Client.m: check whether so key exist, use DATE as default sort key (v4.2.89) Tue Feb 25 11:21:52 2003 Jan Reichmann * NGImap/NGImap4Client.m: fixed a reconnect bug (try only one time, before return with exception) (bug 1108) (v4.2.88) Mon Feb 24 15:48:07 2003 Jan Reichmann * NGImap4/NGImap4Message.m: select folder befor fetch body structure (bug 1094) (v4.2.87) Mon Feb 17 18:19:06 2003 Jan Reichmann * v4.2.86 (fixed bug 1064) * NGMimeBodyParser: remove NGMimeRfc822BodyParser * NGMimePartParser.m: remove call to NGMimeRfc822BodyParser * NGMimeMessageParser: add NGMimeRfc822BodyParser, add delegate method bodyParserForPart: to call the NGMimeRfc822BodyParser Fri Feb 14 16:16:47 2003 Jan Reichmann * NGImap4Context.m: code cleanups (v4.2.85) Wed Feb 5 14:43:22 2003 * NGMimePartParser.m: check whether la (called to buffer data) failed with EndOfStream (bug 993) (v4.2.84) Fri Jan 31 17:05:55 2003 * NGImap4Context.m: add defaults for imap special folders, fix folder create bug (v4.2.83) * NGImap4Folder.m: fetch all messages if no sort failed or no sortordering was given (v4.2.82) * NGImap4: fix parsing structure bug, code cleanups (v4.2.81) Wed Jan 29 22:12:08 2003 * NGImap4*: code cleanups (replace macros with method calls), catch all exceptions, now they are stored in [context lastException] remove connection retry (v4.2.80) 2003-01-29 Helge Hess * NGMimeFileData.m: fixed required includes (v4.2.79) Tue Jan 28 15:39:25 2003 * NGImap4: courier support (v4.2.78) * NGImap4: remove abort() (v4.2.77) * v4.2.76 * NGMimePartGenerator: generator handles now tmp-file creation * NGMimeGeneratorProtocols.h: add missing methods * NGMimeFileData.m: add Data init methods, use default to generate file-data (NGMimeBuildMimeTempDirectory) * v4.2.75 * NGMimeJoinedData: code cleanups, write file with 0600 * NGMimeFileData: code cleanups * NGMimeFileData: code cleanup (v4.2.74) Mon Jan 27 19:08:28 2003 * v4.2.73 * NGMimeJoinedData: a mutable date wrapper to join date objects without merging them in memory * NGMimeFileData: a data object to store the date content on disk * NGMime*Generator: build mime parts on disk Wed Jan 22 17:26:17 2003 * NGMimeBodyGenerator.m: add configurable boundary prefix 2003-01-22 Helge Hess * NGMimeMultipartBodyParser.m: use incremental version (v4.2.72) Tue Jan 21 19:05:30 2003 * NGImap4: add additional Courier imapd support (v4.2.71) * v4.2.70 * NGImap4: increase class version number of NGMimeMessageParser * NGMimePartParser: if parsePartFromData got immutable data, parsing will be based on data bytes, increase version, add instance vars * NGMimeMultipartBodyParser.m: code cleanups Mon Jan 20 19:00:14 2003 * NGMimePartGenerator.m: fixed wrong release handling (v4.2.69) 2003-01-20 Helge Hess * NGConcreteMimeType.m: added support for vCalendar "method" parameters in text/* MIME types, replaced some RELEASE macros (v4.2.68) * replaced some RETAIN macros (v4.2.67) Fri Jan 17 13:49:17 2003 * NGImap4: fix variable placing (v4.2.66) Thu Jan 16 18:36:54 2003 * v4.2.65 * NGImap4: decode headers values fur bodystructures * NGMimePartParser: add +defaultHeaderFieldEncoding Tue Jan 14 16:57:28 2003 Jan Reichmann * NGImap4: improve body structure parsing * NGMimeType.m: allow all chars for parameter-values, use constant strings for some types, subtypes, parameternames (v4.2.64) 2003-01-14 Helge Hess * NGMimeType.m: added "koi-r" as an unsupported, but known encoding (v4.2.62) Tue Jan 14 12:24:44 2003 * NGImap4: improve error handling, handle unexpected BYE response (v4.2.61) * NGImap: fix parsing of cyrus version bug (skyrix bug 845) (v4.2.60) Mon Jan 13 19:42:47 2003 * v4.2.59 * NGMimePartParser: add fix header field names * NGImap4, NGPart.m, NGMimeHeaderFieldParser.m, NGMimeHeaderFieldGenerator.m, NGMimeBodyPart.m: use header field name constants 2003-01-13 Helge Hess * NGPart.h: added some docu to header Fri Jan 10 09:54:14 2003 * NGImap4: fixed skyrix bug 822, improve error handling (v4.2.58) Wed Jan 9 15:26:00 2003 * NGImap4: improve parsing to handle over quota warnings fix skyrix bug 777 (v4.2.57) Wed Jan 8 16:26:00 2003 * NGImap4: fix skyrix bug 835 (fix quota bugs) (v4.2.56) Tue Jan 7 16:47:36 2003 * NGImap4: fix skyrix bug 821 (add -usedSpace and -maxQuota to NGImap4Folder protocol and NGImap4ServerRoot) (v4.2.55) 2003-01-07 Helge Hess * changes for improved compilation on MacOSX, replaced RETAIN macros with methods (v4.2.54) Fri Dec 27 10:53:50 2002 Helge Hess * smaller clean ups (v4.2.53) Mon Dec 23 15:39:33 2002 Helge Hess * NGImap4: small cleanups (v4.2.52) 2002-12-17 Helge Hess * cosmetic change, replaced 'THROW' with 'raise' * NGMimeType.m: added big5, 'iso-2022-jp' and 'gb2312' as unsupported, but known encodings (SuSE Bug 16780) (v4.2.51) Tue Dec 10 19:12:45 2002 * NGImap4: add quota support 2002-12-07 Helge Hess * NGImap4: fixed a compilation warning (v4.2.49) * fixed Jan's version numbers Tue Dec 10 19:12:45 2002 * NGImap4ResponseParser.m: throw concrete exception (Bug 651) * NGImap4Folder.m, NGImap4ServerRoot: Default for display sub-folders * NGImap4Client.m: fixed debug release-bug (v4.2.48) * NGImap4ResponseParser.m: fix parse bug * NGImap4Message+BodyStructure.h: fix header handling (v4.2.47) Mon Dec 9 13:55:52 2002 * NGImap4Context.m, NGImap4Client.*, NGImap4ResponseParser: add capability support (v4.2.46) Fri Dec 6 17:08:28 2002 * NGImap4Folder (v4.2.45) * NGImap4Message: add some ss-sorting improvements Tue Dec 3 16:45:14 2002 * NGImap4ResponseParser.m: parse empty string if message does 'no longer exists' (v4.2.44) Mon Dec 2 19:22:13 2002 Jan Reichmann * NGImap4Context.m: performance improvements (v4.2.43) * NGImap4Folder.m: -(BUG 17379) clear msn->uid cache after delete -performance Mon Dec 2 11:18:51 2002 * NGImap4Folder.m: only reset subfolder if they are already loaded (v4.2.42) Fri Nov 29 18:12:32 2002 * NGMimePartParser.m: improve error log (v4.2.41) * NGMail/NGMimeMessageParser.m: fixed quoted printable parsing bug Fri Nov 29 12:27:25 2002 * NGImap4ResponseParser.m: check tagged responses before parsing it(v4.2.40) Mon Nov 25 16:29:40 2002 Jan Reichmann * NGImap4Context.m, NGImap4Folder: add msn-uid cache (v4.2.39) * NGImap4Folder.m: if no next mail, return nil (v4.2.38) * NGImap4Client.m: check whether sort keys are valid (v4.2.36) * NGImap4ResponseParser.m: fixed content parsing Fri Nov 22 15:04:18 2002 * NGImap4Message*: add support for body-structure content(v4.2.35) Fri Nov 22 11:13:40 2002 * NGImap4ResponseParser.m: add Imap4MMDataBoundary Default to modify MM-Data-Use boundary (v4.2.34) Tue Nov 21 18:13:38 2002 * NGImap4*: memory mapped data (v4.2.33) * NGImap4*: add fetch bodystructure/single part bodies (v4.2.32) 2002-11-20 Helge Hess * NGImap4: can query headers using KVC (4.2.31) * NGImap4: smaller changes in URL initialization (v4.2.30) Tue Nov 19 18:13:38 2002 * NGImap4*: add commands (thread, fetch body) (v4.2.29) Mon Nov 11 10:24:14 2002 Jan Reichmann * NGImap4Client.m: improve greetings parse behavior (v4.2.29) 2002-11-11 Helge Hess * NGImap4: initialize objects with URL and SSL support (v4.2.28) Wed Oct 30 16:26:46 2002 Jan Reichmann * NGMimePartParser.m retain/autorelease values to prevent RELEASE Exceptions (v4.2.27) 2002-09-30 Helge Hess * v4.2.25 * NGMimeHeaderFieldGenerator.m: fixed some compilation warnings 2002-08-29 Helge Hess * NGMimeHeaderFieldGenerator.m: small fix for Jaguar compilation Tue Aug 20 18:33:00 2002 Jan41 Reichmann * NGMimeHeaderFieldGenerator.m: add default for LF seperated address entries (v4.2.22) (BUG 17551) 2002-08-09 Helge Hess * NGMimeType.m: added windows-1252, iso-8859-2 as known charset strings (v4.2.20) - 2002-07-23 v4.2.19 (hh) - 2002-07-17 v4.2.18 (jr) - 2002-07-17 v4.2.17 (hh) - 2002-07-10 v4.2.16 (hh) - 2002-07-09 v4.2.15 (hh) - 2002-07-09 v4.2.14 (hh) - 2002-07-08 v4.2.13 (hh) - 2002-07-08 v4.2.12 (hh) 2002-07-09 Helge Hess * NGMimeType.m: added some charset encoding strings (8859-1, ks_c_5601-1987, euc-kr) * NGConcreteMimeType.m: do not print a warning if a "x-mac-" MIME type parameter was found ... Tue Jul 9 12:39:12 2002 Jan Reichmann * NGMime.m: add libraryVersion method 2002-07-08 Helge Hess * removed fix for -valueOfHeaderField:data:, since this breaks SKYRiXgreen => later 2002-07-08 Helge Hess * NGMimePartParser.m: immediatly close the datastream after parsing, so that the NSData object associated with the stream is guaranteed to be released (this lessens the possibility for a new variant of "The Big Master Bug") * NGMimeUtilities.h (_rfc2047Decoding): small optimization, if the data is base64 encoded, immediatly release the temporary NSData object used to call -dataByDecodingBase64: * NGMimeType.m: added a class method to turn charset strings into a Foundation NSStringEncoding constants (eg utf-8 => NSUTF8StringEncoding) * NGMimePartParser.m: cache the mutable data object used during parsing to avoid memory fragmentation and to improve speed * NGMimeBodyParser.m: moved multipart body parser to it's own file * NGMimePartParser.m ([NGMimePartParser -valueOfHeaderField:data:): fixed behaviour of method when a delegate is set. Previously if the delegate returned nil, the parser would invoke it's own header field parsing (while the doc says, that if the delegate implements the method, it's *completly* responsible ...) SEE ABOVE, fix removed * major source code cleanup to support hunting the bug known as "The Big Master Bug" (BMB, SuSE bug 16845) Fri Jun 28 17:27:16 2002 Jan41 Reichmann * NGMimeBodyGenerator.m: remove log * NGMimeHeaderFieldParser.m: add DateFormat Fri Jun 28 16:58:15 2002 Jan41 Reichmann * NGMimeBodyParser.m: compares charset caseInsensitive now Fri Jun 26 10:40:05 2002 Helge Hess * various fixes for MacOSX - 2002-06-13 v4.2.11 (jr) [extracted from CVS] - 2002-06-11 v4.2.10 (jr) [extracted from CVS] - 2002-06-10 v4.2.9 (jr) [extracted from CVS] - 2002-06-10 v4.2.8 (jr) [extracted from CVS] - 2002-06-09 v4.2.7 (jr) [extracted from CVS] - 2002-06-09 v4.2.6 (jr) [extracted from CVS] - 2002-06-07 v4.2.5 (jr) [extracted from CVS] Fri Jun 7 17:11:05 2002 Jan41 Reichmann * NGMime*: add better encoding handling - 2002-06-04 v4.2.4 (jr) [extracted from CVS] Tue Jun 4 17:47:30 2002 Jan41 Reichmann * NGMimeHeaderFieldParser.m: fixed euro handling Fri May 31 16:13:56 2002 Jan41 Reichmann * NGMimeHeaderFieldGenerator.m: add NGMimeAddressHeaderFieldGenerator, encoding of filenames - 2002-05-22 v4.2.3 (jr) [extracted from CVS] Wed May 15 13:23:03 2002 Helge Hess * added NGMail, NGImap4 subprojects Mon May 6 22:28:21 2002 Helge Hess * NGMimeHeaderFieldGenerator.m: fixed a problem with GroupWise (a space was generated before a MIME-type parameter value) Thu Mar 7 12:24:41 2002 Jan41 Reichmann * NGMimeBodyGenerator.m: fixed assertion bug Thu Feb 21 13:03:52 2002 Helge Hess * NGMimePartParser.m: changed to support -lastException Thu Feb 14 11:27:06 2002 Jan41 Reichmann * NGMimeHeaderFields.m: supports now ill microsoft content-disposition type Tue Dec 18 16:58:11 2001 Helge Hess * NGConcreteMimeType.m ([NGConcreteTextMimeType -initWithType:subType:parameters:]): parse "q" quality parameter Tue Dec 18 11:37:15 2001 Helge Hess * NGMimeBodyParser.m: added iso-8859-1 as a known charset Tue Dec 11 09:53:03 2001 Jan41 Reichmann * NGMimeHeaderFieldGenerator.m: fixed string value bug * NGMimeHeaderFieldParser.m: add date format Fri Dec 7 15:17:54 2001 Helge Hess * NGMimeBodyGenerator.m: fixed bug with content-type Mon Oct 22 19:00:59 2001 Helge Hess * NGMimePartParser.m ([NGMimePartParser -parserForBodyOfPart:data:]): use TextParser only for text/plain bodies Mon Oct 22 10:12:45 2001 Helge Hess * NGMimeHeaderFieldGenerator.m: changed to deal with string-header fields and replaced various -cString calls with -dataUsingEncoding: Tue Oct 16 19:21:15 2001 Helge Hess * NGMimeType.m: check for empty mime-type strings ... Tue Oct 16 18:59:39 2001 Helge Hess * NGMimeHeaderFieldGenerator.m: fixed static-var init bug Fri Oct 12 10:36:53 2001 Helge Hess * NGMimePartParser.m ([NGMimePartParser -parserForBodyOfPart:data:]): trim spaces of header-field values ... Thu Aug 9 14:21:45 2001 Helge Hess * removed java.mail related stuff Thu Aug 9 13:22:35 2001 Helge Hess * NGMimeFileDataSource.m: use -initWithPath:, no use of NGFileUrl Fri Jul 20 15:48:36 2001 Helge Hess * NGConcreteMimeType.m: allow parameters in wildcard MIME type Fri Apr 6 14:51:41 2001 Jan Reichmann * NGMimePartGenerator.m: fixed Autorelease/Release bug Wed Mar 28 17:55:21 2001 Jan Reichmann * NGMimeHeaderFieldParser.m: add new date formats Tue Feb 6 17:08:04 2001 Jan Reichmann * NGMimePartParser.m: fixed delegate message bug Mon Jan 29 16:27:23 2001 Jan Reichmann * NGMimeBodyParser.m, NGMimePartGenerator.m, NGMimePartParser.m: fixed header encoding bug Mon Dec 4 12:19:19 2000 Helge Hess * NGMimePartParser.m: changed to support empty HTTP headers (might break some email parsing ??) * NGMimePartParser.m: dynamically allocate parse buffer, added class caching Fri Jun 23 14:24:36 2000 Helge Hess * reverted changes from Jun-21 Fri Jun 23 12:21:32 2000 Helge Hess * NGMimeHeaderFieldParser.m: fixed stmt ordering bug Wed Jun 21 23:39:23 2000 Helge Hess * removed stack-buffer allocations in various methods Tue Jun 13 19:33:31 2000 Helge Hess * NGMimeHeaderFields.m: do not use stack-allocated buffers Fri Jun 9 17:50:00 2000 Helge Hess * GNUmakefile (ADDITIONAL_CPPFLAGS): added -Wall Tue Feb 29 18:24:39 2000 Helge Hess * MOF3 import 2000-02-17 * NGMimeHeaderFieldGenerator.m, NGMimeType, NGMimePartParser, NGMimeHeaderFields: removed cString stuff Wed Jan 26 11:11:23 2000 Jan Reichmann * NGMimeHeaderFieldParser.m: NGMimeRFC822DateHeaderFieldParser returns now a y2k date Mon Oct 25 15:07:36 1999 Helge Hess * NGConcreteMimeType.m: fixed bug in NGConcreteTextMimeType, fixed bugs in -stringValue of multipart-types Wed Oct 6 14:19:57 1999 Helge Hess * NGConcreteMimeType.m: added support for 'format' parameter in text/* types Mon Oct 4 10:23:32 1999 Helge Hess * NGMimePartParser.m: lowercase content-transfer-encoding, to catch both, 7bit and 7BIT and 7Bit ... Fri Oct 1 18:53:43 1999 Helge Hess * NGMimeHeaderFieldParser.m: added various date formats to Rfc822 date header scanner * NGMimePartParser.m: added '8bit' as a known content-transfer-encoding Thu Sep 2 21:04:32 1999 Helge Hess * added class versions and superclass version checks Mon Jul 12 22:36:45 1999 Helge Hess * NGMimePartGenerator.m: fixed bug (collection was modified while an enumerator was in use ..) Fri Jun 18 19:28:52 1999 Helge Hess * NGMimePartParser.m: filter out and apply content-transfer-encoding Tue Jun 15 11:22:29 1999 Jan Reichmann * removed quoted printable encoding from string header field parser * NGMimePartParser.m: lowercase MIME header field names on-the-fly Tue Jun 15 07:57:20 1999 Jan Reichmann * NGMimeHeaderFieldGenerator.m: insert parsing of date-field and quoted-printable encoding * NGMimeHeaderFieldParser.m : insert generating from NSDate date-field Tue Jun 1 16:48:38 1999 Jan Reichmann * NGMimeBodyGenerator.m: fixed bug (add generated boundary to multipart) Wed May 26 11:01:48 1999 Jan Reichmann * NGMimeBodyGenerator.m fixed nil-body bug Fri May 7 20:42:53 1999 Jan Reichmann * add -stringValue to NGMimeHeaderFields Tue May 4 16:16:47 1999 Helge Hess * added MIME generator classes Tue May 4 11:43:39 1999 Jan Reichmann * NGMimeBodyPartParser.m: fixed remove-comments bug Tue May 4 11:30:53 1999 Helge Hess * NGMimeBodyParser.m: added NGMimeRfc822BodyParser class * NGMimePartParser.m: added new delegate method to apply content transfer encoding like stuff on MIME bodies. Thu Apr 22 18:58:02 1999 Helge Hess * renamed NGMimeParser to NGMimePartParser Tue Apr 20 18:27:44 1999 Jan Reichmann * NGMimeParser.m: fixed content-length LA-bug Tue Apr 20 11:01:27 1999 Jan Reichmann * NGMimeBodyParser.m: end-of-line chars needn`t to be on end of boundary body can be less than 2 * boundary (remove assert) if start- or end-boundary wasn`t found the left over data were append to the multipart * NGMimeParser.m : check whether content-type, content-length, subject are already in headers * NGMimeType.m : fixed len bug Mon Apr 19 08:55:42 1999 Jan Reichmann * NGMimeParser.m: add delegate for use of content-length-field fixed read content-length bug Fri Apr 16 19:52:46 1999 Helge Hess * NGMimeParser.m: improved content-length parsing Fri Apr 16 18:48:35 1999 Helge Hess * NGMimeParser.m: rewritten to support MIME mails Fri Apr 16 12:33:46 1999 Helge Hess * NGMimeType.m, NGConcreteMimeType.[hm]: added 'name' parameter to text type and added x-vcard type * NGMimeType.m: make MIME type names and parameters lowercase * NGMimeBodyParser.m: added support for different EOL sequences * NGMimeParser.m: added delegates to parse a body of a part or to select a body parser for a body of a part. * NGConcreteMimeType.m: fixed bug, message/rfc822 is not a composite type Mon Apr 12 16:28:47 1999 Helge Hess * use #include instead of #import, made headers #include safe Mon Mar 29 11:39:45 1999 Helge Hess * added kit class NGMime * separate MIME parsers for messages and general MIME. Mon Jan 18 20:17:19 1999 Helge Hess * NGConcreteMimeType.m: fixed bug in NSConcreteTextMimeType -parametersAsDictionary method Sat Jan 9 21:09:29 1999 Helge Hess * NGMimeParser.m: new 'foundEOF' variable Tue Dec 15 17:56:40 1998 Helge Hess * NGConcreteMimeType.m: fixed -isEqual: of NGConcreteGenericMimeType Fri Nov 27 14:50:03 1998 Helge Hess * started WIN32 support Thu Nov 5 12:25:22 1998 Helge Hess * added NGMimeHeaderFields.[hm] with NGMimeContentDispositionHeaderField class in it. * NGMimeHeaderFieldParser.m: added NGMimeContentDispositionHeaderFieldParser class * added NGMimeBodyPart for parts contained in multiparts * made NSData/NSMutableData a NGMimePart * added NGMimeMultipartBody class Wed Nov 4 21:07:48 1998 Helge Hess * NGMimeType.m: bugfix in wildcard-type creation * NGConcreteMimeType.m: bugfix in wildcard matching * NGMimeBodyParser.m: added NGMimeMultipartBodyParser for parsing multipart bodies. Wed Nov 4 18:49:22 1998 Helge Hess * added NGMimeBodyPartParser for parsing the entities in multipart-bodies. * NGConcreteMimeType.m: added fast concrete implementations of comparison methods * NGMimeType.m: added advanced type-comparison/matching methods * Added new protocol and class NGMimeBodyParser responsible for parsing raw body data provided by the NGMimeParser. 1998-10-09 Helge Hess * created ChangeLog SOPE/sope-mime/NGMime/common.h0000644000000000000000000000241615004363604014776 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_common_H__ #define __NGMime_common_H__ /* common include files */ #import #if NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY # import # import #endif #include #include #include "NGMimeType.h" @interface NSObject(OSXHacks) - (void)subclassResponsibility:(SEL)_acmd; - (void)notImplemented:(SEL)_acmd; @end #endif /* __NGMime_common_H__ */ SOPE/sope-mime/NGMime/NGMimeContentDispositionHeaderFieldGenerator.m0000644000000000000000000000636515004363604024342 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeHeaderFieldGenerator.h" #include "NGMimeHeaderFields.h" #include "common.h" #include @implementation NGMimeContentDispositionHeaderFieldGenerator - (NSData *)generateDataForHeaderFieldNamed:(NSString *)_headerField value:(id)_value { NGMimeContentDispositionHeaderField *field; NSString *tmp; NSMutableData *data; field = _value; if (field == nil) { [self logWithFormat:@"WARNING(%s): Content-Disposition field is empty", __PRETTY_FUNCTION__]; return [NSData data]; } if ([_value isKindOfClass:[NSString class]]) return [_value dataUsingEncoding:NSUTF8StringEncoding]; // TODO: move the stuff below to some NSString or NSData category? data = [NSMutableData dataWithCapacity: 64]; tmp = [field type]; [data appendBytes:[tmp cString] length:[tmp length]]; tmp = [field filename]; if (tmp != nil) { [data appendBytes:"; " length:2]; [data appendBytes:"filename=\"" length:10]; const char* bytes; unsigned length; int cnt; BOOL doEnc; //d = [tmp dataUsingEncoding: NSUTF8StringEncoding]; //bytes = [d bytes]; //length = [d length]; bytes = [tmp cStringUsingEncoding: NSUTF8StringEncoding]; length = strlen(bytes); cnt = 0; doEnc = NO; while (cnt < length) { if ((unsigned char)bytes[cnt] > 127) { doEnc = YES; break; } cnt++; } if (doEnc) { char iso[] = "=?utf-8?q?"; unsigned isoLen = 10; char isoEnd[] = "?="; unsigned isoEndLen = 2; int desLen; char *des; bytes = [[tmp stringByReplacingOccurrencesOfString:@"\\\"" withString:@"\""] cStringUsingEncoding: NSUTF8StringEncoding]; length = strlen(bytes); desLen = length * 3 + 20; des = calloc(desLen + 2, sizeof(char)); memcpy(des, iso, isoLen); desLen = NGEncodeQuotedPrintableMime((unsigned char *)bytes, length, (unsigned char *)(des + isoLen), desLen - isoLen); if (desLen != -1) { memcpy(des + isoLen + desLen, isoEnd, isoEndLen); [data appendBytes:des length:(isoLen + desLen + isoEndLen)]; } else { [self logWithFormat:@"WARNING(%s:%i): An error occour during " @"quoted-printable decoding", __PRETTY_FUNCTION__, __LINE__]; if (des != NULL) free(des); } } else { [data appendBytes:[tmp cString] length:[tmp length]]; } [data appendBytes:"\"" length:1]; } return data; } @end /* NGMimeContentDispositionHeaderFieldGenerator */ SOPE/sope-mime/NGMime/NGMimeHeaderFields.m0000644000000000000000000001231715004363604017070 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeHeaderFields.h" #include "NGMimeUtilities.h" #include "common.h" NGMime_DECLARE NSString *NGMimeContentDispositionInlineType = @"inline"; NGMime_DECLARE NSString *NGMimeContentDispositionAttachmentType = @"attachment"; NGMime_DECLARE NSString *NGMimeContentDispositionFormType = @"form-data"; @implementation NGMimeContentDispositionHeaderField static int MimeLogEnabled = -1; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; MimeLogEnabled = [ud boolForKey:@"MimeLogEnabled"] ? 1 : 0; } - (id)initWithString:(NSString *)_value { unsigned len = [_value length]; unichar buf[len+1]; if (len == 0) { [self logWithFormat: @"WARNING(%s): no value for disposition header value!", __PRETTY_FUNCTION__]; self = [self autorelease]; return nil; } [_value getCharacters:buf]; buf[len] = '\0'; if ((self = [super init])) { unsigned cnt, start; cnt = 0; // skip leading spaces while (isRfc822_LWSP(buf[cnt])) cnt++; if (buf[cnt] == '\0') { if (MimeLogEnabled) [self logWithFormat:@"WARNING(%s): no value for disposition header" @" value !", __PRETTY_FUNCTION__]; self = [self autorelease]; return nil; } start = cnt; while ((buf[cnt] != ';') && (buf[cnt] != '\0') && !isRfc822_LWSP(buf[cnt])) cnt++; if (cnt <= start) { if (MimeLogEnabled) [self logWithFormat:@"WARNING(%s): found no type in disposition " @"header value (%@) !", __PRETTY_FUNCTION__, _value]; self = [self autorelease]; return nil; } self->type = [[[NSString alloc] initWithCharacters:buf+start length:(cnt - start)] autorelease]; start = 0; self->type = [self->type lowercaseString]; self->type = [self->type retain]; if (self->type == nil) { if (MimeLogEnabled) [self logWithFormat:@"WARNING(%s): found no type in disposition header " @"value (%@) !", __PRETTY_FUNCTION__, _value]; self = [self autorelease]; return nil; } self->parameters = [parseParameters(self, _value, buf+cnt) retain]; } return self; } - (id)init { return [self initWithString:nil]; } - (void)dealloc { [self->type release]; [self->parameters release]; [super dealloc]; } /* accessors */ - (NSString *)type { return self->type; } /* parameters */ - (NSString *)name { return [self->parameters objectForKey:@"name"]; } - (NSString *)filename { NSString *fn; fn = [self->parameters objectForKey:@"filename"]; if (![fn isNotNull]) fn = nil; if (![fn length]) { fn = [self name]; } return fn; } - (NSString *)valueOfParameterWithName:(NSString *)_name { return [self->parameters objectForKey:_name]; } - (BOOL)valueNeedsQuotes:(NSString *)_parameterValue { int len = [_parameterValue length]; unichar cstr[len + 1]; int cnt; [_parameterValue getCharacters:cstr]; for (cnt = 0; cnt < len; cnt++) { if (isMime_SpecialByte(cstr[cnt])) return YES; if (cstr[cnt] == 32) return YES; } return NO; } - (NSString *)parametersAsString { NSEnumerator *names; if ((names = [self->parameters keyEnumerator])) { NSMutableString *result = [NSMutableString stringWithCapacity:64]; NSString *name; while ((name = [names nextObject])) { id value = [[parameters objectForKey:name] stringValue]; [result appendString:@"; "]; [result appendString:name]; [result appendString:@"="]; if ([self valueNeedsQuotes:value]) { [result appendString:@"\""]; [result appendString:value]; [result appendString:@"\""]; } else [result appendString:value]; } return result; } else return nil; } - (NSString *)stringValue { NSMutableString *str; str = [NSMutableString stringWithCapacity:20]; [str appendString:type]; { NSString *paras = [self parametersAsString]; if (paras) [str appendString:paras]; } return str; } /* description */ - (NSString *)description { NSMutableString *d; d = [[NSMutableString alloc] init]; [d appendFormat:@"<%@[0x%p]: type=%@", NSStringFromClass([self class]), self, self->type]; if (self->parameters) [d appendFormat:@" parameters=%@", self->parameters]; [d appendString:@">"]; return [d autorelease]; } @end /* NGMimeContentDispositionHeaderField */ SOPE/sope-mime/NGMime/NGMimeJoinedData.h0000644000000000000000000000252415004363604016545 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGMimeJoinedData_H__ #define __NGMime_NGMimeJoinedData_H__ #import /* NGMimeJoinedData TODO: explain. Note: -copyWithZone: returns a _retained_ copy. Bug or feature? */ @class NSMutableArray; @interface NGMimeJoinedData : NSObject { NSMutableArray *joinedDataObjects; } - (void)appendData:(NSData *)_data; - (void)appendBytes:(const void *)_bytes length:(unsigned int)_length; - (BOOL)writeToFile:(NSString*)_path atomically:(BOOL)_useAuxiliaryFile; @end /* NGMimeJoinedData */ #endif /* __NGMime_NGMimeJoinedData_H__ */ SOPE/sope-mime/NGMime/NGMimeMultipartBodyParser.m0000644000000000000000000004026715004363604020532 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeBodyParser.h" #include "NGMimeBodyPartParser.h" #include "NGMimeMultipartBody.h" #include "common.h" #include @implementation NGMimeMultipartBodyParser static int MimeLogEnabled = -1; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; MimeLogEnabled = [ud boolForKey:@"MimeLogEnabled"] ? 1 : 0; } // returns the postion of the '\r' that starts the boundary static inline const char *_findNextBoundary(const char *_from, unsigned _len, const char *_boundary, unsigned _boundaryLen, BOOL _isFirst) { register unsigned pos = 0; register unsigned blen = _boundaryLen; if (_isFirst) { blen += 3; // -- + at least one EOL char at end of line if (_len < blen) return NULL; // too short to contain boundary for (pos = 0; (pos < _len) && (_len - pos > blen); pos++) { if ((_from[pos] == '-') && (_from[pos + 1] == '-')) { if (strncmp(&(_from[pos + 2]), _boundary, _boundaryLen) == 0) { // found boundary; return _from + pos; } } } } else { blen += 4; // -- + at least two EOL chars at start and end of line if (_len < blen) return NULL; // too short to contain boundary /* detect: --boundary(--)?CR CR--boundary(--)?CR CRLF--boundary(--)?CRLF LF--boundary(--)?LF */ for (pos = 0; (pos < _len) && ((_len - pos) > blen); pos++) { if (_from[pos] == '\n') { // check for LF-- if ((_from[pos + 1] == '-') &&(_from[pos + 2] == '-')) { // found LF-- if (strncmp(&(_from[pos + 3]), _boundary, _boundaryLen) == 0) // found LF--boundary return (_from + pos); } } else if (_from[pos] == '\r') { // check for CR.-? if ((_from[pos + 1] == '-') && (_from[pos + 2] == '-')) { // CHECK FOR CR-- // found CR-- if (strncmp(&(_from[pos + 3]), _boundary, _boundaryLen) == 0) // found LF--boundary return (_from + pos); } if ((_from[pos + 1] == '\n') && (_from[pos + 2] == '-') && (_from[pos + 3] == '-')) { // found CRLF-- if ((_len - pos) <= blen) { // remaining part is too short for boundary starting with CRLF break; } if (strncmp(&(_from[pos + 4]), _boundary, _boundaryLen) == 0) // found LF--boundary return (_from + pos); } } else if ((_from[pos] == '-') && (_from[pos + 1] == '-')) { if (strncmp(&(_from[pos + 2]), _boundary, _boundaryLen) == 0) { // found --boundary return (_from + pos); } } } } return NULL; } static inline BOOL _isEndBoundary(const char *_from, unsigned _len, const char *_boundary, unsigned _boundaryLen) { // no buffer out-of-bounds check, may cause segfault if (_len < (_boundaryLen + 8)) // + 2x CRLF and 2x '--' return YES; while (*_from != '-') _from++; // search first '-' _from += 2; // skip '--' _from += _boundaryLen; // skip boundary; return ((_from[0] == '-') && (_from[1] == '-')) ? YES : NO; } static inline const char * _skipBoundary(id self, const char *_from, unsigned _len, BOOL _first) { register unsigned pos = 0; register unsigned char c = 0; if (_from == NULL) return NULL; if (_from[0] == '-') { // skip '--' c = 0; // EOL needs to be detected } else if (_from[1] == '-') { // skip CR-- or LF-- c = _from[0]; if ((c != '\n') && (c != '\r')) { if (MimeLogEnabled) [self logWithFormat:@"WARNING(%s): invalid char before boundary '--'", __PRETTY_FUNCTION__]; } pos = 3; } else if (_from[2] == '-') { // skip CRLF-- c = _from[0]; if (c != '\r') { if (MimeLogEnabled) [self logWithFormat:@"WARNING(%s): missing CR before boundary 'LF--'", __PRETTY_FUNCTION__]; } c = _from[1]; if (c != '\n') { if (MimeLogEnabled) [self logWithFormat:@"WARNING(%s): missing LF before boundary '--' (after" @"CR)", __PRETTY_FUNCTION__]; } pos = 4; } else { if (MimeLogEnabled) [self logWithFormat:@"ERROR(%s): invalid parser state, skipping 4.", __PRETTY_FUNCTION__]; pos = 4; } while (pos < _len) { register unsigned char fc = _from[pos]; if (c == 0) { // EOL detect (on first line) if (fc == '\n') // LF break; if (fc == '\r') { // CR * if ((pos + 1) == _len) // CR EOF break; else if (_from[pos + 1] == '\n') { // CRLF pos++; // skip LF break; } else // CR break; } } else if (fc == c) // EOL char is known break; pos++; } if (pos < _len) pos++; // skip EOL char return &(_from[pos]); // return pointer to position after char } - (NSArray *)_parseBody:(NGMimeMultipartBody *)_body part:(id)_part data:(NSData *)_data boundary:(const char *)_boundary length:(unsigned)_boundaryLen delegate:(id)_delegate { NSMutableArray *result; NSAutoreleasePool *pool; const char *begin = NULL; const char *end = NULL; const char *buffer = [_data bytes]; unsigned len = [_data length]; BOOL isEOF = NO; NSCAssert(buffer, @"got no buffer"); NSCAssert(_boundary, @"got no boundary"); result = [NSMutableArray arrayWithCapacity:7]; // find first boundary and store prefix begin = _findNextBoundary(buffer, len, _boundary, _boundaryLen, YES); if (begin == NULL) { if (MimeLogEnabled) [self logWithFormat:@"WARNING(%s): Found multipart with no 1st boundary", __PRETTY_FUNCTION__]; [result addObject:_data]; return result; } pool = [[NSAutoreleasePool alloc] init]; { unsigned preLen = begin - buffer; if (preLen > 0) { if ([_delegate respondsToSelector: @selector(multipartBodyParser:foundPrefix:inMultipart:)]) { [_delegate multipartBodyParser:self foundPrefix:[NSData dataWithBytes:buffer length:preLen] inMultipart:_part]; } [_body setPrefix:[NSString stringWithCString:buffer length:preLen]]; } } // skip first boundary begin = _skipBoundary(self, begin, len - (begin - buffer), YES); NSCAssert(begin, @"could not skip 1st boundary .."); // loop over multipart bodies and exit if end-boundary is found do { /* check for boundary denoting end of current part */ end = _findNextBoundary(begin, len - (begin - buffer), _boundary,_boundaryLen, NO); if (end == NULL) { NSRange subDataRange; NSData *rawData = nil; if (MimeLogEnabled) [self logWithFormat:@"WARNING(%s): reached end of body without" @" end-boundary", __PRETTY_FUNCTION__]; subDataRange.location = (begin - buffer); subDataRange.length = ([_data length] + buffer - begin); rawData = [_data subdataWithRange:subDataRange]; if (rawData) [result addObject:rawData]; isEOF = YES; break; } else { NSRange subDataRange; NSData *rawData = nil; NSCAssert(end - begin >= 0, @"invalid range .."); subDataRange.location = (begin - buffer); subDataRange.length = (end - begin); rawData = [_data subdataWithRange:subDataRange]; if (rawData) { [result addObject:rawData]; } else { NSLog(@"WARNING(%s): could not create rawdata for " @" bodypart in multipart %@", __PRETTY_FUNCTION__, _part); } /* check whether last read boundary was an end boundary */ if (_isEndBoundary(end, len - (end - buffer), _boundary, _boundaryLen)) { isEOF = NO; break; } /* skip non-end boundary */ begin = _skipBoundary(self, end, len - (end - buffer), NO); } } while (begin); // skip end boundary and store suffix if (!isEOF) { if ((begin = _skipBoundary(self, end, len - (end - buffer), NO))) { unsigned sufLen; sufLen = len - (begin - buffer); if (sufLen > 0) { if ([_delegate respondsToSelector: @selector(multipartBodyParser: foundSuffix: inMultipart:)]) [_delegate multipartBodyParser:self foundSuffix:[NSData dataWithBytes:begin length:sufLen] inMultipart:_part]; [_body setSuffix:[NSString stringWithCString:begin length:sufLen]]; } } } /* result is not contained in this pool, so no need to retain ... */ RELEASE(pool); return result; } static NSString *_searchBoundary(NGMimeMultipartBodyParser *self, NSData *_data) { const char *buffer = [_data bytes]; int length = [_data length]; int pos = 0; BOOL found = NO; if (length < 3) return nil; if ((buffer[0] == '-') && (buffer[1] == '-')) { // no prefix found = YES; pos = 2; } else { while (pos + 5 < length) { if (buffer[pos + 2] != '-') { // if third char is not a '-' it cannot be a boundary start pos++; continue; } if (buffer[pos] == '\n') { // check for LF-- if (buffer[pos + 1] == '-') { // found LF-- pos += 3; found = YES; break; } } else if (buffer[pos] == '\r') { // check for CR.-? if ((buffer[pos + 1] == '-') ) { // CHECK FOR CR-- // found CR-- pos += 3; found = YES; break; } if ((buffer[pos + 1] == '\n') && (buffer[pos + 3] == '-')) { // found CRLF-- if ((length - pos) <= 4) { // remaining part is too short for boundary starting with CRLF break; } // found LF--boundary pos += 4; found = YES; break; } } pos++; } } if (found) { int boundLength = 0; buffer += pos; while (((boundLength + pos) < length) && (buffer[boundLength] != '\n') && (buffer[boundLength] != '\r')) { boundLength++; } if ((boundLength + pos) < length) { return [NSString stringWithCString:buffer length:boundLength]; } else return nil; } else return nil; } - (id)parseBodyPartWithData:(NSData *)_rawData inMultipart:(id)_multipart parser:(NGMimePartParser *)_parser { if (![_rawData length]) return nil; return [_parser parsePartFromData:_rawData]; } - (BOOL)parseBody:(NGMimeMultipartBody *)_body ofMultipart:(id)_part data:(NSData *)_data delegate:(id)_d { NGMimeType *contentType = nil; NSString *boundary = nil; NSArray *rawBodyParts = nil; BOOL foundError = NO; NSData *boundaryBytes; contentType = [_part contentType]; boundary = [contentType valueOfParameter:@"boundary"]; if (boundary == nil) boundary = _searchBoundary(self, _data); *(&foundError) = NO; boundaryBytes = [boundary dataUsingEncoding:NSISOLatin1StringEncoding]; *(&rawBodyParts) = [self _parseBody:_body part:_part data:_data boundary:[boundaryBytes bytes] length:[boundary length] delegate:_d]; if (rawBodyParts) { NGMimeBodyPartParser *bodyPartParser; unsigned i, count; BOOL askDelegate = NO; *(&count) = [rawBodyParts count]; *(&i) = 0; *(&bodyPartParser) = nil; if ([_d respondsToSelector: @selector(multipartBodyParser:parserForEntity:inMultipart:)]) { *(&askDelegate) = YES; } for (i = 0; i < count; i++) { NSString *reason = @"ERROR: could not parse body part at index %i in multipart %@: %@"; NGMimePartParser *parser; id rawData; id bodyPart; rawData = [rawBodyParts objectAtIndex:i]; *(&parser) = bodyPartParser; *(&bodyPart) = nil; if (askDelegate) { parser = [_d multipartBodyParser:self parserForEntity:rawData inMultipart:_part]; [parser setDelegate:_d]; } else if (bodyPartParser == nil) { bodyPartParser = [[NGMimeBodyPartParser alloc] init]; [bodyPartParser setDelegate:_d]; parser = bodyPartParser; } if (parser == nil) { if (rawData) { NSData *d; /* ensure that we have a copy, not a range on the full data */ d = [[NSData alloc] initWithBytes:[rawData bytes] length:[rawData length]]; [_body addBodyPart:d]; RELEASE(d); } } else { NS_DURING { if ([rawData length]) bodyPart = [self parseBodyPartWithData:rawData inMultipart:_part parser:parser]; } NS_HANDLER { NSLog(reason, i, _part, localException); foundError = YES; } NS_ENDHANDLER; if (bodyPart) { [_body addBodyPart:bodyPart]; } parser = nil; } } RELEASE(bodyPartParser); bodyPartParser = nil; } return foundError; } - (BOOL)parseImmediatlyWithDelegate:(id)_delegate multipart:(id)_part data:(NSData *)_data { if ([_delegate respondsToSelector: @selector(multipartBodyParser:immediatlyParseBodyOfMultipart:data:)]) { BOOL result; result = [_delegate multipartBodyParser:self immediatlyParseBodyOfMultipart:_part data:_data]; return result; } else return YES; } - (id)parseBodyOfPart:(id)_part data:(NSData *)_data delegate:(id)_d { NGMimeMultipartBody *body; NGMimeType *contentType; NSString *boundary; unsigned len; contentType = [_part contentType]; boundary = [contentType valueOfParameter:@"boundary"]; len = [_data length]; if (len == 0) return nil; if (contentType == nil) { NSLog(@"ERROR [%s]: part %@ has no content type, cannot find out " @"the boundary !", __PRETTY_FUNCTION__, _part); return _data; } if (![contentType isCompositeType]) { NSLog(@"ERROR [%s]: content type %@ of part %@ is not composite !", __PRETTY_FUNCTION__, contentType, _part); return _data; } if (boundary == nil) { if (!(boundary = _searchBoundary(self, _data))) { NSLog(@"ERROR [%s]: no boundary parameter in content " @"type %@ of part %@ !", __PRETTY_FUNCTION__, contentType, _part); return _data; } } if ([boundary length] > 70) { if (MimeLogEnabled) [self logWithFormat:@"WARNING(%s): got boundary longer than 70 chars " @"(not allowed by RFC) in type %@", __PRETTY_FUNCTION__, contentType]; } if ([self parseImmediatlyWithDelegate:_d multipart:_part data:_data]) { body = [[NGMimeMultipartBody alloc] initWithPart:_part]; body = AUTORELEASE(body); if (![self parseBody:body ofMultipart:_part data:_data delegate:_d]) ; // error } else { body = [[NGMimeMultipartBody alloc] initWithPart:_part data:_data delegate:_d]; body = AUTORELEASE(body); } return body; } @end /* NGMimeMultipartBodyParser */ SOPE/sope-mime/NGMime/NGMimeHeaderFieldParser.m0000644000000000000000000000700215004363604020055 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeHeaderFieldParser.h" #include "NGMimeHeaderFields.h" #include "NGMimeUtilities.h" #include "common.h" #include @implementation NGMimeHeaderFieldParser static int MimeLogEnabled = -1; static int StripLeadingSpaces = -1; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; if (MimeLogEnabled == -1) MimeLogEnabled = [ud boolForKey:@"MimeLogEnabled"]?1:0; if (StripLeadingSpaces == -1) StripLeadingSpaces = [ud boolForKey:@"StripLeadingSpaces"]?1:0; } + (BOOL)isMIMELogEnabled { return MimeLogEnabled ? YES : NO; } + (BOOL)doesStripLeadingSpaces { return StripLeadingSpaces ? YES : NO; } - (NSString *)removeCommentsFromValue:(NSString *)_rawValue { unsigned int len = [_rawValue length]; unichar bytes[len + 1]; unsigned int cnt; NSString *str; if (_rawValue == NULL) return nil; [_rawValue getCharacters:bytes]; bytes[len] = '\0'; cnt = 0; str = nil; while ((cnt < len) && (bytes[cnt] != '(')) cnt++; if (cnt < len) { unichar result[len+1]; int resLen, commentNesting, begin; BOOL modifyValue; resLen = 0; commentNesting = 0; begin = 0; modifyValue = NO; for (cnt = 0; cnt < len; cnt++) { if (commentNesting == 0) { if (isRfc822_QUOTE(bytes[cnt])) { cnt++; while ((cnt < len) && !isRfc822_QUOTE(bytes[cnt])) cnt++; } else if (bytes[cnt] == '(') { modifyValue = YES; if ((cnt - begin) > 0) { int c; for (c = begin; c < cnt; c++) result[resLen++] = bytes[c]; } commentNesting++; } } else { if (bytes[cnt] == ')') { commentNesting--; if (commentNesting == 0) begin = (cnt + 1); } else if (bytes[cnt] == '(') commentNesting++; } } if (modifyValue) { if ((cnt - begin) > 0) { int c; for (c = begin; c < cnt; c++) result[resLen++] = bytes[c]; } str = [[[NSString alloc] initWithCharacters:result length:resLen] autorelease]; } } if (str == nil) str = _rawValue; if (MimeLogEnabled) { if (str != _rawValue) { [self logWithFormat:@"%s:%d remove comment [%@] -> [%@]", __PRETTY_FUNCTION__, __LINE__, _rawValue, str]; } } return str; } - (NSData *)quotedPrintableDecoding:(NSData *)_value { return _value; } - (id)parseValue:(id)_data ofHeaderField:(NSString *)_field { // abstract NSLog(@"ERROR(%s): subclass should override this method: %@", __PRETTY_FUNCTION__, self); return nil; } @end /* NGMimeHeaderFieldParser */ SOPE/sope-mime/NGMime/COPYING0000644000000000000000000006130315004363604014370 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-mime/NGMime/NGMimeBodyPart.h0000644000000000000000000000371315004363604016270 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGMimeBodyPart_H__ #define __NGMime_NGMimeBodyPart_H__ #import #include @class NGHashMap; /* NGMimeBodyPart is a part that is contained in a multipart body. */ @class NSString, NSArray, NSDictionary, NSEnumerator; @class NGMutableHashMap; @interface NGMimeBodyPart : NSObject < NGMimePart > { @protected NGMutableHashMap *header; id body; } + (id)bodyPartWithHeader:(NGHashMap *)_headers; - (id)initWithHeader:(NGHashMap *)_headers; // designated initializer /* NGPart */ - (NSEnumerator *)valuesOfHeaderFieldWithName:(NSString *)_name; - (NSEnumerator *)headerFieldNames; - (void)setBody:(id)_body; - (id)body; /* NGMimePart */ - (NGMimeType *)contentType; - (NSString *)contentId; - (NSArray *)contentLanguage; - (NSString *)contentMd5; - (NSString *)encoding; - (NSString *)contentDescription; /* convenience */ - (NSString *)headerForKey:(NSString *)_key; - (void) setHeader: (id) _header forKey: (NSString *)_key; - (NSArray *)headersForKey:(NSString *)_key; - (NSArray *)headerKeys; - (NSDictionary *)headers; - (NSString *)headersAsString; - (NSDictionary *) bodyInfo; @end #endif /* __NGMime_NGMimeBodyPart_H__ */ SOPE/sope-mime/NGMime/README0000644000000000000000000000403615004363604014215 0ustar rootrootNGMime ====== Defaults ======== Mail_Use_8bit_Encoding_For_Text - bool - Use 8bit content-transfer-encoding for text messages UseLFSeperatedAddressEntries - bool NGMime_MultipartBoundaryPrefix - string UseFoundationStringEncodingForMimeText - bool NGMimeBuildMimeTempDirectory - string - "/tmp/" MimeLogEnabled - bool StripLeadingSpaces - bool Removed in SKYRiX 4.1, available in MOF3 ======================================== java.mail related stuff: NGMimeFileDataSource NGMimeFileTypeMap NGMimeCommandMap NGMimeDataHandler NGMime Objective-C Kit ====================== Class-Hierachy NSObject NGMimeType < NSCopying, NSCoding > NGParameterMimeType NGConcreteApplicationMimeType NGConcreteMultipartMimeType NGConcreteMessageMimeType NGConcreteImageMimeType NGConcreteAudioMimeType NGConcreteVideoMimeType NGConcreteTextMimeType NGConcreteAppOctetMimeType NGConcreteGenericMimeType NGConcreteWildcardType NGMimeBodyParser < NGMimeBodyParser > NGMimeTextBodyParser NGMimeMultipartBodyParser NGMimeBodyPart < NGPart, NGMimePart > NGMimeHeaderFieldParser < NGMimeHeaderFieldParser > NGMimeContentTypeHeaderFieldParser NGMimeContentLengthHeaderFieldParser NGMimeStringHeaderFieldParser NGMimeHeaderFieldParserSet < NGMimeHeaderFieldParser,NSCopying > NGMimeMultipartBody NGMimePartParser NGMimeBodyPartParser NSException NGMimeException NGMimeParserException Protocols NSObject+NGMimeParserDelegate NGMimeBodyParser NGMimeHeaderFieldParser NGPart NGMimePart < NGPart > Categories NSData+DataPart NSMutableData+DataPart -- Helge Hess (helge.hess@opengroupware.org) 1998-11-04 updated: 2002-07-08 updated: 2004-06-20 SOPE/sope-mime/NGMime/NGMimeRfc822BodyGenerator.m0000644000000000000000000000277215004363604020210 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeBodyGenerator.h" #include "NGMimePartGenerator.h" #include "common.h" @implementation NGMimeRfc822BodyGenerator - (id)generatorForPart:(id)_part { id g; g = [[[NGMimePartGenerator alloc] init] autorelease]; [g setUseMimeData:self->useMimeData]; return g; } - (NSData *)generateBodyOfPart:(id)_part additionalHeaders:(NGMutableHashMap *)_addHeaders delegate:(id)_delegate { NSData *data; NGMimePartGenerator *gen; gen = (NGMimePartGenerator *)[self generatorForPart:_part]; [gen setDelegate:_delegate]; data = [gen generateMimeFromPart:[_part body]]; return data; } @end /* NGMimeRfc822BodyGenerator */ SOPE/sope-mime/NGMime/NGMimeContentDispositionHeaderFieldParser.m0000644000000000000000000000426715004363604023647 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeHeaderFieldParser.h" #include "NGMimeHeaderFields.h" #include "NGMimeUtilities.h" #include "common.h" @implementation NGMimeContentDispositionHeaderFieldParser static BOOL StripLeadingSpaces = NO; static BOOL MimeLogEnabled = NO; + (void)initialize { StripLeadingSpaces = [self doesStripLeadingSpaces]; MimeLogEnabled = [self isMIMELogEnabled]; } - (id)parseValue:(id)_data ofHeaderField:(NSString *)_field { unsigned len = [_data length]; unichar src[len + 1]; unsigned cnt; BOOL didModify; NSString *str; didModify = NO; cnt = 0; [_data getCharacters:src]; /* strip leading spaces */ if (StripLeadingSpaces) { while (isRfc822_LWSP(src[cnt]) && (len > 0)) { cnt++; len--; didModify = YES; } } /* strip trailing spaces */ while (len > 0) { if (isRfc822_LWSP(src[len - 1])) { len--; didModify = YES; } else break; } if (len == 0) { if (MimeLogEnabled) [self logWithFormat:@"WARNING(%s): empty value for header field %@ ..", __PRETTY_FUNCTION__, _field]; return nil; } str = nil; str = (didModify) ? [NSString stringWithCharacters:(src + cnt) length:len] : _data; return [[[NGMimeContentDispositionHeaderField alloc] initWithString:str] autorelease]; } @end /* NGMimeContentDispositionHeaderFieldParser */ SOPE/sope-mime/NGMime/NGMimeContentLengthHeaderFieldGenerator.m0000644000000000000000000000250315004363604023245 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeHeaderFieldGenerator.h" #include "NGMimeHeaderFields.h" #include "common.h" @implementation NGMimeContentLengthHeaderFieldGenerator - (NSData *)generateDataForHeaderFieldNamed:(NSString *)_headerField value:(id)_value { // TODO: rewrite for ASCII and plain buffer - much faster ... if (_value == nil) { NSLog(@"WARNING(%s): empty content length field", __PRETTY_FUNCTION__); return [NSData data]; } return [[_value stringValue] dataUsingEncoding:NSUTF8StringEncoding]; } @end /* NGMimeContentLengthHeaderFieldGenerator */ SOPE/sope-mime/NGMime/NGMimeHeaderFieldGenerator.h0000644000000000000000000000553515004363604020553 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGHeaderFieldGenerator_H__ #define __NGMime_NGHeaderFieldGenerator_H__ #import #include @class NSString, NSData, NSMutableDictionary; @interface NGMimeHeaderFieldGenerator : NSObject + (id)headerFieldGenerator; + (NSString *)encodeQuotedPrintableWord: (NSString *)word; + (NSString *)encodeQuotedPrintableText: (NSString *)text; - (NSData *)generateDataForHeaderFieldNamed:(NSString *)_headerField value:(id)_value; @end @interface NGMimeContentTypeHeaderFieldGenerator : NGMimeHeaderFieldGenerator @end @interface NGMimeContentLengthHeaderFieldGenerator : NGMimeHeaderFieldGenerator @end @interface NGMimeRFC822DateHeaderFieldGenerator : NGMimeHeaderFieldGenerator @end @interface NGMimeContentDispositionHeaderFieldGenerator : NGMimeHeaderFieldGenerator @end @interface NGMimeStringHeaderFieldGenerator : NGMimeHeaderFieldGenerator @end @interface NGMimeAddressHeaderFieldGenerator : NGMimeHeaderFieldGenerator @end @interface NGMimeHeaderFieldGeneratorSet : NSObject { @protected NSMutableDictionary *fieldNameToGenerate; id defaultGenerator; } + (id)headerFieldGeneratorSet; + (id)defaultRfc822HeaderFieldGeneratorSet; - (id)init; - (id)initWithDefaultGenerator:(id)_gen; /* accessors */ - (void)setGenerator:(id)_gen forField:(NSString *)_name; - (void)setDefaultGenerator:(id)_gen; - (id)_gen; /* operation */ - (NSData *)generateDataForHeaderFieldNamed:(NSString *)_headerField value:(id)_value; @end extern BOOL NGEncodeQuotedPrintableMimeNeeded(const unsigned char *src, unsigned srcLen); extern int NGEncodeQuotedPrintableMime(const unsigned char *src, unsigned srcLen, unsigned char *dest, unsigned destLen); #endif // __NGMime_NGHeaderFieldGenerator_H__ SOPE/sope-mime/NGMime/NGMimePartGenerator.m0000644000000000000000000003552615004363604017335 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimePartGenerator.h" #include "NGMimeHeaderFieldGenerator.h" #include "NGMimeBodyGenerator.h" #include "NGMimeJoinedData.h" #include #include #include "common.h" @implementation NGMimePartGenerator static NSDictionary *standardCapitalizedHeaders = nil; static NSProcessInfo *Pi = nil; static BOOL debugOn = NO; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; debugOn = [ud boolForKey:@"NGMimeGeneratorDebugEnabled"]; //if (debugOn) // NSLog(@"WARNING[%@]: NGMimeGeneratorDebugEnabled is enabled!", self); if (Pi == nil) Pi = [[NSProcessInfo processInfo] retain]; if (standardCapitalizedHeaders == nil) { // See https://tools.ietf.org/html/rfc4021 for a good list standardCapitalizedHeaders = [NSDictionary dictionaryWithObjectsAndKeys: @"Content-ID", @"content-id", @"Content-MD5", @"content-md5", @"Discarded-X400-IPMS-Extensions", @"discarded-x400-ipms-extensions", @"Discarded-X400-MTS-Extensions", @"discarded-x400-mts-extensions", @"DL-Expansion-History", @"dl-expansion-history", @"List-ID", @"list-id", @"Message-ID", @"message-id", @"MIME-Version", @"mime-version", @"Original-Message-ID", @"original-message-id", @"PICS-Label", @"pics-label", @"Resent-Message-ID", @"resent-message-id", @"X400-MTS-Identifier", @"x400-mts-identifier", nil]; [standardCapitalizedHeaders retain]; } } + (id)mimePartGenerator { return [[[self alloc] init] autorelease]; } - (id)init { if ((self = [super init])) { self->part = nil; self->delegate = nil; self->appendBytes = NULL; } return self; } - (void)dealloc { [self->result release]; [self->part release]; self->appendBytes = NULL; [super dealloc]; } /* setting the delegate */ - (void)setDelegate:(id)_delegate { self->delegate = _delegate; self->delegateRespondsTo.generatorGenerateDataForHeaderField = [self->delegate respondsToSelector: @selector(mimePartGenerator:generateDataForHeaderField:value:)]; self->delegateRespondsTo.generatorGeneratorForBodyOfPart = [self->delegate respondsToSelector: @selector(mimePartGenerator:generatorForBodyOfPart:)]; self->delegateRespondsTo.generatorGenerateDataForBodyOfPart = [self->delegate respondsToSelector: @selector(mimePartGenerator:generateDataForBodyOfPart:additionalHeaders:)]; } - (id)delegate { return self->delegate; } - (BOOL)prepareForGenerationOfPart:(id)_part { ASSIGN(self->part, _part); if (self->result) { [self->result release]; self->result = nil; } self->result = (self->useMimeData) ? (NSMutableData*)[[NGMimeJoinedData alloc] init] : [[NSMutableData alloc] initWithCapacity:4096]; if ([self->result respondsToSelector:@selector(methodForSelector:)]) { self->appendBytes = (void(*)(id,SEL,const void *, unsigned)) [self->result methodForSelector: @selector(appendBytes:length:)]; } else self->appendBytes = NULL; return YES; } - (BOOL)generatePrefix { return YES; } - (void)generateSuffix { } - (id)generatorForHeaderField:(NSString *)_name { return [NGMimeHeaderFieldGeneratorSet defaultRfc822HeaderFieldGeneratorSet]; } - (NSData *)generateDataForHeaderField:(NSString *)_headerField value:(id)_value { NSData *data; if (self->delegateRespondsTo.generatorGenerateDataForHeaderField) { data = [self->delegate mimePartGenerator:self generateDataForHeaderField:_headerField value:_value]; } else { data = [[self generatorForHeaderField:_headerField] generateDataForHeaderFieldNamed:_headerField value:_value]; } return data; } - (BOOL)isMultiValueCommaHeaderField:(NSString *)_headerField { /* This is used by NGMimeMessageGenerator to encode multivalue To/Cc/Bcc in a single line. */ return NO; } - (BOOL)appendHeaderField:(NSString *)_field values:(NSEnumerator *)_values toData:(NSMutableData *)_data { /* returns whether data was generated */ const unsigned char *fcname; id value = nil; unsigned len, line_len; BOOL isMultiValue, isFirst; /* get field name and strip leading spaces */ // We capitalize headers to avoid spam filters from increasing // their score level if ([standardCapitalizedHeaders objectForKey: _field]) _field = [standardCapitalizedHeaders objectForKey: _field]; else _field = [_field asCapitalizedHeader]; fcname = (const unsigned char *)[_field cStringUsingEncoding:NSISOLatin1StringEncoding]; for (len = [_field lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding]; len > 0; fcname++, len--) { if (*fcname != ' ') break; } isMultiValue = [self isMultiValueCommaHeaderField:_field]; isFirst = YES; line_len = 0; while ((value = [_values nextObject]) != nil) { NSData *data; if ((data = [self generateDataForHeaderField: [_field lowercaseString] value:value]) == nil) continue; if (isMultiValue) { if (isFirst) { [_data appendBytes:fcname length:len]; [_data appendBytes:": " length:2]; isFirst = NO; line_len = len+2; } else { // Line MUST be no more than 998 characters. This is RFC-enforced. if (line_len + [data length] + 2 <= 998) { [_data appendBytes:", " length:2]; line_len += 2; } else { [_data appendBytes:",\r\n " length:4]; line_len = 1; } } [_data appendData:data]; line_len += [data length]; } else { [_data appendBytes:fcname length:len]; [_data appendBytes:": " length:2]; [_data appendData:data]; [_data appendBytes:"\r\n" length:2]; } } if (!isFirst && isMultiValue) [_data appendBytes:"\r\n" length:2]; return isFirst; } - (NSData *)generateHeaderData:(NGHashMap *)_additionalHeaders { NSEnumerator *headerFieldNames = nil; NSString *headerFieldName = nil; NGMutableHashMap *addHeaders = nil; NSMutableData *data; NSMutableArray *allHeaderFieldNames; NSUInteger index; data = (self->useMimeData) ? [[[NGMimeJoinedData alloc] init] autorelease] : [NSMutableData dataWithCapacity:2048]; // We make sure the From header is always the first one. // That can cause issues otherwise in Outlook's Sent items allHeaderFieldNames = [NSMutableArray arrayWithArray: [[self->part headerFieldNames] allObjects]]; index = [allHeaderFieldNames indexOfObject: @"from"]; if (index != NSNotFound) [allHeaderFieldNames exchangeObjectAtIndex: 0 withObjectAtIndex: index]; headerFieldNames = [allHeaderFieldNames objectEnumerator]; addHeaders = [_additionalHeaders mutableCopy]; while ((headerFieldName = [headerFieldNames nextObject]) != nil) { NSEnumerator *enumerator; BOOL reset; if ([[_additionalHeaders objectsForKey:headerFieldName] count] > 0) { enumerator = [addHeaders objectEnumeratorForKey:headerFieldName]; reset = YES; } else { reset = NO; enumerator = [self->part valuesOfHeaderFieldWithName:headerFieldName]; } [self appendHeaderField:headerFieldName values:enumerator toData:data]; if (reset) [addHeaders removeAllObjectsForKey:headerFieldName]; } headerFieldNames = [addHeaders keyEnumerator]; while ((headerFieldName = [headerFieldNames nextObject]) != nil) { [self appendHeaderField:headerFieldName values:[addHeaders objectEnumeratorForKey:headerFieldName] toData:data]; } [addHeaders release]; addHeaders = nil; return data; } - (NGMimeType *)defaultContentTypeForPart:(id)_part { static NGMimeType *octetStreamType = nil; if (octetStreamType == nil) octetStreamType = [[NGMimeType mimeType:@"application/octet-stream"] copy]; return octetStreamType; } - (id)defaultBodyGenerator { id gen; gen = [[[NGMimeBodyGenerator alloc] init] autorelease]; [(id)gen setUseMimeData:self->useMimeData]; return gen; } - (id)generatorForBodyOfPart:(id)_part { id bodyGen = nil; NGMimeType *contentType = nil; NSString *type = nil; if (self->delegateRespondsTo.generatorGeneratorForBodyOfPart) { bodyGen = [self->delegate mimePartGenerator:self generatorForBodyOfPart:self->part]; } if (bodyGen == nil) { contentType = [_part contentType]; if (contentType == nil) contentType = [self defaultContentTypeForPart:_part]; if (contentType == nil) { [self logWithFormat:@"WARNING(%s): no content-type",__PRETTY_FUNCTION__]; return nil; } type = [contentType type]; if ([type isEqualToString:NGMimeTypeMultipart]) { bodyGen = [[[NGMimeMultipartBodyGenerator alloc] init] autorelease]; } else if ([type isEqualToString:NGMimeTypeText]) { bodyGen = [[[NGMimeTextBodyGenerator alloc] init] autorelease]; } else if (([type isEqualToString:NGMimeTypeMessage]) && [[contentType subType] isEqualToString:@"rfc822"]) { bodyGen = [[[NGMimeRfc822BodyGenerator alloc] init] autorelease]; } } [(id)bodyGen setUseMimeData:self->useMimeData]; return bodyGen; } - (NSData *)generateBodyData:(NGMutableHashMap *)_additionalHeaders { NSData *data = nil; id bodyGen = nil; id body; /* ask delegate whether it wants to deal with the part */ if (self->delegateRespondsTo.generatorGenerateDataForBodyOfPart) { data = [self->delegate mimePartGenerator:self generateDataForBodyOfPart:self->part additionalHeaders:_additionalHeaders]; return data; } /* lookup generator object or use default generator */ bodyGen = [self generatorForBodyOfPart:self->part]; if (bodyGen == nil) { /* no generator for body */ bodyGen = [self defaultBodyGenerator]; if (debugOn) { [self debugWithFormat:@"Note: using default generator %@ for part: %@", bodyGen, self->part]; } } [(id)bodyGen setUseMimeData:self->useMimeData]; /* generate */ if (bodyGen != nil) { data = [bodyGen generateBodyOfPart:self->part additionalHeaders:_additionalHeaders delegate:self->delegate]; return data; } /* fallback, try to encode NSString and NSData objects */ body = [self->part body]; [self logWithFormat:@"WARNING(%s): class has no defaultBodyGenerator", __PRETTY_FUNCTION__]; if ([body isKindOfClass:[NSData class]]) data = body; else if ([body isKindOfClass:[NSString class]]) data = [body dataUsingEncoding: NSISOLatin1StringEncoding]; else data = nil; return data; } - (void)generateData { NGMutableHashMap *additionalHeaders; NSData *bodyData; NSData *headerData; /* the body generator will fill in headers if required */ additionalHeaders = [[NGMutableHashMap alloc] initWithCapacity:16]; if (debugOn) { [self debugWithFormat:@"generate part: 0x%p<%@>", self->part, NSStringFromClass([self->part class])]; } bodyData = [self generateBodyData:additionalHeaders]; if (debugOn) { [self debugWithFormat:@" => body 0x%p<%@> length=%d", bodyData, NSStringFromClass([bodyData class]), [bodyData length]]; } headerData = [self generateHeaderData:additionalHeaders]; if (debugOn) { [self debugWithFormat:@" => header 0x%p<%@> length=%d", headerData, NSStringFromClass([headerData class]), [headerData length]]; } if (headerData != nil) { // TODO: length check is new, this should be correct, but might be wrong. // Some strange things occur if we generate a part which is a // NGMimeFileData (this method was called twiced, once without header // data which in turn resulted in a superflous "\r\n" string if ([headerData length] > 0) { [self->result appendData:headerData]; // We pad so our output buffer's with an extra \n\r to avoid Outlook data corruption. // See: http://answers.microsoft.com/en-us/office/forum/office_2010-outlook/outlook-2010-decodes-pdf-attachment-as-all-zero/51012fe5-9d5e-431d-9d9c-a37b0171264a?page=2 // for more details. [self->result appendBytes:"\r\n" length:2]; } if (bodyData != nil) { [self->result appendData:bodyData]; [self->result appendBytes:"\r\n" length:2]; } else if (debugOn) [self debugWithFormat:@" => did not generate any body data!"]; } else if (debugOn) [self debugWithFormat:@" => did not generate any header data!"]; [additionalHeaders release]; additionalHeaders = nil; } - (NSData *)generateMimeFromPart:(id)_part { NSData *data; [self prepareForGenerationOfPart:_part]; if (![self generatePrefix]) return nil; [self generateData]; [self generateSuffix]; data = self->result; self->result = nil; return [data autorelease]; } - (NSString *)generateMimeFromPartToFile:(id)_part { NSString *filename = nil; static NSString *TmpPath = nil; if (TmpPath == nil) { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; TmpPath = [ud stringForKey:@"NGMimeBuildMimeTempDirectory"]; if (TmpPath == nil) TmpPath = @"/tmp/"; TmpPath = [[TmpPath stringByAppendingPathComponent:@"OGo"] copy]; } filename = [Pi temporaryFileName:TmpPath]; [self setUseMimeData:YES]; if (![[self generateMimeFromPart:_part] writeToFile:filename atomically:YES]) { [self errorWithFormat: @"couldn`t write data to temorary file %@", filename]; return nil; } return filename; } - (id)part { return self->part; } - (void)setUseMimeData:(BOOL)_b { self->useMimeData = _b; } - (BOOL)useMimeData { return self->useMimeData; } /* debugging */ - (BOOL)isDebuggingEnabled { return debugOn; } @end /* NGMimePartGenerator */ SOPE/sope-mime/NGMime/NGMimeFileData.m0000644000000000000000000001253115004363604016220 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeFileData.h" #include "common.h" #include #include #include #include #include @implementation NGMimeFileData static NSString *TmpPath = nil; static NSProcessInfo *Pi = nil; static unsigned tmpmask = 0600; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; if (TmpPath == nil) { TmpPath = [ud stringForKey:@"NGMimeBuildMimeTempDirectory"]; if (TmpPath == nil) TmpPath = @"/tmp/"; TmpPath = [[TmpPath stringByAppendingPathComponent:@"OGo"] copy]; } if (Pi == nil) Pi = [[NSProcessInfo processInfo] retain]; } - (id)initWithPath:(NSString *)_path removeFile:(BOOL)_remove { #if !GNUSTEP_BASE_LIBRARY /* see OGo bug #1890, the gstep-base -init clashes and we don't exactly need it ... (but I guess its better to call it on other Foundations) */ if ((self = [super init]) != nil) { #endif if (![[NSFileManager defaultManager] fileExistsAtPath:_path]) { NSLog(@"ERROR[%s]: missing file at path %@", __PRETTY_FUNCTION__, _path); [self release]; return nil; } self->path = [_path copy]; self->removeFile = _remove; self->length = -1; #if !GNUSTEP_BASE_LIBRARY } #endif return self; } - (id)initWithBytes:(const void*)_bytes length:(NSUInteger)_length { NSString *filename = nil; int fd; filename = [Pi temporaryFileName:TmpPath]; fd = open([filename fileSystemRepresentation], O_WRONLY | O_CREAT | O_TRUNC, tmpmask); if (fd == -1) { fprintf(stderr, "Could not open file for writing %s: %s\n", [filename fileSystemRepresentation], strerror(errno)); [self release]; return nil; } if (write(fd, _bytes, _length) != (int)_length) { fprintf(stderr, #if GS_64BIT_OLD "Failed to write %i bytes to %s: %s\n", #else "Failed to write %li bytes to %s: %s\n", #endif _length, [filename fileSystemRepresentation], strerror(errno)); close(fd); [self release]; return nil; } close(fd); return [self initWithPath:filename removeFile:YES]; } - (void)dealloc { if (self->removeFile) { [[NSFileManager defaultManager] removeFileAtPath:self->path handler:nil]; } [self->path release]; [super dealloc]; } - (NSData *)_data { return [NSData dataWithContentsOfMappedFile:self->path]; } - (id)copyWithZone:(NSZone *)zone { return [self retain]; } - (const void*)bytes { return [[self _data] bytes]; } - (NSUInteger)length { if (self->length == -1) { self->length = [[[[NSFileManager defaultManager] fileAttributesAtPath:self->path traverseLink:NO] objectForKey:NSFileSize] intValue]; } return self->length; } - (BOOL)appendDataToFileDesc:(int)_fd { NGFileStream *fs; int bufCnt = 8192; char buffer[bufCnt]; BOOL result; int fileLen; if (![[NSFileManager defaultManager] isReadableFileAtPath:self->path]) { NSLog(@"ERROR[%s] missing file at path %@", __PRETTY_FUNCTION__, self->path); return NO; } fileLen = [self length]; result = YES; fs = [NGFileStream alloc]; /* to keep gcc 3.4 happy */ fs = [fs initWithPath:self->path]; if (![fs openInMode:@"r"]) { NSLog(@"%s: could not open file stream ... %@", __PRETTY_FUNCTION__, self->path); [fs release]; fs = nil; return NO; } NS_DURING { NSInteger read; NSInteger alreadyRead; alreadyRead = 0; read = (bufCnt > (fileLen - alreadyRead)) ? fileLen - alreadyRead : bufCnt; while ((read = [fs readBytes:buffer count:read])) { alreadyRead += read; if (write(_fd, buffer, read) != read) { fprintf(stderr, #if GS_64BIT_OLD "%s: Failed to write %i bytes to file\n", #else "%s: Failed to write %li bytes to file\n", #endif __PRETTY_FUNCTION__, read); result = NO; break; } if (alreadyRead == fileLen) break; } } NS_HANDLER { printf("got exceptions %s\n", [[localException description] cString]); if (![localException isKindOfClass:[NGEndOfStreamException class]]) { [fs release]; fs = nil; result = NO; } } NS_ENDHANDLER; [fs release]; fs = nil; return result; } /* description */ - (NSString *)description { return [NSString stringWithFormat:@"<0x%p[%@]: path=%@>", self, NSStringFromClass([self class]), self->path]; } @end /* NGMimeFileData */ SOPE/sope-mime/NGMime/NGMimeHeaderFields.h0000644000000000000000000000346215004363604017064 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGMimeHeaderFields_H__ #define __NGMime_NGMimeHeaderFields_H__ #import #include @class NSString, NSDictionary; /* NGMimeContentDispositionHeaderField This class is a special value object for holding (and parsing) the content of a content-disposition MIME header field (primarily used for attachments). */ NGMime_EXPORT NSString *NGMimeContentDispositionInlineType; NGMime_EXPORT NSString *NGMimeContentDispositionAttachmentType; NGMime_EXPORT NSString *NGMimeContentDispositionFormType; @interface NGMimeContentDispositionHeaderField : NSObject { @protected NSString *type; NSDictionary *parameters; } - (id)initWithString:(NSString *)_value; /* accessors */ - (NSString *)type; /* parameters */ - (NSString *)name; - (NSString *)filename; - (NSString *)valueOfParameterWithName:(NSString *)_name; - (NSString *)stringValue; - (NSString *)parametersAsString; - (BOOL)valueNeedsQuotes:(NSString *)_parameterValue; @end #endif /* __NGMime_NGMimeHeaderFields_H__ */ SOPE/sope-mime/NGMime/NGMimeHeaderFieldParser.h0000644000000000000000000000636515004363604020063 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGHeaderFieldParser_H__ #define __NGMime_NGHeaderFieldParser_H__ #import @class NSData, NSString, NSMutableDictionary; @protocol NGMimeHeaderFieldParser < NSObject > - (id)parseValue:(id)_data ofHeaderField:(NSString *)_field; @end @interface NGMimeHeaderFieldParser : NSObject < NGMimeHeaderFieldParser > + (BOOL)isMIMELogEnabled; + (BOOL)doesStripLeadingSpaces; - (NSString *)removeCommentsFromValue:(NSString *)_rawValue; - (id)parseValue:(id)_data ofHeaderField:(NSString *)_field; // abstract @end @interface NGMimeContentTypeHeaderFieldParser : NGMimeHeaderFieldParser @end @interface NGMimeRFC822DateHeaderFieldParser : NGMimeHeaderFieldParser @end @interface NGMimeContentLengthHeaderFieldParser : NGMimeHeaderFieldParser @end /* Content-Disposition headers have the form: disposition := "Content-Disposition" ":" disposition-type *(";" disposition-parm) disposition-type := "inline" / "attachment" / extension-token ; values are not case-sensitive disposition-parm := filename-parm / parameter filename-parm := "filename" "=" value; Content-Disposition values may not contain comments ! */ @interface NGMimeContentDispositionHeaderFieldParser : NGMimeHeaderFieldParser @end /* This strips spaces at the beginning and the end of the value, then it removes all comments */ @interface NGMimeStringHeaderFieldParser : NGMimeHeaderFieldParser { @protected BOOL removeComments; // default=YES } - (id)initWithRemoveComments:(BOOL)_flag; - (id)init; - (id)parseValue:(id)_data ofHeaderField:(NSString *)_field; @end /* This stores a mapping between header field parsers and field names. */ @interface NGMimeHeaderFieldParserSet : NSObject { @protected NSMutableDictionary *fieldNameToParser; id defaultParser; } + (id)headerFieldParserSet; + (id)defaultRfc822HeaderFieldParserSet; - (id)init; - (id)initWithDefaultParser:(id)_parser; - (id)initWithParseSet:(NGMimeHeaderFieldParserSet *)_set; /* accessors */ - (void)setParser:(id)_parser forField:(NSString *)_name; - (void)setDefaultParser:(id)_parser; - (id)defaultParser; /* operation */ - (id)parseValue:(id)_data ofHeaderField:(NSString *)_field; @end #endif /* __NGMime_NGHeaderFieldParser_H__ */ SOPE/sope-mime/NGMime/NGMimeBodyGenerator.m0000644000000000000000000000465415004363604017322 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeBodyGenerator.h" #include "NGMimePartGenerator.h" #include "NGMail/NGMimeMessageGenerator.h" #include "common.h" @implementation NGMimeBodyGenerator static BOOL debugOn = NO; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; debugOn = [ud boolForKey:@"NGMimeGeneratorDebugEnabled"]; if (debugOn) NSLog(@"WARNING[%@]: NGMimeGeneratorDebugEnabled is enabled!", self); } /* generate data for body */ - (NSData *)generateBodyOfPart:(id)_part additionalHeaders:(NGMutableHashMap *)_addHeaders delegate:(id)_delegate { NSData *data, *input; input = [_part body]; // We make sure we're dealing with data here. SOPE is just too lame. if ([input isKindOfClass: [NSString class]]) input = [(id)input dataUsingEncoding: NSUTF8StringEncoding]; data = [self encodeData:input forPart:_part additionalHeaders:_addHeaders]; if (debugOn) { [self debugWithFormat:@"encoded %d bytes to %d bytes (same=%s, class=%@)", [input length], [data length], input == data ? "yes" : "no", NSStringFromClass([data class])]; } return data; } /* properly encode data for transfer (eg to 7bit for email) */ - (NSData *)encodeData:(NSData *)_data forPart:(id)_part additionalHeaders:(NGMutableHashMap *)_addHeaders { return _base64Encoding(self, _data, _part, _addHeaders); } /* manage data storage */ - (void)setUseMimeData:(BOOL)_b { self->useMimeData = _b; } - (BOOL)useMimeData { return self->useMimeData; } /* debugging */ - (BOOL)isDebuggingEnabled { return debugOn; } @end /* NGMimeBodyGenerator */ SOPE/sope-mime/NGMime/NGMimeGeneratorProtocols.h0000644000000000000000000000361615004363604020401 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMimeGenerator_NGMimeGeneratorProtocols_H__ #define __NGMimeGenerator_NGMimeGeneratorProtocols_H__ #import #import @class NSData, NGMutableHashMap; @protocol NGMimePartGenerator /* generate mime from part and store it in _file */ - (NSString *)generateMimeFromPartToFile:(id)_part; - (NSData *)generateMimeFromPart:(id)_part; - (void)setDelegate:(id)_delegate; - (id)delegate; - (void)setUseMimeData:(BOOL)_useMimeData; @end @protocol NGMimeBodyGenerator < NSObject > - (NSData *)generateBodyOfPart:(id)_part additionalHeaders:(NGMutableHashMap *)_addHeaders delegate:(id)_delegate; - (NSData *)encodeData:(NSData *)_data forPart:(id)_part additionalHeaders:(NGMutableHashMap *)_addHeaders; /* use mime data objects to store mime objects on disk instead in memory */ - (void)setUseMimeData:(BOOL)_useMimeData; @end @protocol NGMimeHeaderFieldGenerator < NSObject > - (NSData *)generateDataForHeaderFieldNamed:(NSString *)_headerField value:(id)_value; @end #endif // __NGMimeGenerator_NGMimeGeneratorProtocols_H__ SOPE/sope-mime/NGMime/NGMimeJoinedData.m0000644000000000000000000001060115004363604016545 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeJoinedData.h" #include "common.h" #include "timeMacros.h" #include #include #include #include #include #include "NGMimeFileData.h" @implementation NGMimeJoinedData - (id)init { if ((self = [super init])) { self->joinedDataObjects = [[NSMutableArray alloc] initWithCapacity:16]; } return self; } - (void)dealloc { [self->joinedDataObjects release]; [super dealloc]; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { // TODO: we are mutable, is -retain a bug or feature? return [self retain]; } /* data */ - (NSArray *)_joinedDataObjects { return self->joinedDataObjects; } - (NSUInteger)length { NSUInteger i, count, size; for (i = 0, count = [self->joinedDataObjects count], size = 0; i < count;i++) size += [[self->joinedDataObjects objectAtIndex:i] length]; return size; } /* appending data */ - (void)appendData:(NSData *)_data { if ([_data isKindOfClass:[NGMimeJoinedData class]]) { [self->joinedDataObjects addObjectsFromArray: [(NGMimeJoinedData *)_data _joinedDataObjects]]; } else [self->joinedDataObjects addObject:_data]; } - (void)appendBytes:(const void *)_bytes length:(unsigned int)_length { NSMutableData *data; if (_length == 0) return; data = (NSMutableData *)[self->joinedDataObjects lastObject]; if ([data isKindOfClass:[NSMutableData class]]) { [data appendBytes:_bytes length:_length]; } else { /* Note: we create a mutable because it is not unlikely that additional appends are coming. */ data = [[NSMutableData alloc] initWithBytes:_bytes length:_length]; if (data != nil) [self->joinedDataObjects addObject:data]; [data release]; } } /* writing to file */ - (BOOL)writeToFile:(NSString*)_path atomically:(BOOL)_useAuxiliaryFile { NSString *filename = nil; NSEnumerator *enumerator; NSData *data; volatile BOOL result; int fd; filename = _path; fd = open([filename fileSystemRepresentation], O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd == -1) { fprintf(stderr, "Could not open file for writing %s: %s\n", [filename fileSystemRepresentation], strerror(errno)); return NO; } result = YES; enumerator = [self->joinedDataObjects objectEnumerator]; while ((data = [enumerator nextObject])) { TIME_START("write bytes "); if ([data isKindOfClass:[NGMimeFileData class]]) { if (![(NGMimeFileData *)data appendDataToFileDesc:fd]) { fprintf(stderr, #if GS_64BIT_OLD "Failed to write %i bytes to %s: %s\n", #else "Failed to write %li bytes to %s: %s\n", #endif [data length], [filename fileSystemRepresentation], strerror(errno)); close(fd); } } else { const void *bytes; unsigned len; TIME_START("bytes ...") bytes = [data bytes]; len = [data length]; TIME_END; if (write(fd, bytes, len) != (int)len) { fprintf(stderr, "Failed to write %i bytes to %s: %s\n", len, [filename fileSystemRepresentation], strerror(errno)); close(fd); return NO; } } TIME_END; } close(fd); return result; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:128]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; [ms appendFormat:@" joinedDataObjects=%d>", (int)[self->joinedDataObjects count]]; [ms appendString:@">"]; return ms; } @end /* NGMimeJoinedData */ SOPE/sope-mime/NGMime/NGMimeFileData.h0000644000000000000000000000276015004363604016216 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGMimeFileData_H__ #define __NGMime_NGMimeFileData_H__ #import /* NGMimeFileData TODO: explain. Somehow this is an object to save loading an NSData to RAM. Note: the -initWithBytes:length: method creates a temporary file! Checked in: - NGMimeBodyGenerator - NGMimeBodyPart - NGMimeJoinedData */ @class NSString; @interface NGMimeFileData : NSData { NSString *path; BOOL removeFile; int length; } - (id)initWithPath:(NSString *)_path removeFile:(BOOL)_remove; - (id)initWithBytes:(const void *)_bytes length:(NSUInteger)_length; /* operations */ - (BOOL)appendDataToFileDesc:(int)_fd; @end /* NGMimeFileData */ #endif /* __NGMime_NGMimeFileData_H__ */ SOPE/sope-mime/NGMime/NGMimeMultipartBody.h0000644000000000000000000000413615004363604017343 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGMimeMultipartBody_H__ #define __NGMime_NGMimeMultipartBody_H__ #import #include @class NSData, NSString, NSMutableArray; /* Represents bodies of multipart entities. Multipart bodies can be parsed 'on-demand'. ATTENTION: the delegate is _required_ to persist until the multipart body is parsed ! The body does not retain the delegate. */ @interface NGMimeMultipartBody : NSObject { @protected id part; /* non-retained */ NSString *prefix; NSString *suffix; NSMutableArray *bodyParts; // for on-demand parsing NSData *rawData; id delegate; /* non-retained */ struct { BOOL isParsed:1; } flags; } - (id)initWithPart:(id)_part; // designated initializer - (id)initWithPart:(id)_part data:(NSData *)_data delegate:(id)_delegate; // accessors - (id)part; // the part the body belongs to - (NSArray *)parts; - (void)addBodyPart:(id)_part; - (void)addBodyPart:(id)_part atIndex:(int)_idx; - (void)removeBodyPart:(id)_part; - (void)removeBodyPartAtIndex:(int)_idx; - (void)setPrefix:(NSString *)_prefix; - (NSString *)prefix; - (void)setSuffix:(NSString *)_suffix; - (NSString *)suffix; @end #endif /* __NGMime_NGMimeMultipartBody_H__ */ SOPE/sope-mime/NGMime/NSCalendarDate+RFC822.m0000644000000000000000000000645015004363604017127 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" @implementation NSCalendarDate(RFC822Dates) static NSString *dateFormats[] = { /* short-weekday, day short-month year hour:minute:second timezoneoffset eg: Mon, 01 Mar 1999 13:13:13 +0000 */ @"%a, %d %b %Y %H:%M:%S %z", /* short-weekday, day short-month year hour:minute:second timezonename eg: Mon, 01 Mar 1999 13:13:13 GMT */ @"%a, %d %b %Y %H:%M:%S %Z", /* short-weekday, day short-month year hour:minute:second timezonename eg: Mon, 01 Mar 1999 13:13 +0000 */ @"%a, %d %b %Y %H:%M %z", /* short-weekday, day short-month year hour:minute:second timezonename eg: Mon, 01 Mar 1999 13:13 (+0000) */ @"%a, %d %b %Y %H:%M (%z)", /* short-weekday, day short-month year hour:minute:second timezonename eg: Mon, 01 Mar 1999 13:13 (GMT) */ @"%a, %d %b %Y %H:%M (%Z)", /* short-weekday, day short-month year hour:minute:second eg: Mon, 01 Mar 1999 13:13:13 */ @"%a, %d %b %Y %H:%M:%S", /* day short-month year hour:minute:second timezoneoffset eg: 01 Oct 1999 18:20:12 +0200 */ @"%d %b %Y %H:%M:%S %z", /* day short-month year hour:minute:second timezonename eg: 01 Oct 1999 18:20:12 EST */ @"%d %b %Y %H:%M:%S %Z", /* day short-month year hour:minute:second (timezoneoffset) eg: 30 Sep 1999 21:00:05 (+0200) */ @"%d %b %Y %H:%M:%S (%z)", /* day short-month year hour:minute:second (timezonename) eg: 30 Sep 1999 21:00:05 (MEST) */ @"%d %b %Y %H:%M:%S (%Z)", /* day short-month year hour:minute:second (timezonename) eg: 30 Sep 1999 21:00:05 (MEST) */ @"%d %b %Y %H:%M:%S (%Z)", /* short-weekday, day short-month year hour:minute:second timezoneoffset eg: Mon, 01 Mar 1999 13:13:13 +0000 */ @"%a %b %d %H:%M:%S %Y (%Z)", /* eg: '16 Jun 2002 10:28 GMT' */ @"%d %b %Y %H:%M %Z", /* eg: '16 Jun 2002 10:28 +0000' */ @"%d %b %Y %H:%M %z", /* terminate list */ nil }; + (NSCalendarDate *)calendarDateWithRfc822DateString:(NSString *)_str { // TODO: optimize MUCH more - calformat parsing is *slow* NSCalendarDate *date = nil; NSString *dateString = nil; int i; dateString = [_str stringByTrimmingSpaces]; if ([dateString length] == 0) return nil; /* check various date formats */ for (i = 0, date = nil; (date == nil) && (dateFormats[i] != nil); i++) { date = [NSCalendarDate dateWithString:dateString calendarFormat:dateFormats[i]]; } return [date y2kDate]; } @end /* NSCalendarDate(RFC822Dates) */ SOPE/sope-mime/NGMime/NGMimePartGenerator.h0000644000000000000000000001210415004363604017313 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMimeGenerator_NGMimePartGenerator_H__ #define __NGMimeGenerator_NGMimePartGenerator_H__ #import #import #import @class NSMutableData, NSData, NSString, NSEnumerator; @class NGHashMap, NGMutableHashMap; @class NGMimeType, NGMimePartGenerator; @interface NGMimePartGenerator : NSObject { @protected NSMutableData *result; // result id part; // for generating id delegate; // not retained to prevent retain cycles BOOL useMimeData; void (*appendBytes)(id,SEL,const void*,unsigned int); /* cached method for result */ struct { BOOL generatorGenerateDataForHeaderField:1; BOOL generatorGeneratorForBodyOfPart:1; BOOL generatorGenerateDataForBodyOfPart:1; } delegateRespondsTo; } + (id)mimePartGenerator; /* generating mime from MimeMessage */ - (NSData *)generateMimeFromPart:(id)_part; /* generate mime from part and store it in the returned filename */ - (NSString *)generateMimeFromPartToFile:(id)_part; /* build data with current mime-header and the _additionalHeaders; _additionalHeaders come from generateBodyData (boundary, encoding, ...) */ - (NSData *)generateHeaderData:(NGHashMap *)_additionalHeaders; /* build the body; use -generatorForBodyOfPart */ - (NSData *)generateBodyData:(NGMutableHashMap *)_additionalHeaders; /* call generateHeaderData and generateBodyData; manage additionalHeaders */ - (void)generateData; /* set result and other stuff */ - (BOOL)prepareForGenerationOfPart:(id)_part; /* setting the delegate */ - (void)setDelegate:(id)_delegate; - (id)delegate; /* ----- hooks for subclasses ----- */ /* Generate a prefix and/or a suffix for a part. Can be used to write HTTP response lines before the part. */ - (BOOL)generatePrefix; - (void)generateSuffix; /* if no content-type is set */ - (NGMimeType *)defaultContentTypeForPart:(id)_part; /* returns header field generator for the specified field */ - (id)generatorForHeaderField:(NSString *)_name; /* build data for the specified header; employ -generatorForHeaderField */ - (NSData *)generateDataForHeaderField:(NSString *)_headerField value:(id)_value; /* build data with the specified header; */ - (BOOL)isMultiValueCommaHeaderField:(NSString *)_headerField; - (BOOL)appendHeaderField:(NSString *)_field values:(NSEnumerator *)_values toData:(NSMutableData *)_data; /* looking for a NGMimeBodyGenerator in dependece to the content-type */ - (id)generatorForBodyOfPart:(id)_part; /* ----- end hooks for subclasses ----- */ /* accessors */ - (id)part; @end @interface NSObject(NGMimePartGenerator) /* The delegete has the opportunity to generate data for specified header-field with the given enumerator. The classes of the values depends on the _headerField name, normaly they are NSStrings */ - (NSData *)mimePartGenerator:(id)_gen generateDataForHeaderField:(NSString *)_headerField value:(NSEnumerator *)_value; /* The delegate can choose, which generator should be used, to generate the specified NGMimePart. */ - (id)mimePartGenerator:(id)_gen generatorForBodyOfPart:(id)_part; /* The delegate has the opportunity to generate the whole body-part. Additional headers like boundary can be set in _additionalHeaders. */ - (NSData *)mimePartGenerator:(id)_gen generateDataForBodyOfPart:(id)_part additionalHeaders:(NGMutableHashMap *)_additionalHeaders; /* The delegate can set prefix and suffix for a multipart. */ - (NSString *)multipartBodyGenerator:(id)_bodyGen prefixForPart:(id)_part; - (NSString *)multipartBodyGenerator:(id)_bodyGen suffixForPart:(id)_part; /* The delegate can select which NGMimeBodyGenerator should de used for generate the given part. */ - (id)multipartBodyGenerator:(id)aGenerator generatorForPart:(id)_part; - (BOOL)useMimeData; - (void)setUseMimeData:(BOOL)_b; @end #endif // __NGMimeGenerator_NGMimePartGenerator_H__ SOPE/sope-mime/NGMime/NGMimePartParser.m0000644000000000000000000011554615004363604016644 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimePartParser.h" #include "NGMimeBodyParser.h" #include "NGMimeType.h" #include "NGMimeUtilities.h" #include "common.h" #include /* this tunes, how big reused data cache objects may get (10MB) */ #define MAX_DATA_OBJECT_SIZE_CACHE (10*1024*1024) @implementation NSData(MIMEContentTransferEncoding) - (NSData *)dataByApplyingMimeContentTransferEncoding:(NSString *)_enc { // TODO: make this an NSData category unsigned len; unichar c; if ((len = [_enc length]) == 0) return self; _enc = [_enc lowercaseString]; c = [_enc characterAtIndex:0]; switch (c) { case 'q': if ([_enc hasPrefix:@"quoted"]) return [self dataByDecodingQuotedPrintableTransferEncoding]; break; case 'b': if ([_enc hasPrefix:@"base64"]) return [self dataByDecodingBase64]; if ([@"binary" isEqualToString:_enc]) return self; break; case '7': case '8': case 'i': if (len == 4) { if ([@"7bit" isEqualToString:_enc]) return self; if ([@"8bit" isEqualToString:_enc]) return self; break; } else if (len == 8) { if ([@"identity" isEqualToString:_enc]) return self; } case 'u': if (len == 12) { if ([@"unknown-8bit" isEqualToString:_enc]) return self; } default: break; } [self warnWithFormat:@"%s: unknown content-transfer-encoding: '%@'", __PRETTY_FUNCTION__, _enc]; return nil; } @end /* NSData(MIMEContentTransferEncoding) */ @implementation NGMimePartParser static Class StringClass = Nil; static Class MStringClass = Nil; static Class DataClass = Nil; static Class NSMutableDataClass = NULL; static NGMimeHeaderNames *HeaderNames = NULL; static int MimeLogEnabled = -1; + (void)initialize { static BOOL isInitialized = NO; NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; if (isInitialized) return; isInitialized = YES; MimeLogEnabled = [ud boolForKey:@"MimeLogEnabled"] ? 1 : 0; MStringClass = [NSMutableString class]; StringClass = [NSString class]; DataClass = [NSData class]; NSMutableDataClass = [NSMutableData class]; } static inline int _la(NGMimePartParser *self, int _la); static inline void _consume(NGMimePartParser *self, int _cnt); static inline BOOL _checkKey(NGMimePartParser *self, NGHashMap *_map, NSString *_key); + (NGMimeHeaderNames *)headerFieldNames { if (HeaderNames == NULL) { HeaderNames = malloc(sizeof(NGMimeHeaderNames)); HeaderNames->accept = @"accept"; HeaderNames->acceptLanguage = @"accept-language"; HeaderNames->acceptEncoding = @"accept-encoding"; HeaderNames->acceptCharset = @"accept-charset"; HeaderNames->cacheControl = @"cache-control"; HeaderNames->cc = @"cc"; HeaderNames->connection = @"connection"; HeaderNames->contentDisposition = @"content-disposition"; HeaderNames->contentLength = @"content-length"; HeaderNames->contentTransferEncoding = @"content-transfer-encoding"; HeaderNames->contentType = @"content-type"; HeaderNames->cookie = @"cookie"; HeaderNames->date = @"date"; HeaderNames->from = @"from"; HeaderNames->host = @"host"; HeaderNames->keepAlive = @"keep-alive"; HeaderNames->messageID = @"message-id"; HeaderNames->mimeVersion = @"mime-version"; HeaderNames->organization = @"organization"; HeaderNames->received = @"received"; HeaderNames->returnPath = @"return-path"; HeaderNames->referer = @"referer"; HeaderNames->replyTo = @"reply-to"; HeaderNames->subject = @"subject"; HeaderNames->to = @"to"; HeaderNames->userAgent = @"user-agent"; HeaderNames->xMailer = @"x-mailer"; } return HeaderNames; } - (id)init { if ((self = [super init])) { self->bufLen = 1024; self->contentLength = -1; self->delegate = nil; } return self; } - (void)dealloc { [self->delegate release]; [self->contentTransferEncoding release]; [self->source release]; [self->sourceData release]; [super dealloc]; } /* accessors */ - (void)setDelegate:(id)_delegate { ASSIGN(self->delegate, _delegate); self->delegateRespondsTo.parserWillParseHeader = [self->delegate respondsToSelector:@selector(parserWillParseHeader:)]; self->delegateRespondsTo.parserDidParseHeader = [self->delegate respondsToSelector:@selector(parser:didParseHeader:)]; self->delegateRespondsTo.parserKeepHeaderFieldData = [self->delegate respondsToSelector:@selector(parser:keepHeaderField:data:)]; self->delegateRespondsTo.parserKeepHeaderFieldValue = [self->delegate respondsToSelector: @selector(parser:keepHeaderField:value:)]; self->delegateRespondsTo.parserFoundCommentInHeaderField = [self->delegate respondsToSelector: @selector(parser:foundComment:inHeaderField:)]; self->delegateRespondsTo.parserWillParseBodyOfPart = [self->delegate respondsToSelector:@selector(parser:willParseBodyOfPart:)]; self->delegateRespondsTo.parserDidParseBodyOfPart = [self->delegate respondsToSelector:@selector(parser:didParseBodyOfPart:)]; self->delegateRespondsTo.parserParseRawBodyDataOfPart = [self->delegate respondsToSelector: @selector(parser:parseRawBodyData:ofPart:)]; self->delegateRespondsTo.parserBodyParserForPart = [self->delegate respondsToSelector:@selector(parser:bodyParserForPart:)]; self->delegateRespondsTo.parserDecodeBodyOfPart = [self->delegate respondsToSelector:@selector(parser:decodeBody:ofPart:)]; self->delegateRespondsTo.parserParseHeaderFieldData = [self->delegate respondsToSelector:@selector(parser:parseHeaderField:data:)]; } - (id)delegate { return self->delegate; } /* header */ - (id)parserForHeaderField:(NSString *)_name { static id defParserSet = nil; if (defParserSet == nil) { defParserSet = [[NGMimeHeaderFieldParserSet defaultRfc822HeaderFieldParserSet] retain]; } return defParserSet; } + (NSStringEncoding)defaultHeaderFieldEncoding { return NSUTF8StringEncoding; } - (id)valueOfHeaderField:(NSString *)_name data:(id)_data { // TODO: use iconv (if available, eg not on OSX !!!) to convert // an unknown encoding to UTF-16 and create an NSConcrete*UTF16String id parser; NSString *tmp; id value = nil; if (self->delegateRespondsTo.parserParseHeaderFieldData) value = [delegate parser:self parseHeaderField:_name data:_data]; if (value) return value; if ([_data isKindOfClass:DataClass]) { tmp = [[StringClass alloc] initWithData:_data encoding:[NGMimePartParser defaultHeaderFieldEncoding]]; // We try to fallback to ISO-8859-1 here. This fixes some brain // damage due to broken mails. See http://sogo.nu/bugs/view.php?id=3309 // for details. if (!tmp) tmp = [[StringClass alloc] initWithData: _data encoding: NSISOLatin1StringEncoding]; } else tmp = [_data retain]; if ((parser = [self parserForHeaderField:_name])) value = [parser parseValue:tmp ofHeaderField:_name]; else value = [tmp stringByTrimmingSpaces]; value = [[value retain] autorelease]; [tmp release]; return value; } /* possible constants: NGMime_CC = @"cc"; NGMime_To = @"to"; : 2 NGMime_Date = @"date"; NGMime_Host = @"host"; NGMime_From = @"from"; : 4 NGMime_Cookie = @"cookie" NGMime_Accept = @"accept" : 6 NGMime_Referer = @"referer" NGMime_Subject = @"subject"; : 7 NGMime_xMailer = @"x-mailer"; NGMime_ReplyTo = @"reply-to" NGMime_Received = @"received"; : 8 NGMime_Connection = @"connection" NGMime_KeepAlive = @"keep-alive" NGMime_UserAgent = @"user-agent"; NGMime_MessageID = @"message-id"; : 10 NGMime_ReturnPath = @"return-path"; : 11 NGMime_MimeVersion = @"mime-version"; NGMime_Organization = @"organization"; NGMime_ContentType = @"content-type"; : 12 NGMime_CacheControl = @"cache-control" : 13 NGMime_AcceptCharset = @"accept-charset" NGMime_ContentLength = @"content-length"; : 14 NGMime_AcceptEncoding = @"accept-encoding" NGMime_AcceptLanguage = @"accept-language" : 15 NGMime_ContentDisposition = @"content-disposition"; : 19 NGMime_ContentTransferEncoding = @"content-transfer-encoding"; : 25 */ static NSString *fieldNameForCString(id self, char *_cstring, int _len) { if (HeaderNames == NULL) [NGMimePartParser headerFieldNames]; switch (_len) { case 0: return @""; case 2: if (_cstring[0] == 'c' && _cstring[1] == 'c') return HeaderNames->cc; else if (_cstring[0] == 't' && _cstring[1] == 'o') return HeaderNames->to; break; case 4: if (_cstring[3] == 'e') { if (strncmp(_cstring, "date", 4) == 0) return HeaderNames->date; } else if (_cstring[3] == 'm') { if (strncmp(_cstring, "from", 4) == 0) return HeaderNames->from; } else if (_cstring[3] == 't') { if (strncmp(_cstring, "host", 4) == 0) return HeaderNames->host; } break; case 6: if (_cstring[5] == 't') { if (strncmp(_cstring, "accept", 6) == 0) return HeaderNames->accept; } if (_cstring[5] == 'e') { if (strncmp(_cstring, "cookie", 6) == 0) return HeaderNames->cookie; } break; case 7: if (_cstring[6] == 't') { if (strncmp(_cstring, "subject", 7) == 0) return HeaderNames->subject; } if (_cstring[6] == 'r') { if (strncmp(_cstring, "referer", 7) == 0) return HeaderNames->referer; } break; case 8: if (_cstring[5] == '-') { if (strncmp(_cstring, "reply-to", 8) == 0) return HeaderNames->replyTo; } if (_cstring[7] == 'd') { if (strncmp(_cstring, "received", 8) == 0) return HeaderNames->received; } if (_cstring[1] == '-') { if (strncmp(_cstring, "x-mailer", 8) == 0) return HeaderNames->xMailer; } break; case 10: if (_cstring[4] == '-') { if (_cstring[6] == 'g') { if (strncmp(_cstring, "user-agent", 10) == 0) return HeaderNames->userAgent; } if (_cstring[6] == 'l') { if (strncmp(_cstring, "keep-alive", 10) == 0) return HeaderNames->keepAlive; } } else if (_cstring[7] == '-') { if (strncmp(_cstring, "message-id", 10) == 0) return HeaderNames->messageID; } else if (_cstring[9] == 'n') { if (strncmp(_cstring, "connection", 10) == 0) return HeaderNames->connection; } break; case 11: if (_cstring[6] == '-') { if (strncmp(_cstring, "return-path", 11) == 0) return HeaderNames->returnPath; } break; case 12: if (_cstring[4] == '-') { if (strncmp(_cstring, "mime-version", 12) == 0) return HeaderNames->mimeVersion; } else if (_cstring[11] == 'n') { if (strncmp(_cstring, "organization", 12) == 0) return HeaderNames->organization; } else if (_cstring[7] == '-') { if (strncmp(_cstring, "content-type", 12) == 0) return HeaderNames->contentType; } break; case 13: if (_cstring[5] == '-') { if (strncmp(_cstring, "cache-control", 13) == 0) return HeaderNames->cacheControl; } break; case 14: if (_cstring[7] == '-') { if (strncmp(_cstring, "content-length", 14) == 0) { return HeaderNames->contentLength; } } else if (_cstring[6] == '-') { if (strncmp(_cstring, "accept-charset", 14) == 0) return HeaderNames->acceptCharset; } break; case 15: if (_cstring[6] == '-') { if (_cstring[7] == 'l') { if (strncmp(_cstring, "accept-language", 15) == 0) return HeaderNames->acceptLanguage; } else if (_cstring[7] == 'e') { if (strncmp(_cstring, "accept-encoding", 15) == 0) return HeaderNames->acceptEncoding; } } break; case 19: if (_cstring[7] == '-') { if (strncmp(_cstring, "content-disposition", 19) == 0) return HeaderNames->contentDisposition; } break; case 25: if (_cstring[7] == '-') { if (strncmp(_cstring, "content-transfer-encoding", 25) == 0) return HeaderNames->contentTransferEncoding; } break; } { NSString *result; result = [NSString stringWithCString:_cstring length:_len]; #if DEBUG & 0 if (MimeLogEnabled) [self logWithFormat:@"%s: found no headerfield constant for <%@>, " @"generate new string", __PRETTY_FUNCTION__, result]; #endif return result; } } - (NSString *)fieldNameForCString:(char *)_cstring length:(int)_len { return fieldNameForCString(self, _cstring, _len); } - (NGHashMap *)parseHeader { // TODO: split up this huge method! /* parse headers until an empty line is seen */ NGMutableHashMap *header = nil; NSMutableData *fieldValue = nil; NSMutableString *fieldName = nil; NSString *realFieldName = nil; BOOL foundEndOfHeaders = NO; int bufCnt = 0; char *buf = NULL; NSAutoreleasePool *pool; ASSIGN(self->contentTransferEncoding, (id)nil); if (self->delegateRespondsTo.parserWillParseHeader) { if (![self->delegate parserWillParseHeader:self]) return nil; } pool = [[NSAutoreleasePool alloc] init]; fieldValue = [NSMutableData dataWithCapacity:512]; header = [NGMutableHashMap hashMapWithCapacity:128]; buf = calloc(self->bufLen, 1); bufCnt = *&bufCnt; while (!foundEndOfHeaders) { int c = 0; BOOL endOfFieldBody = NO; /* reset mutable vars */ if (fieldName) { [fieldName release]; fieldName = nil; } [fieldValue setLength:0]; /* parse fieldName */ { unsigned fnlen; BOOL lastWasCR; bufCnt = 0; fnlen = 0; lastWasCR = NO; while ((c = _la(self, 0)) != ':') { if (c == -1) /* EOF */ break; /* check for leading '\r\n' or '\n' */ if (fnlen == 0) { if (c == '\r') { lastWasCR = YES; } else if (c == '\n') { /* finish, found header starting with newline */ foundEndOfHeaders = YES; endOfFieldBody = YES; self->useContentLength = NO; _consume(self, 1); // consume newline break; /* leave local loop */ } } else if ((fnlen == 1) && lastWasCR) { if (c == '\n') { /* finish, found \r\n */ foundEndOfHeaders = YES; endOfFieldBody = YES; self->useContentLength = NO; bufCnt = 0; _consume(self, 1); // consume newline break; /* leave local loop */ } } /* add to buffer */ buf[bufCnt] = c; bufCnt++; fnlen++; _consume(self, 1); if (bufCnt >= self->bufLen) { register int i; for (i = 0; i < bufCnt; i++) buf[i] = tolower((int)buf[i]); if (fieldName == nil) { fieldName = [[MStringClass alloc] initWithCString:buf length:bufCnt]; } else { NSString *s; s = [[StringClass alloc] initWithCString:buf length:bufCnt]; [fieldName appendString:s]; [s release]; s = nil; } bufCnt = 0; } } if (foundEndOfHeaders) /* leave main loop */ break; if (bufCnt > 0) { register int i; for (i = 0; i < bufCnt; i++) buf[i] = tolower((int)buf[i]); if ([fieldName length] == 0) { /* const headernames are always smaller than bufLen */ realFieldName = fieldNameForCString(self, buf, bufCnt); } else { NSString *s; s = [[StringClass alloc] initWithCString:buf length:bufCnt]; [fieldName appendString:s]; [s release]; s = nil; realFieldName = fieldName; if (c == -1) { NSLog(@"WARNING(%s:%i): 1 an error occured during header-field " @" parsing (maybe end of stream) fieldName: %@", __PRETTY_FUNCTION__, __LINE__, fieldName); foundEndOfHeaders = YES; endOfFieldBody = YES; } } } else { realFieldName = fieldName; } _consume(self, 1); // consume ':' } /* parse fieldBody */ bufCnt = 0; while (!endOfFieldBody) { int laC0 = _la(self, 0); if (laC0 == -1) break; if (laC0 == '\r') { // CR int laC1 = _la(self, 1); if (isRfc822_LWSP(laC1)) { // CR LSWSP _consume(self, 1); // folding } else if (laC1 == '\n') { // CR LF int laC2 = _la(self, 2); if (isRfc822_LWSP(laC2)) { // CR LF LWSP _consume(self, 2); // folding } else if (laC2 == '\r') { // CR LF CR int laC3 = _la(self, 3); if (laC3 == '\n') { // CR LF CR LF _consume(self, 4); foundEndOfHeaders = YES; // end of headers endOfFieldBody = YES; } else { // CR LF CR * _consume(self, 3); // ignored ?? } } else if (laC2 == '\n') { // CR LF LF _consume(self, 3); foundEndOfHeaders = YES; // end of headers endOfFieldBody = YES; } else { // CR LF * _consume(self, 2); endOfFieldBody = YES; // next header field } } else { // CR * _consume(self, 1); endOfFieldBody = YES; // next header field } } else if (laC0 == '\n') { // LF int laC1 = _la(self, 1); if (isRfc822_LWSP(laC1)) { // LF LWSP _consume(self, 1); // folding } else if (laC1 == '\n') { // LF LF _consume(self, 2); foundEndOfHeaders = YES; // end of headers endOfFieldBody = YES; } else if (laC1 == '\r') { // LF CR int laC2 = _la(self, 2); if (isRfc822_LWSP(laC2)) { // LF CR LWSP _consume(self, 2); // folding } else if (laC2 == '\n') { // LF CR LF _consume(self, 3); // foundEndOfHeaders = YES; // end of headers endOfFieldBody = YES; } else { // LF CR * _consume(self, 2); endOfFieldBody = YES; // next header field } } else { // LF * _consume(self, 1); endOfFieldBody = YES; // next header field } } else { // * if ((bufCnt != 0) || (!isRfc822_LWSP(laC0))) { /* ignore leading white spaces */ buf[bufCnt++] = laC0; } _consume(self, 1); if (bufCnt >= self->bufLen) { [fieldValue appendBytes:buf length:bufCnt]; bufCnt = 0; } } } if (bufCnt > 0) { [fieldValue appendBytes:buf length:bufCnt]; bufCnt = 0; } if (!endOfFieldBody) { [self logWithFormat: @"WARNING(%s:%i): 2 an error occured during body parsing " @"(maybe end of stream)", __PRETTY_FUNCTION__, __LINE__]; foundEndOfHeaders = YES; } if (realFieldName != nil) { BOOL keepHeader = YES; if (HeaderNames == NULL) [NGMimePartParser headerFieldNames]; if (realFieldName == HeaderNames->contentTransferEncoding) { int len; const unsigned char *cstr; len = [fieldValue length]; cstr = [fieldValue bytes]; keepHeader = NO; // don't keep content-tranfer-encodings while (isRfc822_LWSP(*cstr) && (len > 0)) { // strip leading spaces cstr++; len--; } if (len > 0) { // len==0 means the value was a string of LWSP [self->contentTransferEncoding release]; self->contentTransferEncoding = [[StringClass alloc] initWithCString:(char *)cstr length:len]; } else { [self->contentTransferEncoding release]; self->contentTransferEncoding = nil; } } /* take a look on content-length headers, since the parser needs to know this for reading in the body .. */ if (keepHeader && self->useContentLength) { if (realFieldName == HeaderNames->contentLength) { int len; const unsigned char *cstr; len = [fieldValue length]; cstr = [fieldValue bytes]; while (isRfc822_LWSP(*cstr) && (len > 0)) { // strip leading spaces cstr++; len--; } if (len > 0) { // len==0 means the value was a string of LWSP unsigned char buf[len + 1]; int i = 0; while (isdigit(*cstr) && (i < len)) { // extract following digits buf[i++] = *cstr; cstr++; } buf[i] = '\0'; // stop string after last digit (ignore the rest) self->contentLength = atoi((char *)buf); } else { /* header value are only spaces */ self->contentLength = -1; } } } /* ask delegate if the header is to be kept */ if (keepHeader) { if (self->delegateRespondsTo.parserKeepHeaderFieldData) keepHeader = [self->delegate parser:self keepHeaderField:realFieldName data:fieldValue]; } if (keepHeader) { id value = nil; value = [self valueOfHeaderField:realFieldName data:fieldValue]; if (value) { value = [value retain]; /* ask delegate if the header is to be kept */ if (self->delegateRespondsTo.parserKeepHeaderFieldValue) { keepHeader = [self->delegate parser:self keepHeaderField:realFieldName value:value]; } if (keepHeader) { NSAssert(realFieldName, @"missing field name .."); NSAssert(value, @"missing field value .."); /* check whether content-length, content-type, subject already in hashmap */ if (_checkKey(self, header, realFieldName)) [header addObject:value forKey:realFieldName]; } [value release]; } } } } if (buf) { free(buf); buf = NULL; } if (self->delegateRespondsTo.parserDidParseHeader) [self->delegate parser:self didParseHeader:header]; header = [header retain]; [pool release]; return [header autorelease]; } - (NSData *)readBodyUnknownLengthStream { static NSMutableData *dataObject = nil; NGIOReadMethodType readBytes = NULL; NSData *rbody; NSMutableData *body; int bufCnt; char buf[self->bufLen]; void (*appendBytes)(id,SEL,const void *,unsigned); BOOL decodeBase64; *(&readBytes) = NULL; if ([self->source respondsToSelector:@selector(methodForSelector:)]) { readBytes = (NGIOReadMethodType) [self->source methodForSelector:@selector(readBytes:count:)]; } *(&appendBytes) = NULL; *(&bufCnt) = 0; // THREAD /* check whether we can reuse the dataObj ... */ if (dataObject) { *(&body) = [dataObject autorelease]; dataObject = nil; /* mark as used ... */ } else { *(&body) = [[[NSMutableData alloc] initWithCapacity:100010] autorelease]; } decodeBase64 = NO; appendBytes = (void(*)(id,SEL,const void *, unsigned)) [body methodForSelector:@selector(appendBytes:length:)]; NS_DURING { while (YES) { NSException *e; NS_DURING { _la(self, self->bufLen - 1); } NS_HANDLER { if (![localException isKindOfClass:[NGEndOfStreamException class]]) [localException raise]; } NS_ENDHANDLER; e = nil; bufCnt = (readBytes != NULL) ? readBytes(self->source, @selector(readBytes:count:), buf, self->bufLen) : [self->source readBytes:buf count:self->bufLen]; if (bufCnt == NGStreamError) { e = [self->source lastException]; if ([e isKindOfClass:[NGEndOfStreamException class]]) /* leave loop */ break; else [e raise]; } /* perform any on-the-fly encodings */ /* add to body data */ appendBytes(body, @selector(appendBytes:length:), buf, bufCnt); bufCnt = 0; } } NS_HANDLER { if (![localException isKindOfClass:[NGEndOfStreamException class]]) [localException raise]; } NS_ENDHANDLER; if (bufCnt > 0 && bufCnt != NGStreamError) { appendBytes(body, @selector(appendBytes:length:), buf, bufCnt); bufCnt = 0; } if (decodeBase64) { ASSIGN(self->contentTransferEncoding, (id)nil); } rbody = [body copy]; // THREAD /* remember that object for reuse ... */ if (dataObject == nil && [body length] < MAX_DATA_OBJECT_SIZE_CACHE) { dataObject = [body retain]; [dataObject setLength:0]; } return [rbody autorelease]; } - (NSData *)readBodyUnknownLengthData { return [self->sourceData subdataWithRange: NSMakeRange(self->dataIdx, self->byteLen - self->dataIdx)]; } - (NSData *)readBodyUnknownLength { return (self->source) ? [self readBodyUnknownLengthStream] : [self readBodyUnknownLengthData]; } - (NSData *)readBodyWithKnownLengthFromStream:(unsigned)_len { NGIOReadMethodType readBytes = NULL; NSData *rbody = nil; unsigned char *buf = NULL; int readB = 0; *(&readBytes) = NULL; if ([self->source respondsToSelector:@selector(methodForSelector:)]) { readBytes = (NGIOReadMethodType) [self->source methodForSelector:@selector(readBytes:count:)]; } *(&buf) = NULL; readB = 0; buf = calloc(_len, sizeof(char)); if (!buf) { [NSException raise: @"MIMEPartReadException" format: @"Can't alloc memory"]; return nil; } NS_DURING { NS_DURING { if (self->contentLength > self->bufLen) _la(self, self->bufLen - 1); else _la(self, self->contentLength - 1); } NS_HANDLER { if ([localException isKindOfClass:[NGEndOfStreamException class]]) { fprintf(stderr, "WARNING(%s): EOF occurred before whole content was read " "(content-length=%i, read=%i)\n", __PRETTY_FUNCTION__, self->contentLength, readB); } else { if (buf) free(buf); [localException raise]; } } NS_ENDHANDLER; while (self->contentLength != readB) { int tmp = self->contentLength - readB; readB += (readBytes != NULL) ? readBytes(self->source, @selector(readBytes:count:), (buf + readB), tmp) : [self->source readBytes:(buf + readB) count:tmp]; if (readB == NGStreamError) { [[self->source lastException] raise]; } tmp = self->contentLength - readB; if (tmp > 0) { if (tmp > self->bufLen) _la(self, self->bufLen - 1); else _la(self, tmp - 1); } } } NS_HANDLER { if ([localException isKindOfClass:[NGEndOfStreamException class]]) { fprintf(stderr, "WARNING(%s): EOF occurred before whole content was read " "(content-length=%i, read=%i)\n", __PRETTY_FUNCTION__, self->contentLength, readB); } else { if (buf) free(buf); [localException raise]; } } NS_ENDHANDLER; rbody = buf ? [NSData dataWithBytes:buf length:readB] : nil; if (buf) free(buf); return rbody; } - (NSData *)readBodyWithKnownLengthFromData:(unsigned)_len { NSData *data; data = [self->sourceData subdataWithRange: NSMakeRange(self->dataIdx, self->byteLen - self->dataIdx)]; if ([data length] != _len) { NSLog(@"%s[%i]: got wrong data %d _len %d", __PRETTY_FUNCTION__, __LINE__, (int)[data length], _len); return nil; } return data; } - (NSData *)readBodyWithKnownLength:(unsigned)_len { return (self->source != nil) ? [self readBodyWithKnownLengthFromStream:_len] : [self readBodyWithKnownLengthFromData:_len]; } - (NSData *)applyTransferEncoding:(NSString *)_enc onData:(NSData *)_data{ // Note: this method is used in WebUI return [_data dataByApplyingMimeContentTransferEncoding:_enc]; } - (NSData *)readBody { /* Read data of body and apply content-transfer-encoding if required. */ NSAutoreleasePool *pool; NSData *rbody = nil; pool = [[NSAutoreleasePool alloc] init]; if (self->contentLength == -1) { rbody = [self readBodyUnknownLength]; } else if(self->contentLength > 0){ /* note: this is called only, if self->useContentLength is set ! */ rbody = [self readBodyWithKnownLength:self->contentLength]; } if ([self->contentTransferEncoding length] > 0) { NSData *new; new = [self applyTransferEncoding:self->contentTransferEncoding onData:rbody]; if (new) { ASSIGN(self->contentTransferEncoding, (id)nil); rbody = new; } else { [self logWithFormat:@"WARNING(%s): " @"encountered unknown content-transfer-encoding: '%@'", __PRETTY_FUNCTION__, self->contentTransferEncoding]; } } rbody = [rbody retain]; [pool release]; return [rbody autorelease]; } - (NSData *)decodeBody:(NSData *)_data ofPart:(id)_part { return (self->delegateRespondsTo.parserDecodeBodyOfPart) ? [self->delegate parser:self decodeBody:_data ofPart:_part] : _data; } - (NGMimeType *)defaultContentTypeForPart:(id)_part { static NGMimeType *octetType = nil; if (octetType == nil) octetType = [[NGMimeType mimeType:@"application/octet-stream"] retain]; return octetType; } - (id)parserForBodyOfPart:(id)_p data:(NSData *)_dt { id ctype; NGMimeType *contentType; id bodyParser = nil; ctype = [_p contentType]; if (!ctype && self->delegateRespondsTo.parserContentTypeOfPart) ctype = [self->delegate parser: self contentTypeOfPart: _p]; contentType = ([ctype isKindOfClass:[NGMimeType class]]) ? ctype : [NGMimeType mimeType:[ctype stringValue]]; if (self->delegateRespondsTo.parserBodyParserForPart) { if ((bodyParser = [self->delegate parser:self bodyParserForPart:_p])) return bodyParser; } if (contentType == nil) { contentType = [self defaultContentTypeForPart:_p]; } if (contentType) { if ([[contentType type] isEqualToString:@"multipart"]) { bodyParser = [[[NGMimeMultipartBodyParser alloc] init] autorelease]; } else if ([[contentType type] isEqualToString:@"text"] && [[contentType subType] isEqualToString:@"plain"]) { bodyParser = [[[NGMimeTextBodyParser alloc] init] autorelease]; } } return bodyParser; } - (void)parseBodyOfPart:(id)_part { NGMimeBodyParser *parser = nil; NSData *rawBody = nil; id body = nil; rawBody = [self readBody]; /* apply content-encoding, transfer-encoding and similar */ rawBody = [self decodeBody:rawBody ofPart:_part]; if (self->delegateRespondsTo.parserParseRawBodyDataOfPart) { BOOL didParse; didParse = [self->delegate parser:self parseRawBodyData:rawBody ofPart:_part]; if (didParse) return; } parser = (NGMimeBodyParser *)[self parserForBodyOfPart:_part data:rawBody]; if (parser) { /* make sure delegate keeps being around .. */ self->delegate = [[self->delegate retain] autorelease]; body = [parser parseBodyOfPart:_part data:rawBody delegate:self->delegate]; } else if (rawBody) { /* no parser found for body */ if (body == nil) body = rawBody; } [_part setBody:body]; } /* part */ - (id)producePartWithHeader:(NGHashMap *)_header { [self subclassResponsibility:_cmd]; return nil; } - (BOOL)prepareForParsingFromData:(NSData *)_data { if (_data == nil) return NO; ASSIGN(self->sourceData, _data); self->sourceBytes = [self->sourceData bytes]; self->byteLen = [self->sourceData length]; self->dataIdx = 0; self->contentLength = -1; return YES; } - (BOOL)prepareForParsingFromStream:(id)_stream { if (_stream == nil) return NO; if (self->source != _stream) { NGByteBuffer *bb; bb = [NGByteBuffer alloc]; bb = [bb initWithSource:_stream la:self->bufLen]; [self->source release]; self->source = bb; } if ([self->source respondsToSelector:@selector(methodForSelector:)]) { self->la = (int (*)(id, SEL, unsigned)) [self->source methodForSelector:@selector(la:)]; self->consume = (void (*)(id, SEL)) [self->source methodForSelector:@selector(consume)]; self->consumeCnt = (void (*)(id, SEL, unsigned)) [self->source methodForSelector:@selector(consume:)]; } else { self->la = NULL; self->consume = NULL; self->consumeCnt = NULL; } self->contentLength = -1; return YES; } - (void)finishParsingOfPart:(id)_part { [self->source release]; self->source = nil; self->contentLength = -1; self->la = NULL; self->consume = NULL; self->consumeCnt = NULL; } - (void)finishParsingOfPartFromData:(id)_part { [self->sourceData release]; self->sourceData = nil; self->sourceBytes = NULL; self->byteLen = 0; self->dataIdx = 0; self->contentLength = -1; } - (BOOL)parsePrefix { return YES; } - (void)parseSuffix { } - (id)parsePart { id part = nil; NGHashMap *header; BOOL doParse = YES; if (![self parsePrefix]) return nil; if ((header = [self parseHeader]) == nil) return nil; part = [self producePartWithHeader:header]; doParse = (delegateRespondsTo.parserWillParseBodyOfPart) ? [delegate parser:self willParseBodyOfPart:part] : YES; if (doParse) { NSAutoreleasePool *pool; pool = [[NSAutoreleasePool alloc] init]; [self parseBodyOfPart:part]; [pool release]; if (delegateRespondsTo.parserDidParseBodyOfPart) [delegate parser:self didParseBodyOfPart:part]; [self parseSuffix]; } return part; } - (id)parsePartFromStream:(id)_stream { id p; if (![self prepareForParsingFromStream:_stream]) return nil; p = [self parsePart]; [self finishParsingOfPart:p]; return p; } - (id)parsePartFromData:(NSData *)_data { id part; if ([_data isKindOfClass:NSMutableDataClass]) { NGDataStream *dataStream; dataStream = [NGDataStream streamWithData:_data]; part = [self parsePartFromStream:dataStream]; [dataStream close]; return part; } if ([self prepareForParsingFromData:_data]) { part = [self parsePart]; [self finishParsingOfPartFromData:part]; return part; } return nil; } /* accessors */ - (BOOL)doesUseContentLength { return self->useContentLength; } - (void)setUseContentLength:(BOOL)_use { self->useContentLength = _use; } /* functions */ static inline int _la(NGMimePartParser *self, int _la) { if (self->source) { return (self->la != NULL) ? self->la(self->source, @selector(la:), _la) : [self->source la:_la]; } else { if ((self->dataIdx+_la) < self->byteLen) return self->sourceBytes[self->dataIdx+_la]; else return -1; } } static inline void _consume(NGMimePartParser *self, int _cnt) { if (self->source) { if (_cnt == 1) { if (self->consume != NULL) self->consume(self->source, @selector(consume)); else [self->source consume]; } else { if (self->consumeCnt != NULL) self->consumeCnt(self->source, @selector(consume:), _cnt); else [self->source consume:_cnt]; } } else { if ((self->dataIdx+_cnt) <= self->byteLen) { self->dataIdx += _cnt; } else { NSLog(@"%s[%i]: error try to read over buffer len self->dataIdx %d " @"_cnt %d byteLen %d", __PRETTY_FUNCTION__, __LINE__, self->dataIdx, _cnt, self->byteLen); } } } static inline BOOL _checkKey(NGMimePartParser *self, NGHashMap *_map, NSString *_key) { if (HeaderNames == NULL) [NGMimePartParser headerFieldNames]; if ((_key == HeaderNames->contentLength) || _key == HeaderNames->contentType) { if ([_map countObjectsForKey:_key] > 0) return NO; } return YES; } @end /* NGMimePartParser */ SOPE/sope-mime/NGMime/NSData+RFC822.m0000644000000000000000000000307615004363604015472 0ustar rootroot/* Copyright (C) 2012 Inverse inc Author: Wolfgang Sourdeau This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "NSData+RFC822.h" @implementation NSData (NGRFC822) - (NSData *) dataByEnsuringCRLFLineEndings { NSData *newData; const char *bytesOld; char *bytesNew; NSUInteger lenOld, cntOld, cntNew; bytesOld = [self bytes]; lenOld = [self length]; bytesNew = NSZoneMalloc (NULL, lenOld * 2); cntNew = 0; for (cntOld = 0; cntOld < lenOld; cntOld++) if (bytesOld[cntOld] != '\r') { if (bytesOld[cntOld] == '\n') { bytesNew[cntNew] = '\r'; cntNew++; } bytesNew[cntNew] = bytesOld[cntOld]; cntNew++; } newData = [NSData dataWithBytesNoCopy: bytesNew length: cntNew freeWhenDone: YES]; return newData; } @end SOPE/sope-mime/NGMime/NGMimeBodyParser.m0000644000000000000000000000546515004363604016631 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeBodyParser.h" #include "NGMimeBodyPartParser.h" #include "NGMimeMultipartBody.h" #include "common.h" @implementation NGMimeBodyParser - (id)parseBodyOfPart:(id)_part data:(NSData *)_data delegate:(id)_d { return _data; } @end /* NGMimeBodyParser */ @implementation NGMimeTextBodyParser static int UseFoundationStringEncodingForMimeText = -1; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; if (UseFoundationStringEncodingForMimeText == -1) { UseFoundationStringEncodingForMimeText = [ud boolForKey:@"UseFoundationStringEncodingForMimeText"]?1:0; } } - (id)parseBodyOfPart:(id)_part data:(NSData *)_data delegate:(id)_d { NSString *charset; id ctype, body; if (_data == nil) return nil; ctype = [_part contentType]; if (!ctype && [_d respondsToSelector: @selector(parser:contentTypeOfPart:)]) ctype = [_d parser: self contentTypeOfPart: _part]; if (![ctype isKindOfClass:[NGMimeType class]]) ctype = [NGMimeType mimeType:[ctype stringValue]]; charset = [[ctype valueOfParameter:NGMimeParameterTextCharset] lowercaseString]; body = nil; if (!UseFoundationStringEncodingForMimeText) { if (![_data length]) return @""; if (![[charset lowercaseString] isEqualToString:@"us-ascii"] && [charset length]) { body = [NSString stringWithData:_data usingEncodingNamed:charset]; } } if (!body) { NSStringEncoding encoding; encoding = [NGMimeType stringEncodingForCharset:charset]; // If we nave no encoding here, let's not simply return nil. // We SHOULD try at least UTF-8 and after, Latin1. if (!encoding) encoding = NSUTF8StringEncoding; body = [[[NSString alloc] initWithData:_data encoding:encoding] autorelease]; if (!body) body = [[[NSString alloc] initWithData:_data encoding:NSISOLatin1StringEncoding] autorelease]; } return body; } @end /* NGMimeTextBodyParser */ SOPE/sope-mime/NGMime/NGMimeBodyPart.m0000644000000000000000000001410115004363604016266 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeBodyPart.h" #include "NGMimeType.h" #include "common.h" #include "NGMimeFileData.h" #include @implementation NGMimeBodyPart + (id)bodyPartWithHeader:(NGHashMap *)_header { return [[[self alloc] initWithHeader:_header] autorelease]; } - (id)initWithHeader:(NGHashMap *)_header { if ((self = [super init])) { if (_header) self->header = [NGMutableHashMap hashMapWithHashMap: _header]; else self->header = [NGMutableHashMap hashMap]; [self->header retain]; self->body = nil; } return self; } - (id)init { return [self initWithHeader:nil]; } - (void)dealloc { [self->header release]; [self->body release]; [super dealloc]; } /* NGPart */ - (NSEnumerator *)valuesOfHeaderFieldWithName:(NSString *)_name { return [self->header objectEnumeratorForKey:_name]; } - (NSEnumerator *)headerFieldNames { return [self->header keyEnumerator]; } - (void)setBody:(id)_body { ASSIGN(self->body, _body); } - (id)body { return self->body; } /* convenience */ - (NSString *)headerForKey:(NSString *)_key { return [[self->header objectEnumeratorForKey:_key] nextObject]; } - (void) setHeader: (id) _header forKey: (NSString *)_key { [self->header setObject: _header forKey: _key]; } - (NSArray *)headersForKey:(NSString *)_key { NSEnumerator *values; NSMutableArray *array; id value; if ((values = [self->header objectEnumeratorForKey:_key]) == nil) return nil; array = [NSMutableArray arrayWithCapacity:4]; while ((value = [values nextObject]) != nil) [array addObject:value]; return array; } - (NSArray *)headerKeys { NSEnumerator *values; NSMutableArray *array = nil; id name = nil; if ((values = [self->header keyEnumerator]) == nil) return nil; array = [[NSMutableArray alloc] init]; while ((name = [values nextObject]) != nil) [array addObject:name]; name = [array copy]; [array release]; return [name autorelease]; } - (NSDictionary *)headers { return [self->header asDictionary]; } - (NSString *)headersAsString { // TODO: not correct for MIME NSMutableString *ms; NSEnumerator *keys; NSString *key; ms = [NSMutableString stringWithCapacity:1024]; /* headers */ keys = [[self headerKeys] objectEnumerator]; while ((key = [keys nextObject]) != nil) { NSEnumerator *vals; id val; vals = [[self headersForKey:key] objectEnumerator]; while ((val = [vals nextObject])) { [ms appendString:key]; [ms appendString:@": "]; [ms appendString:[val stringValue]]; [ms appendString:@"\r\n"]; } } return ms; } /* NGMimePart */ - (NGMimeType *)contentType { id type; static NGMimeHeaderNames *Fields = NULL; if (!Fields) Fields = (NGMimeHeaderNames *)[NGMimePartParser headerFieldNames]; type = [self->header objectForKey:Fields->contentType]; if (![type isKindOfClass:[NGMimeType class]]) type = [NGMimeType mimeType:[type stringValue]]; return type; } - (NSString *)contentId { return [[self->header objectForKey:@"content-id"] stringValue]; } - (NSArray *)contentLanguage { id value; value = [self->header objectForKey:@"content-language"]; if (![value isKindOfClass:[NSArray class]]) value = [value componentsSeparatedByString:@","]; return value; } - (NSString *)contentMd5 { return [[self->header objectForKey:@"content-md5"] stringValue]; } - (NSString *)encoding { return [[self->header objectForKey:@"content-transfer-encoding"] stringValue]; } - (NSString *)contentDescription { return [[self->header objectForKey:@"content-description"] stringValue]; } /* description */ - (NSString *)description { NSMutableString *d; id b = [self body]; d = [NSMutableString stringWithCapacity:128]; [d appendFormat:@"<%@[0x%p]: header=%@", NSStringFromClass([self class]), self, self->header]; if (b) [d appendFormat:@" bodyClass=%@", NSStringFromClass([b class])]; if ([b isKindOfClass:[NGMimeFileData class]]) { [d appendFormat:@" body=%@", b]; } else if ([b isKindOfClass:[NSString class]] || [b isKindOfClass:[NSData class]]) { if ([b length] < 512) { [d appendFormat:@" bodyLen=%i body=%@", (int)[b length], b]; } else [d appendFormat:@" body[len=%i]", (int)[b length]]; } else [d appendFormat:@" body=%@", b]; [d appendString:@">"]; return d; } - (NSDictionary *) bodyInfo { NSMutableDictionary *d; id o; d = [NSMutableDictionary dictionary]; if ((o = [[self contentType] type])) [d setObject: o forKey: @"type"]; if ((o = [[self contentType] subType])) [d setObject: o forKey: @"subtype"]; if ((o = [self contentId])) [d setObject: o forKey: @"bodyId"]; o = [self headerForKey: @"content-disposition"]; if ([o filename]) { NSDictionary *parameterList; NSMutableDictionary *disposition; parameterList = [NSDictionary dictionaryWithObject: [o filename] forKey: @"filename"]; disposition = [NSMutableDictionary dictionaryWithObject: parameterList forKey: @"parameterList"]; if ([o type]) [disposition setObject: [o type] forKey: @"type"]; [d setObject: disposition forKey: @"disposition"]; } if ((o = [self headerForKey: @"content-length"])) [d setObject: o forKey: @"size"]; return d; } @end /* NGMimeBodyPart */ SOPE/sope-mime/NGMime/NGMimeRFC822DateHeaderFieldGenerator.m0000644000000000000000000000541515004363604022142 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeHeaderFieldGenerator.h" #include "NGMimeHeaderFields.h" #include "common.h" @implementation NGMimeRFC822DateHeaderFieldGenerator - (NSData *)generateDataForHeaderFieldNamed:(NSString *)_headerField value:(id)_value { NSCalendarDate *date = nil; NSString *dateString = nil; if ([_value isKindOfClass:[NSString class]]) return [_value dataUsingEncoding:NSUTF8StringEncoding]; date = _value; if (date == nil) return [NSData data]; if ([date respondsToSelector:@selector(descriptionWithCalendarFormat:)]) { // TODO: do not use -descriptionWithCalendarFormat: ! // - slow #if GNUSTEP_BASE_MINOR_VERSION < 21 dateString = [date descriptionWithCalendarFormat: @" %a, %d %b %Y %H:%M:%S %z"]; #else dateString = [date descriptionWithCalendarFormat: @" %a, %d %b %Y %H:%M:%S %z" timeZone: [NSTimeZone timeZoneWithName: @"GMT"] locale: [NSDictionary dictionaryWithObjectsAndKeys: [NSArray arrayWithObjects: @"Jan", @"Feb", @"Mar", @"Apr", @"May", @"Jun", @"Jul", @"Aug", @"Sep", @"Oct", @"Nov", @"Dec", nil], @"NSShortMonthNameArray", [NSArray arrayWithObjects: @"Sun", @"Mon", @"Tue", @"Wed", @"Thu", @"Fri", @"Sat", nil], @"NSShortWeekDayNameArray", nil]]; #endif } else dateString = [date stringValue]; return [dateString dataUsingEncoding:NSUTF8StringEncoding]; } @end /* NGMimeRFC822DateHeaderFieldGenerator */ SOPE/sope-mime/NGMime/SxCore-NGMime.graffle0000644000000000000000000035646515004363604017222 0ustar rootroot CanvasColor w 1.000000e+00 ColumnAlign 0 ColumnSpacing 5.400000e+01 GraphDocumentVersion 2 GraphicsList Bounds {{8.75, 730}, {109, 36}} Class ShapedGraphic FitText YES ID 163 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-BoldOblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\b\fs48 \cf0 NGMime} Bounds {{548.75, 730}, {109, 36}} Class ShapedGraphic FitText YES ID 162 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-BoldOblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\b\fs48 \cf0 NGMime} Bounds {{548.75, 10}, {109, 36}} Class ShapedGraphic FitText YES ID 161 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-BoldOblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\b\fs48 \cf0 NGMime} Bounds {{8.75, 10}, {109, 36}} Class ShapedGraphic FitText YES ID 160 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-BoldOblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\b\fs48 \cf0 NGMime} Bounds {{99, 1368}, {162, 18}} Class ShapedGraphic ID 159 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4ResponseParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGImap4ResponseParser} Class Group Graphics Bounds {{819, 648}, {189, 18}} Class ShapedGraphic ID 134 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGConcreteMimeType.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGConcreteAudioMimeType} Bounds {{603, 648}, {198, 18}} Class ShapedGraphic ID 135 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGConcreteMimeType.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGConcreteMultipartMimeType} Bounds {{819, 504}, {189, 18}} Class ShapedGraphic ID 136 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGConcreteMimeType.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGConcreteGenericMimeType} Bounds {{603, 621}, {198, 18}} Class ShapedGraphic ID 137 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGConcreteMimeType.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGConcreteVideoMimeType} Bounds {{603, 594}, {198, 18}} Class ShapedGraphic ID 138 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGConcreteMimeType.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGConcreteApplicationMimeType} Bounds {{819, 477}, {189, 18}} Class ShapedGraphic ID 139 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGConcreteMimeType.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGConcreteAppOctetMimeType} Bounds {{819, 594}, {189, 18}} Class ShapedGraphic ID 140 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGConcreteMimeType.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGConcreteMessageMimeType} Bounds {{603, 450}, {189, 18}} Class ShapedGraphic ID 141 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGConcreteMimeType.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGConcreteTextMimeType} Bounds {{603, 495}, {189, 18}} Class ShapedGraphic ID 142 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGConcreteMimeType.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGConcreteTextVcardMimeType} Bounds {{711, 387}, {189, 18}} Class ShapedGraphic ID 143 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeType.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeType} Bounds {{819, 450}, {189, 18}} Class ShapedGraphic ID 144 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGConcreteMimeType.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGConcreteWildcardType} Bounds {{711, 549}, {189, 18}} Class ShapedGraphic ID 145 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGConcreteMimeType.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGParameterMimeType} Bounds {{819, 621}, {189, 18}} Class ShapedGraphic ID 146 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGConcreteMimeType.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGConcreteImageMimeType} Class LineGraphic Head ID 134 ID 147 Points {815.318, 567} {903.682, 648} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 145 Class LineGraphic Head ID 135 ID 148 Points {796.091, 567} {711.409, 648} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 145 Class LineGraphic Head ID 136 ID 149 Points {813.808, 405} {905.192, 504} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 143 Class LineGraphic Head ID 137 ID 150 Points {792.562, 567} {714.938, 621} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 145 Class LineGraphic Head ID 138 ID 151 Points {784.8, 567} {722.7, 594} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 145 Class LineGraphic Head ID 139 ID 152 Points {816.3, 405} {902.7, 477} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 143 Class LineGraphic Head ID 140 ID 153 Points {827.1, 567} {891.9, 594} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 145 Class LineGraphic Head ID 141 ID 154 Points {790.071, 405} {712.929, 450} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 143 Class LineGraphic Head ID 145 ID 155 Points {805.5, 405} {805.5, 549} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 143 Class LineGraphic Head ID 142 ID 156 Points {697.5, 468} {697.5, 495} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 141 Class LineGraphic Head ID 144 ID 157 Points {820.929, 405} {898.071, 450} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 143 Class LineGraphic Head ID 146 ID 158 Points {819, 567} {900, 621} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 145 ID 133 Bounds {{63, 495}, {126, 18}} Class ShapedGraphic ID 132 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGMimeMessage.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeMessage} Bounds {{99, 1341}, {162, 18}} Class ShapedGraphic ID 131 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGPop3Support.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGPop3MessageInfo} Class Group Graphics Bounds {{756, 1341}, {243, 18}} Class ShapedGraphic ID 118 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGMimeMessageGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeMessageMultipartBodyGenerator} Bounds {{783, 1251}, {189, 18}} Class ShapedGraphic ID 119 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeBodyGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeMultipartBodyGenerator} Bounds {{666, 1314}, {243, 18}} Class ShapedGraphic ID 120 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGMimeMessageGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeMessageTextBodyGenerator} Bounds {{693, 1224}, {189, 18}} Class ShapedGraphic ID 121 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeBodyGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeTextBodyGenerator} Bounds {{864, 1188}, {189, 18}} Class ShapedGraphic ID 122 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGMimeMessageGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeMessageBodyGenerator} Bounds {{900, 1152}, {153, 18}} Class ShapedGraphic ID 123 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeGeneratorProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGMimeBodyGenerator} Bounds {{585, 1287}, {243, 18}} Class ShapedGraphic ID 124 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGMimeMessageGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeMessageRfc822BodyGenerator} Bounds {{612, 1197}, {189, 18}} Class ShapedGraphic ID 125 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeBodyGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeRfc822BodyGenerator} Bounds {{720, 1152}, {153, 18}} Class ShapedGraphic ID 126 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeBodyGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeBodyGenerator} Class LineGraphic Head ID 118 ID 127 Points {877.5, 1269} {877.5, 1341} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 119 Class LineGraphic Head ID 119 ID 128 Points {803.864, 1170} {870.136, 1251} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 126 Class LineGraphic Head ID 122 ID 129 Points {837, 1170} {918, 1188} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 126 Class LineGraphic Head ID 126 ID 130 Points {900, 1161} {873, 1161} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 123 ID 117 Class Group Graphics Bounds {{99, 1017}, {153, 18}} Class ShapedGraphic ID 112 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape Rectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGFileManager} Bounds {{288, 1053}, {153, 18}} Class ShapedGraphic ID 113 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4FileManager.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGImap4FileManager} Bounds {{288, 1017}, {153, 18}} Class ShapedGraphic ID 114 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileManager.h Shape RoundedRectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGFileManager} Class LineGraphic Head ID 114 ID 115 Points {252, 1026} {288, 1026} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 112 Class LineGraphic Head ID 113 ID 116 Points {364.5, 1035} {364.5, 1053} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 114 ID 111 Bounds {{801, 1035}, {252, 18}} Class ShapedGraphic ID 110 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFieldGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeContentTypeHeaderFieldGenerator} Class Group Graphics Bounds {{855, 36}, {126, 18}} Class ShapedGraphic ID 101 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeBodyParser.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGMimeBodyParser} Bounds {{630, 72}, {171, 18}} Class ShapedGraphic ID 102 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeBodyParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeRfc822BodyParser} Bounds {{810, 72}, {171, 18}} Class ShapedGraphic ID 103 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeBodyParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeTextBodyParser} Bounds {{702, 36}, {135, 18}} Class ShapedGraphic ID 104 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeBodyParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeBodyParser} Bounds {{684, 108}, {171, 18}} Class ShapedGraphic ID 105 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeBodyParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeMultipartBodyParser} Class LineGraphic Head ID 104 ID 106 Points {855, 45} {837, 45} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 101 Class LineGraphic Head ID 102 ID 107 Points {756, 54} {729, 72} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 104 Class LineGraphic Head ID 103 ID 108 Points {801, 54} {864, 72} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 104 Class LineGraphic Head ID 105 ID 109 Points {769.5, 54} {769.5, 108} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 104 ID 100 Bounds {{558, 1008}, {279, 18}} Class ShapedGraphic ID 99 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFieldGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeAddressHeaderFieldGenerator} Bounds {{99, 1314}, {162, 18}} Class ShapedGraphic ID 98 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Client.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGImap4Client} Bounds {{846, 801}, {207, 18}} Class ShapedGraphic ID 97 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFieldGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeHeaderFieldGeneratorSet} Bounds {{99, 1287}, {162, 18}} Class ShapedGraphic ID 96 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGSmtpClient.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGSmtpClient} Bounds {{99, 1260}, {162, 18}} Class ShapedGraphic ID 95 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGSmtpSupport.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGSmtpResponse} Bounds {{801, 981}, {252, 18}} Class ShapedGraphic ID 94 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFieldGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeRFC822DateHeaderFieldGenerator} Bounds {{63, 450}, {126, 18}} Class ShapedGraphic ID 93 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGPart.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGMimePart} Bounds {{198, 495}, {126, 18}} Class ShapedGraphic ID 92 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeBodyPart.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeBodyPart} Bounds {{225, 666}, {162, 18}} Class ShapedGraphic ID 91 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGMimeMessageGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeMessageGenerator} Class Group Graphics Bounds {{585, 207}, {126, 18}} Class ShapedGraphic ID 73 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGPop3Support.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGPop3Exception} Bounds {{576, 243}, {144, 18}} Class ShapedGraphic ID 74 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGPop3Support.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGPop3StateException} Bounds {{900, 207}, {126, 18}} Class ShapedGraphic ID 75 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeException} Bounds {{882, 243}, {162, 18}} Class ShapedGraphic ID 76 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeExceptions.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeParserException} Bounds {{819, 324}, {180, 18}} Class ShapedGraphic ID 77 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Support.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGImap4ResponseException} Bounds {{846, 288}, {180, 18}} Class ShapedGraphic ID 78 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Support.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGImap4SearchException} Bounds {{621, 324}, {180, 18}} Class ShapedGraphic ID 79 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Support.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGImap4ParserException} Bounds {{594, 288}, {180, 18}} Class ShapedGraphic ID 80 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Support.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGImap4ConnectionException} Bounds {{747, 162}, {126, 18}} Class ShapedGraphic ID 81 Shape RoundedRectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NSException} Bounds {{747, 207}, {126, 18}} Class ShapedGraphic ID 82 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Support.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGImap4Exception} Class LineGraphic Head ID 75 ID 83 Points {840.6, 180} {932.4, 207} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 81 Class LineGraphic Head ID 73 ID 84 Points {777.6, 180} {680.4, 207} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 81 Class LineGraphic Head ID 76 ID 85 Points {963, 225} {963, 243} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 75 Class LineGraphic Head ID 77 ID 86 Points {817.615, 225} {901.385, 324} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 82 Class LineGraphic Head ID 78 ID 87 Points {824, 225} {922, 288} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 82 Class LineGraphic Head ID 79 ID 88 Points {802.385, 225} {718.615, 324} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 82 Class LineGraphic Head ID 80 ID 89 Points {796, 225} {698, 288} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 82 Class LineGraphic Head ID 82 ID 90 Points {810, 180} {810, 207} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 81 ID 72 Class Group Graphics Bounds {{45, 963}, {261, 18}} Class ShapedGraphic ID 60 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFieldParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeRFC822DateHeaderFieldParser} Bounds {{243, 936}, {243, 18}} Class ShapedGraphic ID 61 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFieldParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeContentLengthHeaderFieldParser} Bounds {{126, 774}, {180, 18}} Class ShapedGraphic ID 62 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFieldParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeHeaderFieldParserSet} Bounds {{324, 774}, {162, 18}} Class ShapedGraphic ID 63 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFieldParser.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGMimeHeaderFieldParser} Bounds {{45, 909}, {261, 18}} Class ShapedGraphic ID 64 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFieldParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeContentTypeHeaderFieldParser} Bounds {{243, 882}, {243, 18}} Class ShapedGraphic ID 65 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFieldParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeStringHeaderFieldParser} Bounds {{126, 810}, {180, 18}} Class ShapedGraphic ID 66 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFieldParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeHeaderFieldParser} Bounds {{45, 855}, {261, 18}} Class ShapedGraphic ID 67 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFieldParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeContentDispositionHeaderFieldParser} Class LineGraphic Head ID 61 ID 68 Points {226.607, 828} {353.893, 936} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 66 Class LineGraphic Head ID 62 ID 69 Points {324, 783} {306, 783} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 63 Class LineGraphic Head ID 66 ID 70 Points {357.75, 792} {263.25, 810} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 63 Class LineGraphic Head ID 65 ID 71 Points {234.562, 828} {345.938, 882} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 66 ID 59 Bounds {{99, 1233}, {162, 18}} Class ShapedGraphic ID 58 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeMultipartBody.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeMultipartBody} Bounds {{207, 405}, {144, 18}} Class ShapedGraphic ID 57 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeBodyPartParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeBodyPartParser} Bounds {{54, 306}, {180, 18}} Class ShapedGraphic ID 56 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGPop3Support.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGPop3MailDropEnumerator} Bounds {{288, 72}, {171, 18}} Class ShapedGraphic ID 55 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGExtensions/NGFileFolderInfoDataSource.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGFileFolderInfoDataSource} Bounds {{99, 1206}, {162, 18}} Class ShapedGraphic ID 54 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGMailAddressList.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMailAddressList} Bounds {{99, 1179}, {162, 18}} Class ShapedGraphic ID 53 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGMailAddressParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMailAddressParser} Bounds {{126, 360}, {144, 18}} Class ShapedGraphic ID 52 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimePartParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimePartParser} Bounds {{54, 405}, {144, 18}} Class ShapedGraphic ID 51 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGMimeMessageParser.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeMessageParser} Bounds {{558, 954}, {279, 18}} Class ShapedGraphic ID 50 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFieldGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeContentLengthHeaderFieldGenerator} Bounds {{90, 72}, {171, 18}} Class ShapedGraphic ID 49 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4DataSource.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGImap4DataSource} Bounds {{801, 927}, {252, 18}} Class ShapedGraphic ID 48 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFieldGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeStringHeaderFieldGenerator} Bounds {{99, 1152}, {162, 18}} Class ShapedGraphic ID 47 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGMailAddress.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMailAddress} Bounds {{198, 567}, {126, 18}} Class ShapedGraphic ID 46 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Folder.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGImap4Folder} Bounds {{99, 1125}, {162, 18}} Class ShapedGraphic ID 45 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Message.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGImap4Message} Bounds {{558, 1080}, {279, 18}} Class ShapedGraphic ID 44 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFields.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeContentDispositionHeaderField} Bounds {{243, 306}, {180, 18}} Class ShapedGraphic ID 43 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGMBoxReader.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMBoxReader} Bounds {{288, 1152}, {162, 18}} Class ShapedGraphic ID 42 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGPop3Client.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGPop3Client} Bounds {{144, 270}, {180, 18}} Class ShapedGraphic ID 41 Shape RoundedRectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NSEnumerator} Bounds {{288, 1125}, {162, 18}} Class ShapedGraphic ID 40 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMail/NGPop3Support.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGPop3Response} Bounds {{63, 531}, {126, 18}} Class ShapedGraphic ID 39 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Support.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGImap4Folder} Bounds {{63, 567}, {126, 18}} Class ShapedGraphic ID 38 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4ServerRoot.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGImap4ServerRoot} Bounds {{720, 756}, {189, 18}} Class ShapedGraphic ID 37 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeGeneratorProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGMimeHeaderFieldGenerator} Bounds {{54, 144}, {180, 18}} Class ShapedGraphic ID 36 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Support.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGImap4ResponseReceiver} Bounds {{54, 180}, {180, 18}} Class ShapedGraphic ID 35 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGImap4/NGImap4Context.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGImap4Context} Bounds {{63, 630}, {135, 18}} Class ShapedGraphic ID 34 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeGeneratorProtocols.h Shape Rectangle Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf0 NGMimePartGenerator} Bounds {{225, 630}, {162, 18}} Class ShapedGraphic ID 33 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimePartGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimePartGenerator} Bounds {{711, 846}, {207, 18}} Class ShapedGraphic ID 32 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFieldGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeHeaderFieldGenerator} Bounds {{558, 900}, {279, 18}} Class ShapedGraphic ID 31 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/NGMime/NGMimeHeaderFieldGenerator.h Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 NGMimeContentDispositionHeaderFieldGenerator} Bounds {{189, 36}, {171, 18}} Class ShapedGraphic ID 30 Link url file://localhost/Volumes/Jaguar/Users/helge/dev/pkg42/skyrix-core-42/EOControl/EODataSource.h Shape RoundedRectangle Style fill Color b 5.000000e-01 g 1.000000e+00 r 1.000000e+00 Text Text {\rtf1\mac\ansicpg10000\cocoartf100 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 EODataSource} Class LineGraphic Head ID 132 ID 29 Points {126, 468} {126, 495} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 93 Class LineGraphic Head ID 110 ID 28 Points {819.857, 864} {921.643, 1035} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 32 Class LineGraphic Head ID 99 ID 27 Points {808, 864} {704, 1008} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 32 Class LineGraphic Head ID 97 ID 26 Points {841.5, 774} {922.5, 801} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 37 Class LineGraphic Head ID 94 ID 25 Points {822, 864} {919.5, 981} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 32 Class LineGraphic Head ID 92 ID 24 Points {153, 468} {234, 495} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 93 Class LineGraphic Head ID 120 ID 23 Points {787.5, 1242} {787.5, 1314} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 121 Class LineGraphic Head ID 91 ID 22 Points {306, 648} {306, 666} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 33 Class LineGraphic Head ID 74 ID 21 Points {648, 225} {648, 243} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 73 Class LineGraphic Head ID 60 ID 20 Points {213.618, 828} {177.882, 963} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 66 Class LineGraphic Head ID 57 ID 19 Points {214.2, 378} {262.8, 405} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 52 Class LineGraphic Head ID 56 ID 18 Points {211.5, 288} {166.5, 306} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 41 Class LineGraphic Head ID 55 ID 17 Points {299.25, 54} {348.75, 72} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 30 Class LineGraphic Head ID 51 ID 16 Points {183.6, 378} {140.4, 405} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 52 Class LineGraphic Head ID 50 ID 15 Points {804.75, 864} {707.25, 954} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 32 Class LineGraphic Head ID 49 ID 14 Points {249.75, 54} {200.25, 72} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 30 Class LineGraphic Head ID 121 ID 13 Points {795.375, 1170} {788.625, 1224} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 126 Class LineGraphic Head ID 64 ID 12 Points {212.318, 828} {179.182, 909} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 66 Class LineGraphic Head ID 48 ID 11 Points {827, 864} {914.5, 927} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 32 Class LineGraphic Head ID 46 ID 10 Points {159.75, 549} {227.25, 567} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 39 Class LineGraphic Head ID 124 ID 9 Points {706.5, 1215} {706.5, 1287} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 125 Class LineGraphic Head ID 43 ID 8 Points {258.75, 288} {308.25, 306} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 41 Class LineGraphic Head ID 125 ID 7 Points {778.5, 1170} {724.5, 1197} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 126 Class LineGraphic Head ID 38 ID 6 Points {126, 549} {126, 567} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 39 Class LineGraphic Head ID 32 ID 5 Points {814.5, 774} {814.5, 846} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 37 Class LineGraphic Head ID 35 ID 4 Points {144, 162} {144, 180} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 36 Class LineGraphic Head ID 33 ID 3 Points {198, 639} {225, 639} Style stroke Color b 0.000000e+00 g 0.000000e+00 r 1.000000e+00 HeadArrow 0 TailArrow FilledBall Tail ID 34 Class LineGraphic Head ID 67 ID 2 Points {207.9, 828} {183.6, 855} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 66 Class LineGraphic Head ID 31 ID 1 Points {795, 864} {717, 900} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 32 GridInfo HPages 2 ImageCounter 1 IsPalette NO Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo AutoAdjust YES HierarchicalOrientation 0 MagneticFieldCenter {0, 0} MagnetsEnabled YES PageBreakColor w 3.333333e-01 PageBreaks YES PageSetup BAt0eXBlZHN0cmVhbYED6IQBQISEhAtOU1ByaW50SW5mbwGEhAhOU09iamVjdACFkoSE hBNOU011dGFibGVEaWN0aW9uYXJ5AISEDE5TRGljdGlvbmFyeQCUhAFpFZKEhIQITlNT dHJpbmcBlIQBKw9OU1BhZ2VzUGVyU2hlZXSGkoSEhAhOU051bWJlcgCEhAdOU1ZhbHVl AJSEASqEhAFznQGGkoSZmRBOU0pvYkRpc3Bvc2l0aW9uhpKEmZkPTlNQcmludFNwb29s Sm9ihpKEmZkOTlNCb3R0b21NYXJnaW6GkoSbnISEAWaeJIaShJmZC05TUGFwZXJOYW1l hpKEmZkCQTSGkoSZmQ9OU1ByaW50QWxsUGFnZXOGkoSbnJ2dAIaShJmZDU5TSm9iRmVh dHVyZXOGkoSWlwCGkoSZmQ1OU1JpZ2h0TWFyZ2luhpKEm5yiniSGkoSZmQhOU0NvcGll c4aShJuchIQBU58BhpKEmZkPTlNTY2FsaW5nRmFjdG9yhpKEm5yEhAFkoAGGkoSZmQtO U0ZpcnN0UGFnZYaShJucrZ8BhpKEmZkUTlNWZXJ0aWNhbFBhZ2luYXRpb26GkoSbnJ2d AIaShJmZEk5TUmV2ZXJzZVBhZ2VPcmRlcoaShJuchIQBY6EAhpKEmZkVTlNIb3Jpem9u YWxQYWdpbmF0aW9uhpKEm5ydnQCGkoSZmRZOU0hvcml6b250YWxseUNlbnRlcmVkhpKE m5ydnQGGkoSZmQxOU0xlZnRNYXJnaW6GkoSbnKKeJIaShJmZDU5TT3JpZW50YXRpb26G koSbnJ2dAIaShJmZGU5TUHJpbnRSZXZlcnNlT3JpZW50YXRpb26GkraShJmZCk5TTGFz dFBhZ2WGkoSbnISXl4J/////hpKEmZkLTlNUb3BNYXJnaW6GkoSbnKKeJIaShJmZFE5T VmVydGljYWxseUNlbnRlcmVkhpK7koSZmQtOU1BhcGVyU2l6ZYaShJychIQMe19OU1Np emU9ZmZ9ooECU4EDSoaGhg== RowAlign 0 RowSpacing 9.000000e+00 VPages 2 WindowInfo Frame {{83, 91}, {566, 801}} VisibleRegion {{-24, 0}, {1102, 1448}} Zoom 0.5 SOPE/sope-mime/NGMime/timeMacros.h0000644000000000000000000000450715004363604015614 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if 0 #include #define TIME_START(_timeDescription) \ { \ struct timeval tv; \ double ti; \ char *timeDescription; \ unsigned int vm, vm1, rss, rss1; \ static double AddedTime = 0; \ static NSProcessInfo *ProcessInfo = nil; \ static int CountCalls = 0; \ \ if (ProcessInfo == nil) \ ProcessInfo = [[NSProcessInfo processInfo] retain]; \ \ *(&vm) = 0; \ *(&rss) = 0; \ *(&ti) = 0; \ {\ NSAutoreleasePool *p__1; \ p__1 = [NSAutoreleasePool new]; \ vm = [ProcessInfo virtualMemorySize]; \ rss = [ProcessInfo residentSetSize] * 4096; \ [p__1 release];\ }\ timeDescription = _timeDescription; \ gettimeofday(&tv, NULL); \ ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0 ); \ fprintf(stderr, "{"); \ #define TIME_END gettimeofday(&tv, NULL); \ gettimeofday(&tv, NULL); \ { \ NSAutoreleasePool *p__1 = [NSAutoreleasePool new]; \ vm1 = [ProcessInfo virtualMemorySize]; \ rss1 = [ProcessInfo residentSetSize] * 4096; \ [p__1 release]; \ }; \ ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0) - ti; \ AddedTime += ti; \ CountCalls++; \ fprintf(stderr,\ "}%s: <%s>[%d] : \n" \ " time needed: %4.4fs (%4.4fs) \n"\ " memory wasted virtual: %d absolut %d \n" \ " resident set size: %d absolute %d\n", \ __PRETTY_FUNCTION__, timeDescription, CountCalls,\ ti < 0.0 ? -1.0 : ti, AddedTime, vm1 - vm, vm1, rss1 - rss, rss1); \ } #else #define TIME_START(_timeDescription) #define TIME_END #endif SOPE/sope-mime/NGMime/NGMimeBodyParser.h0000644000000000000000000000451715004363604016621 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGMimeBodyParser_H__ #define __NGMime_NGMimeBodyParser_H__ #import #include @class NSData; @protocol NGMimeBodyParser < NSObject > - (id)parseBodyOfPart:(id)_part data:(NSData *)_data delegate:(id)_delegate; @end @interface NGMimeBodyParser : NSObject < NGMimeBodyParser > @end @interface NGMimeTextBodyParser : NGMimeBodyParser @end @class NGMimePartParser; @class NGMimeMultipartBody; /* A multipart body is a part body that contains body-parts separated by boundary lines. */ @interface NGMimeMultipartBodyParser : NGMimeBodyParser - (BOOL)parseBody:(NGMimeMultipartBody *)_body ofMultipart:(id)_part data:(NSData *)_data delegate:(id)_d; - (id)parseBodyPartWithData:(NSData *)_rawData inMultipart:(id)_multipart parser:(NGMimePartParser *)_parser; // usually a NGMimeBodyPartParser @end @interface NSObject(NGMimeMultipartBodyParserDelegate) - (BOOL)multipartBodyParser:(NGMimeMultipartBodyParser *)_parser immediatlyParseBodyOfMultipart:(id)_part data:(NSData *)_data; - (void)multipartBodyParser:(NGMimeMultipartBodyParser *)_parser foundPrefix:(NSData *)_prefix inMultipart:(id)_part; - (void)multipartBodyParser:(NGMimeMultipartBodyParser *)_parser foundSuffix:(NSData *)_suffix inMultipart:(id)_part; - (NGMimePartParser *)multipartBodyParser:(NGMimeMultipartBodyParser *)_parser parserForEntity:(NSData *)_data inMultipart:(id)_part; @end #endif /* __NGMime_NGMimeBodyParser_H__ */ SOPE/sope-mime/NGMime/NGMimeDecls.h0000644000000000000000000000227015004363604015573 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGMimeDecls_H__ #define __NGMime_NGMimeDecls_H__ #if BUILD_libNGMime_DLL # define NGMime_EXPORT __declspec(dllexport) # define NGMime_DECLARE __declspec(dllexport) #elif libNGMime_ISDLL # define NGMime_EXPORT extern __declspec(dllimport) # define NGMime_DECLARE extern __declspec(dllimport) #else # define NGMime_EXPORT extern # define NGMime_DECLARE #endif #endif /* __NGMime_NGMimeDecls_H__ */ SOPE/sope-mime/NGMime/NGMimeExceptions.m0000644000000000000000000000216015004363604016665 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeExceptions.h" #include "common.h" @implementation NGMimeException - (id)init { return [self initWithReason:@"a MIME exception occured"]; } @end /* NGMimeException */ @implementation NGMimeParserException - (id)init { return [self initWithReason:@"a MIME exception occured during parsing"]; } @end /* NGMimeParserException */ SOPE/sope-mime/NGMime/NGMimeHeaderFieldParserSet.m0000644000000000000000000001152315004363604020534 0ustar rootroot/* Copyright (C) 2000-2006 SKYRIX Software AG Copyright (C) 2006 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeHeaderFieldParser.h" #include "NGMimeHeaderFields.h" #include "NGMimeUtilities.h" #include "common.h" #include @implementation NGMimeHeaderFieldParserSet static NGMimeHeaderFieldParserSet *rfc822set = nil; + (id)headerFieldParserSet { return [[[self alloc] init] autorelease]; } + (id)defaultRfc822HeaderFieldParserSet { id parser = nil; static NGMimeHeaderNames *Fields = NULL; if (rfc822set) return rfc822set; if (Fields == NULL) Fields = (NGMimeHeaderNames *)[NGMimePartParser headerFieldNames]; rfc822set = [[self alloc] init]; [rfc822set setParser: (parser = [[NGMimeContentTypeHeaderFieldParser alloc] init]) forField:Fields->contentType]; [parser release]; parser = nil; [rfc822set setParser: (parser = [[NGMimeContentLengthHeaderFieldParser alloc] init]) forField:Fields->contentLength]; [parser release]; parser = nil; [rfc822set setParser: (parser = [[NGMimeStringHeaderFieldParser alloc] initWithRemoveComments:NO]) forField:Fields->received]; [parser release]; parser = nil; [rfc822set setParser: (parser = [[NGMimeStringHeaderFieldParser alloc] initWithRemoveComments:NO]) forField:Fields->subject]; [parser release]; parser = nil; [rfc822set setParser: (parser = [[NGMimeStringHeaderFieldParser alloc] initWithRemoveComments:NO]) forField:@"x-face"]; [parser release]; parser = nil; [rfc822set setParser: (parser = [[NGMimeContentDispositionHeaderFieldParser alloc] init]) forField:Fields->contentDisposition]; [parser release]; parser = nil; [rfc822set setParser: (parser = [[NGMimeRFC822DateHeaderFieldParser alloc] init]) forField:Fields->date]; [parser release]; parser = nil; return rfc822set; } - (id)init { return [self initWithDefaultParser: [[[NGMimeStringHeaderFieldParser alloc] init] autorelease]]; } - (id)initWithDefaultParser:(id)_parser { if ((self = [super init])) { self->fieldNameToParser = [[NSMutableDictionary alloc] initWithCapacity:32]; [self setDefaultParser:_parser]; } return self; } - (id)initWithParseSet:(NGMimeHeaderFieldParserSet *)_set { if ((self = [self initWithDefaultParser:[_set defaultParser]])) { [self->fieldNameToParser addEntriesFromDictionary:_set->fieldNameToParser]; } return self; } - (void)dealloc { [self->fieldNameToParser release]; [self->defaultParser release]; [super dealloc]; } /* accessors */ - (void)setParser:(id)_parser forField:(NSString *)_name { [self->fieldNameToParser setObject:_parser forKey:_name]; } - (void)setDefaultParser:(id)_parser { ASSIGN(self->defaultParser, _parser); } - (id)defaultParser { return self->defaultParser; } /* operation */ - (id)parseValue:(id)_data ofHeaderField:(NSString *)_field { id parser; parser = [self->fieldNameToParser objectForKey:_field]; if (parser == nil) parser = [self defaultParser]; return [parser parseValue:_data ofHeaderField:_field]; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { id copy; NSEnumerator *keys; NSString *key; copy = [[NGMimeHeaderFieldParserSet allocWithZone:_zone] initWithDefaultParser: [self defaultParser]]; keys = [self->fieldNameToParser keyEnumerator]; while ((key = [keys nextObject]) != nil) { id value; value = [self->fieldNameToParser objectForKey:key]; [copy setParser:value forField:key]; } return copy; } /* description */ - (NSString *)description { return [NSString stringWithFormat: @"", self, self->fieldNameToParser, [self defaultParser]]; } @end /* NGMimeHeaderFieldParserSet */ SOPE/sope-mime/NGMime/NGMimeStringHeaderFieldGenerator.m0000644000000000000000000000244615004363604021745 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeHeaderFieldGenerator.h" #include "NGMimeHeaderFields.h" #include "common.h" @implementation NGMimeStringHeaderFieldGenerator - (NSData *)generateDataForHeaderFieldNamed:(NSString *)_headerField value:(id)_value { if (_value == nil) return [NSData data]; if ([_value isKindOfClass:[NSData class]]) return _value; if (![_value isKindOfClass:[NSString class]]) _value = [_value stringValue]; return [_value dataUsingEncoding:NSUTF8StringEncoding]; } @end /* NGMimeStringHeaderFieldGenerator */ SOPE/sope-mime/NGMime/NGMime.m0000644000000000000000000000304615004363604014627 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMime.h" #ifndef LIBRARY_MAJOR_VERSION # if !COCOA_Foundation_LIBRARY && !NeXT_Foundation_LIBRARY # warning library version not passed in as a default (using 4.5.0) # endif # define LIBRARY_MAJOR_VERSION 4 #endif #ifndef LIBRARY_MINOR_VERSION # define LIBRARY_MINOR_VERSION 5 #endif #ifndef LIBRARY_SUBMINOR_VERSION # define LIBRARY_SUBMINOR_VERSION 0 #endif @implementation NGMime + (NSString *)libraryVersion { static NSString *Version = nil; if (Version == nil) { Version = [[NSString alloc] initWithFormat:@"NGMime_%d.%d.%d", LIBRARY_MAJOR_VERSION, LIBRARY_MINOR_VERSION, LIBRARY_SUBMINOR_VERSION]; } return Version; } - (void)_staticLinkClasses { } - (void)_staticLinkModules { } @end /* NGMime */ SOPE/sope-mime/NGMime/COPYRIGHT0000644000000000000000000000010615004363604014622 0ustar rootrootCopyright (C) 2000-2005 SKYRIX Software AG Contact: info@skyrix.com SOPE/sope-mime/NGMime/NGMimeMultipartBodyGenerator.m0000644000000000000000000002446315004363604021224 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeBodyGenerator.h" #include "NGMimePartGenerator.h" #include "NGMimeMultipartBody.h" #include "NGMimeJoinedData.h" #include "NGMimeFileData.h" #include "common.h" #include #include @implementation NGMimeMultipartBodyGenerator static Class NGMimeFileDataClass = Nil; static Class NGMimeJoinedDataClass = Nil; static BOOL debugOn = NO; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; NGMimeFileDataClass = [NGMimeFileData class]; NGMimeJoinedDataClass = [NGMimeJoinedData class]; debugOn = [ud boolForKey:@"NGMimeGeneratorDebugEnabled"]; if (debugOn) NSLog(@"WARNING[%@]: NGMimeGeneratorDebugEnabled is enabled!", self); } + (NSString *)boundaryPrefix { static NSString *BoundaryPrefix = nil; if (BoundaryPrefix == nil) { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; BoundaryPrefix = [[ud stringForKey:@"NGMime_MultipartBoundaryPrefix"] copy]; if (BoundaryPrefix == nil) BoundaryPrefix = @"--=_=-_OpenGroupware_org_NGMime"; } return BoundaryPrefix; } static inline BOOL _isBoundaryInArray(NGMimeMultipartBodyGenerator *self, NSString *_boundary, NSArray *_data) { const unsigned char *boundary; unsigned int length; NSEnumerator *enumerator; NSData *data; BOOL wasFound; // TODO: do we need to treat the boundary as a CString? boundary = (const unsigned char *)[_boundary cString]; length = [_boundary length]; enumerator = [_data objectEnumerator]; data = nil; wasFound = NO; while ((data = [enumerator nextObject]) != nil) { const unsigned char *bytes; unsigned int dataLen; unsigned cnt; if ([data isKindOfClass:NGMimeFileDataClass] || [data isKindOfClass:NGMimeJoinedDataClass]) continue; bytes = [data bytes]; dataLen = [data length]; cnt = 0; if (dataLen < length) return NO; while ((cnt < dataLen) && ((dataLen - cnt) >= length)) { if (bytes[cnt + 2] != '-') { // can`t be a boundary cnt++; continue; } if (bytes[cnt] == '\n') {// LF*- if (bytes[cnt + 1] == '-') { // LF-- if (strncmp((char *)boundary, (char *)(bytes+cnt+3), length) == 0) { wasFound = YES; break; } } } else if (bytes[cnt] == '\r') { //CR*- if (bytes[cnt + 1] == '-') { //CR-- if (strncmp((char *)boundary, (char *)(bytes+cnt+3), length) == 0) { wasFound = YES; break; } } else if ((bytes[cnt + 1] == '\n') && (bytes[cnt + 3] == '-')) { if (strncmp((char*)boundary, (char *)(bytes+cnt+4), length)==0) { // CRLF-- wasFound = YES; break; } } } cnt++; } } return wasFound; } - (NSString *)buildBoundaryForPart:(id)_part data:(NSArray *)_data additionalHeaders:(NGMutableHashMap *)_addHeaders { static int BoundaryUniqueCount = 0; NSString *boundary = nil; BOOL isUnique = NO; unsigned pid; if ((boundary = [[_part contentType] valueOfParameter:@"boundary"])) return boundary; #if defined(__WIN32__) pid = GetCurrentProcessId(); #else pid = getpid(); #endif boundary = [NSString stringWithFormat: @"--%@-%d-%f-%d------", [NGMimeMultipartBodyGenerator boundaryPrefix], pid, [[NSDate date] timeIntervalSince1970], BoundaryUniqueCount++]; while (!isUnique) { isUnique = _isBoundaryInArray(self, boundary, _data) ? NO : YES; if (!isUnique) { boundary = [NSString stringWithFormat: @"--%@-%d-%f-%d-----", [NGMimeMultipartBodyGenerator boundaryPrefix], pid, [[NSDate date] timeIntervalSince1970], BoundaryUniqueCount++]; } } { // setting content-type with boundary NGMimeType *type = nil; type = [_part contentType]; if (type == nil) { NSDictionary *d; d = [[NSDictionary alloc] initWithObjectsAndKeys: boundary, @"boundary", nil]; type = [NGMimeType mimeType:@"multipart" subType:@"mixed" parameters:d]; [d release]; } else { NSMutableDictionary *dict = nil; dict = [NSMutableDictionary dictionaryWithDictionary: [type parametersAsDictionary]]; [dict setObject:boundary forKey:@"boundary"]; type = [NGMimeType mimeType:[type type] subType:[type subType] parameters:dict]; } [_addHeaders setObject:type forKey:@"content-type"]; } return boundary; } - (NSData *)buildDataWithBoundary:(NSString *)_boundary partsData:(NSArray *)_parts { NSEnumerator *enumerator; NSData *part; NSMutableData *data; data = (self->useMimeData) ? [[[NGMimeJoinedData alloc] init] autorelease] : [NSMutableData dataWithCapacity:4096]; enumerator = [_parts objectEnumerator]; while ((part = [enumerator nextObject])) { [data appendBytes:"--" length:2]; [data appendBytes:[_boundary cString] length:[_boundary length]]; [data appendBytes:"\r\n" length:2]; [data appendData:part]; [data appendBytes:"\r\n" length:2]; } [data appendBytes:"--" length:2]; [data appendBytes:[_boundary cString] length:[_boundary length]]; [data appendBytes:"--" length:2]; return data; } - (NSData *)generateBodyOfPart:(id)_part additionalHeaders:(NGMutableHashMap *)_addHeaders delegate:(id)_delegate { // TODO: split up NGMimeMultipartBody *body = nil; NSMutableData *data = nil; id tmp = nil; NSArray *parts = nil; id part = nil; NSEnumerator *enumerator = nil; NSString *boundary = nil; NSMutableArray *partsData = nil; NSAutoreleasePool *pool; body = [_part body]; if (body == nil) return [NSData data]; pool = [[NSAutoreleasePool alloc] init]; NSAssert1([body isKindOfClass:[NGMimeMultipartBody class]], @"NGMimeMultipartBodyGenerator expect a NGMimeMultipartBody " @"as body of part\n part: %@\n", _part); data = (self->useMimeData) ? [[[NGMimeJoinedData alloc] init] autorelease] : [NSMutableData dataWithCapacity:4096]; if ([_delegate respondsToSelector: @selector(multipartBodyGenerator:prefixForPart:)]) tmp = [_delegate multipartBodyGenerator:self prefixForPart:_part]; else tmp = [self multipartBodyGenerator:self prefixForPart:_part mimeMultipart:body]; if (tmp != nil) { NSAssert([tmp isKindOfClass:[NSString class]], @"prefix should be a NSString"); [data appendBytes:[tmp cString] length:[tmp length]]; } parts = [body parts]; enumerator = [parts objectEnumerator]; partsData = [[NSMutableArray alloc] initWithCapacity:4]; while ((part = [enumerator nextObject]) != nil) { id gen = nil; NSData *data; if ([_delegate respondsToSelector: @selector(multipartBodyGenerator:generatorForPart:)]) { gen = [_delegate multipartBodyGenerator:self generatorForPart:part]; } else { gen = [self multipartBodyGenerator:self generatorForPart:part]; [gen setDelegate:_delegate]; [(id)gen setUseMimeData:self->useMimeData]; } if (gen == nil) { [self logWithFormat:@"WARNING(%s): got no generator", __PRETTY_FUNCTION__]; continue; } /* generate part */ data = [gen generateMimeFromPart:part]; if (data != nil) { if (debugOn) { [self debugWithFormat: @"multipart body generated %d bytes using %@ for part: %@", [data length], gen, part]; } [partsData addObject:data]; } else if (debugOn) { [self debugWithFormat: @"multipart body %@ did not generate content for part: %@", gen, part]; } } boundary = [self buildBoundaryForPart:_part data:partsData additionalHeaders:_addHeaders]; tmp = [self buildDataWithBoundary:boundary partsData:partsData]; if (tmp != nil) { [data appendData:tmp]; } else { NSLog(@"WARNING(%s): couldn`t build multipart data", __PRETTY_FUNCTION__); } if ([_delegate respondsToSelector: @selector(multipartBodyGenerator:suffixForPart:)]) tmp = [_delegate multipartBodyGenerator:self suffixForPart:_part]; else tmp = [self multipartBodyGenerator:self suffixForPart:_part mimeMultipart:body]; if (tmp != nil) { NSAssert([tmp isKindOfClass:[NSString class]], @"suffix should be a NSString"); [data appendBytes:[tmp cString] length:[tmp length]]; } [partsData release]; partsData = nil; [data retain]; [pool release]; return [data autorelease]; } - (NSString *)multipartBodyGenerator:(NGMimeMultipartBodyGenerator *)_gen prefixForPart:(id)_part mimeMultipart:(NGMimeMultipartBody *)_body { return @""; // [_body prefix]; } - (NSString *)multipartBodyGenerator:(NGMimeMultipartBodyGenerator *)_gen suffixForPart:(id)_part mimeMultipart:(NGMimeMultipartBody *)_body { return @""; //[_body suffix]; } - (id)multipartBodyGenerator:(NGMimeBodyGenerator *)_gen generatorForPart:(id)_part { id gen; gen = [[NGMimePartGenerator alloc] init]; [gen setUseMimeData:self->useMimeData]; return [gen autorelease]; } /* debugging */ - (BOOL)isDebuggingEnabled { return debugOn; } @end /* NGMimeMultipartBodyGenerator */ SOPE/sope-mime/NGMime/NGMimeContentTypeHeaderFieldParser.m0000644000000000000000000000440415004363604022255 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeHeaderFieldParser.h" #include "NGMimeHeaderFields.h" #include "NGMimeUtilities.h" #include "common.h" @implementation NGMimeContentTypeHeaderFieldParser static BOOL StripLeadingSpaces = NO; static BOOL MimeLogEnabled = NO; + (void)initialize { StripLeadingSpaces = [self doesStripLeadingSpaces]; MimeLogEnabled = [self isMIMELogEnabled]; } - (id)parseValue:(id)_data ofHeaderField:(NSString *)_field { NSString *typeString; unsigned len; _data = [self removeCommentsFromValue:_data]; len = [_data length]; if (len == 0) { if (MimeLogEnabled) { [self logWithFormat:@"WARNING(%s): empty value for header field %@ ..", __PRETTY_FUNCTION__, _field]; } return [NGMimeType mimeType:@"text/plain"]; } typeString = nil; if (StripLeadingSpaces) { unichar src[len + 1]; int cnt; cnt = 0; [_data getCharacters:src]; while (isRfc822_LWSP(src[cnt]) && (len > 0)) { cnt++; len--; } if (cnt > 0) typeString = [[[NSString alloc] initWithCharacters:src+cnt length:len] autorelease]; } if (!typeString) typeString = _data; NSAssert(typeString, @"type string allocation failed .."); return [NGMimeType mimeType:typeString]; } /* description */ - (NSString *)description { return [NSString stringWithFormat: @"", self]; } @end /* NGMimeContentTypeHeaderFieldParser */ SOPE/sope-mime/NGMime/NGMimeUtilities.h0000644000000000000000000001316615004363604016522 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGMimeUtilities_H__ #define __NGMime_NGMimeUtilities_H__ #import #import #include // ******************** RFC 822 ******************** static inline BOOL isRfc822_SpecialByte(unsigned char _byte) { switch (_byte) { case '(': case ')': case '<': case '>': case '@': case ',': case ';': case ':': case '"': case '\\': case '.': case '[': case ']': return YES; default: return NO; } } // single chars NSDictionary *parseParameters(id self, NSString *_str, unichar *cstr); static inline BOOL isRfc822_CR(unichar _byte) { return (_byte == 13); } static inline BOOL isRfc822_LF(unichar _byte) { return (_byte == 10); } static inline BOOL isRfc822_HTAB(unichar _byte) { return (_byte == 9); } static inline BOOL isRfc822_SPACE(unichar _byte) { return (_byte == 32); } static inline BOOL isRfc822_QUOTE(unichar _byte) { return (_byte == 34); } // ranges static inline BOOL isRfc822_CHAR(unichar _byte) { return (_byte < 128); } static inline BOOL isRfc822_CTL(unichar _byte) { return (_byte < 32) || (_byte == 127); } static inline BOOL isRfc822_ALPHA(unichar _byte) { return (((_byte >= 65) && (_byte <= 90)) || ((_byte >= 97) && (_byte <= 122))); } static inline BOOL isRfc822_DIGIT(unichar _byte) { return (_byte >= 48) && (_byte <= 57); } static inline BOOL isRfc822_LWSP(unichar _byte) { return (isRfc822_SPACE(_byte) || isRfc822_HTAB(_byte)); } static inline BOOL isRfc822_FieldNameChar(unichar _byte) { return (isRfc822_CHAR(_byte) && !(isRfc822_CTL(_byte) || isRfc822_SPACE(_byte) || (_byte == ':'))); } static inline BOOL isRfc822_AtomChar(unichar _byte) { return (isRfc822_CHAR(_byte) && !(isRfc822_SpecialByte(_byte) || isRfc822_SPACE(_byte) || isRfc822_CTL(_byte))); } // ******************** MIME *********************** static inline BOOL isMime_SpecialByte(unichar _byte) { switch (_byte) { case '(': case ')': case '<': case '>': case '@': case ',': case ';': case ':': case '"': case '\\': case '/': case '=': case '[': case ']': case '?': return YES; default: return NO; } } static inline BOOL isMime_TokenChar(unichar _byte) { return (isRfc822_CHAR(_byte) && !(isRfc822_CTL(_byte) || isRfc822_SPACE(_byte) || isMime_SpecialByte(_byte))); } static inline BOOL isMime_SafeChar(unichar _byte) { return ((_byte >= 33 && _byte <= 60) || (_byte >= 62 && _byte <= 126)); } static inline BOOL isMime_ValidTypeXTokenChar(unichar _byte) { return !isRfc822_SPACE(_byte); } static inline BOOL isMime_ValidTypeAttributeChar(unichar _byte) { return isMime_TokenChar(_byte); } static inline NSData *_quotedPrintableEncoding(NSData *_data) { const char *bytes; unsigned int length; NSData *result = nil; char *des = NULL; unsigned int desLen = 0; unsigned cnt; const char *test; BOOL doEnc = NO; bytes = [_data bytes]; length = [_data length]; cnt = length; test = bytes; for (cnt = length, test = bytes; cnt > 0; test++, cnt--) { if ((unsigned char)*test > 127) { doEnc = YES; break; } } if (!doEnc) return _data; desLen = length *3; des = NGMallocAtomic(sizeof(char) * desLen + 2); desLen = NGEncodeQuotedPrintable(bytes, length, des, desLen); if ((int)desLen != -1) { result = [NSData dataWithBytesNoCopy:des length:desLen]; } else { NSLog(@"WARNING(%s): An error occour during quoted-printable decoding", __PRETTY_FUNCTION__); if (des) NGFree(des); result = _data; } return result; } static inline NSData *_rfc2047Decoding(char _enc, const char *_bytes, NSUInteger _length) { NSData *data = nil; if ((_enc == 'b') || (_enc == 'B')) { // use BASE64 decoding // TODO: improve efficiency (directly decode buffers w/o NSData) NSData *tmp; tmp = [[NSData alloc] initWithBytes:_bytes length:_length]; data = [tmp dataByDecodingBase64]; [tmp release]; tmp = nil; } else if ((_enc == 'q') || (_enc == 'Q')) { // use quoted-printable decoding char *dest = NULL; size_t destSize = 0; size_t resSize = 0; destSize = _length; dest = calloc(destSize + 2, sizeof(char)); resSize = NGDecodeQuotedPrintable(_bytes, _length, dest, destSize); if ((int)resSize != -1) { data = [NSData dataWithBytesNoCopy:dest length:resSize]; } else { NSLog(@"WARNING(%s): An error occour during quoted-printable decoding", __PRETTY_FUNCTION__); if (dest != NULL) free(dest); dest = NULL; data = [NSData dataWithBytes:_bytes length:_length]; } } else { NSLog(@"WARNING(%s): unknown encoding type %c", __PRETTY_FUNCTION__, _enc); data = [NSData dataWithBytes:_bytes length:_length]; } return data; } #endif /* __NGMime_NGMimeUtilities_H__ */ SOPE/sope-mime/NGMime/NGMimeType.m0000644000000000000000000005120115004363604015465 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeType.h" #include "NGConcreteMimeType.h" #include "NGMimeUtilities.h" #include "common.h" #include NGMime_DECLARE NSString *NGMimeTypeText = @"text"; NGMime_DECLARE NSString *NGMimeTypeAudio = @"audio"; NGMime_DECLARE NSString *NGMimeTypeVideo = @"video"; NGMime_DECLARE NSString *NGMimeTypeImage = @"image"; NGMime_DECLARE NSString *NGMimeTypeApplication = @"application"; NGMime_DECLARE NSString *NGMimeTypeMultipart = @"multipart"; NGMime_DECLARE NSString *NGMimeTypeMessage = @"message"; NGMime_DECLARE NSString *NGMimeParameterTextCharset = @"charset"; static BOOL _parseMimeType(id self, NSString *_str, NSString **type, NSString **subType, NSDictionary **parameters); @implementation NGMimeType static NSMutableDictionary *typeToClass = nil; static inline Class classForType(NSString *_type, NSString *_subType, NSDictionary *_parameters) { Class c = Nil; if (_type == nil) return Nil; if ([_type isEqualToString:@"*"] || [_subType isEqualToString:@"*"]) return [NGConcreteWildcardType class]; if ([_type isEqualToString:NGMimeTypeApplication]) { if ([_subType isEqualToString:@"octet"]) return [NGConcreteAppOctetMimeType class]; } if ([_type isEqualToString:NGMimeTypeText]) { if ([_subType isEqualToString:@"x-vcard"] || [_subType isEqualToString:@"vcard"]) return [NGConcreteTextVcardMimeType class]; } c = [typeToClass objectForKey:_type]; return c ? c : [NGConcreteGenericMimeType class]; } static Class NSStringClass = Nil; + (void)initialize { static BOOL isInitialized = NO; if (!isInitialized) { isInitialized = YES; typeToClass = [[NSMutableDictionary alloc] initWithCapacity:10]; [typeToClass setObject:[NGConcreteTextMimeType class] forKey:NGMimeTypeText]; [typeToClass setObject:[NGConcreteVideoMimeType class] forKey:NGMimeTypeVideo]; [typeToClass setObject:[NGConcreteAudioMimeType class] forKey:NGMimeTypeAudio]; [typeToClass setObject:[NGConcreteImageMimeType class] forKey:NGMimeTypeImage]; [typeToClass setObject:[NGConcreteApplicationMimeType class] forKey:NGMimeTypeApplication]; [typeToClass setObject:[NGConcreteMultipartMimeType class] forKey:NGMimeTypeMultipart]; [typeToClass setObject:[NGConcreteMessageMimeType class] forKey:NGMimeTypeMessage]; } } + (NSStringEncoding)stringEncodingForCharset:(NSString *)_s { NSString *charset; NSStringEncoding encoding; charset = [_s lowercaseString]; if ([charset length] == 0) encoding = [NSString defaultCStringEncoding]; /* UTF-, ASCII */ else if ([charset isEqualToString:@"us-ascii"]) encoding = NSASCIIStringEncoding; else if ([charset isEqualToString:@"ascii"]) encoding = NSASCIIStringEncoding; else if ([charset isEqualToString:@"utf8"]) encoding = NSUTF8StringEncoding; else if ([charset isEqualToString:@"utf-8"]) encoding = NSUTF8StringEncoding; else if ([charset isEqualToString:@"utf-16"]) encoding = NSUnicodeStringEncoding; /* ISO Latin 1 */ else if ([charset isEqualToString:@"iso-latin-1"]) encoding = NSISOLatin1StringEncoding; else if ([charset isEqualToString:@"iso-8859-1"]) encoding = NSISOLatin1StringEncoding; else if ([charset isEqualToString:@"8859-1"]) encoding = NSISOLatin1StringEncoding; /* some unsupported, but known encoding */ else if ([charset isEqualToString:@"ks_c_5601-1987"]) { encoding = NSISOLatin1StringEncoding; } else if ([charset isEqualToString:@"euc-kr"]) { encoding = NSKoreanEUCStringEncoding; } else if ([charset isEqualToString:@"big5"]) { #define C_GNUSTEP_VERSION (GNUSTEP_BASE_MAJOR_VERSION * 1000000) + (GNUSTEP_BASE_MINOR_VERSION * 1000) + GNUSTEP_BASE_SUBMINOR_VERSION #if C_GNUSTEP_VERSION >= 1029000 encoding = NSBig5StringEncoding; #else encoding = NSBIG5StringEncoding; #endif } else if ([charset isEqualToString:@"iso-2022-jp"]) { encoding = NSISO2022JPStringEncoding; } else if ([charset isEqualToString:@"gb2312"]) { #if C_GNUSTEP_VERSION >= 1029000 encoding = NSHZ_GB_2312StringEncoding; #else encoding = NSGB2312StringEncoding; #endif } else if ([charset isEqualToString:@"koi8-r"]) { encoding = NSKOI8RStringEncoding; } else if ([charset isEqualToString:@"windows-1250"]) { encoding = NSWindowsCP1250StringEncoding; } else if ([charset isEqualToString:@"windows-1251"]) { encoding = NSWindowsCP1251StringEncoding; } else if ([charset isEqualToString:@"windows-1252"]) { encoding = NSWindowsCP1252StringEncoding; } else if ([charset isEqualToString:@"iso-8859-2"]) { encoding = NSISOLatin2StringEncoding; } else if ([charset isEqualToString:@"iso-8859-8-i"]) { encoding = NSISOHebrewStringEncoding; } else if ([charset isEqualToString:@"iso-8859-7"]) { encoding = NSISOGreekStringEncoding; } else if ([charset isEqualToString:@"iso-8859-6"]) { encoding = NSISOArabicStringEncoding; } else if ([charset isEqualToString:@"iso-8859-4"]) { // latin 4 is for baltic languages encoding = NSISOLatin4StringEncoding; } else if ([charset isEqualToString:@"iso-8859-9"]) { // latin 5 is for turkish languages encoding = NSISOLatin5StringEncoding; } else if ([charset isEqualToString:@"iso-8859-5"]) { encoding = NSISOCyrillicStringEncoding; } else if ([charset isEqualToString:@"x-unknown"] || [charset isEqualToString:@"unknown"]) { encoding = NSISOLatin1StringEncoding; } /* ISO Latin 9 */ #if !(NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY) else if ([charset isEqualToString:@"iso-latin-9"]) encoding = NSISOLatin9StringEncoding; else if ([charset isEqualToString:@"iso-8859-15"]) encoding = NSISOLatin9StringEncoding; else if ([charset isEqualToString:@"8859-15"]) encoding = NSISOLatin9StringEncoding; #endif else { [self logWithFormat:@"%s: unknown charset '%@'", __PRETTY_FUNCTION__, _s]; encoding = NSISOLatin1StringEncoding; } return encoding; } // init - (id)initWithType:(NSString *)_type subType:(NSString *)_subType parameters:(NSDictionary *)_parameters { Class c; c = classForType(_type, _subType, _parameters); [self release]; return [[c alloc] initWithType:_type subType:_subType parameters:_parameters]; } + (id)mimeType:(NSString *)_type subType:(NSString *)_subType { Class c; c = classForType(_type, _subType, nil); NSAssert(c, @"did not find class for mimetype .."); return [[[c alloc] initWithType:_type subType:_subType parameters:nil] autorelease]; } + (id)mimeType:(NSString *)_type subType:(NSString *)_subType parameters:(NSDictionary *)_parameters { Class c; c = classForType(_type, _subType, _parameters); NSAssert(c, @"did not find class for mimetype .."); return [[[c alloc] initWithType:_type subType:_subType parameters:_parameters] autorelease]; } + (id)mimeType:(NSString *)_stringValue { NSString *type, *subType; NSDictionary *parameters; if ([_stringValue length] == 0) /* empty ... */ return nil; parameters = nil; type = nil; subType = nil; if (_parseMimeType(self, _stringValue, &type, &subType, ¶meters)) { Class c; id result; c = classForType(type, subType, nil); NSAssert(c, @"did not find class for mimetype .."); NSAssert(type, @"didn't parse type .."); NSAssert(subType, @"didn't parse subtype .."); result = [c alloc]; NSAssert(result, @"allocation of mimetype failed .."); result = [result initWithType:type subType:subType parameters:parameters]; NSAssert(result, @"initialization of mimetype failed .."); result = [result autorelease]; NSAssert(result, @"autorelease of mimetype failed .."); return result; } else { [self logWithFormat:@"ERROR[%s]: parsing of mimetype '%@' failed !", __PRETTY_FUNCTION__, _stringValue]; return nil; // parsing failed } } /* types */ - (NSString *)type { [self subclassResponsibility:_cmd]; return nil; } - (NSString *)subType { [self subclassResponsibility:_cmd]; return nil; } - (BOOL)isCompositeType { [self subclassResponsibility:_cmd]; return NO; } /* comparing types */ - (BOOL)isEqual:(id)_other { if (_other == nil) return NO; if (_other == self) return YES; return ([_other isKindOfClass:[NGMimeType class]]) ? [self isEqualToMimeType:_other] : NO; } - (BOOL)isEqualToMimeType:(NGMimeType *)_type { if (_type == nil) return NO; if (_type == self) return YES; if (![self hasSameType:_type]) return NO; if (![[_type parametersAsDictionary] isEqual:[self parametersAsDictionary]]) return NO; return YES; } - (BOOL)hasSameGeneralType:(NGMimeType *)_other { // only the 'type' must match if (_other == self) return YES; if ([_other isCompositeType] != [self isCompositeType]) return NO; if (![[_other type] isEqualToString:[self type]]) return NO; return YES; } - (BOOL)hasSameType:(NGMimeType *)_other { // parameters need not match if (_other == nil) return NO; if (_other == self) return YES; if ([_other isCompositeType] != [self isCompositeType]) return NO; if (![[_other type] isEqualToString:[self type]]) return NO; if (![[_other subType] isEqualToString:[self subType]]) return NO; return YES; } - (BOOL)doesMatchType:(NGMimeType *)_other { // interpretes wildcards NSString *t, *st, *ot, *ost; t = [self type]; st = [self subType]; ot = [_other type]; ost = [_other subType]; if ([t isEqualToString:@"*"] || [ot isEqualToString:@"*"]) { t = @"*"; ot = @"*"; } if (![t isEqualToString:ot]) return NO; if ([st isEqualToString:@"*"] || [ost isEqualToString:@"*"]) { ot = @"*"; ost = @"*"; } if (![st isEqualToString:ost]) return NO; return YES; } /* parameters */ - (NSEnumerator *)parameterNames { [self doesNotRecognizeSelector:_cmd]; // subclass return nil; } - (id)valueOfParameter:(NSString *)_parameterName { [self doesNotRecognizeSelector:_cmd]; // subclass return nil; } /* representations */ - (NSDictionary *)parametersAsDictionary { NSMutableDictionary *parameters; NSString *name; NSDictionary *d; NSEnumerator *names; if ((names = [self parameterNames]) == nil) return nil; parameters = [[NSMutableDictionary alloc] init]; while ((name = [names nextObject])) [parameters setObject:[self valueOfParameter:name] forKey:name]; d = [parameters copy]; [parameters release]; return [d autorelease]; } - (NSString *)parametersAsString { NSEnumerator *names; NSMutableString *result; NSString *name; if ((names = [self parameterNames]) == nil) return nil; result = [NSMutableString stringWithCapacity:64]; while ((name = [names nextObject])) { NSString *value; value = [[self valueOfParameter:name] stringValue]; [result appendString:@"; "]; [result appendString:name]; [result appendString:@"="]; if ([self valueNeedsQuotes:value]) { [result appendString:@"\""]; [result appendString:value]; [result appendString:@"\""]; } else [result appendString:value]; } return result; } - (BOOL)valueNeedsQuotes:(NSString *)_parameterValue { NSData *stringData; const char *cstr; unsigned int count, max; BOOL needsQuote; needsQuote = NO; stringData = [_parameterValue dataUsingEncoding:NSUTF8StringEncoding]; cstr = [stringData bytes]; max = [stringData length]; count = 0; while (!needsQuote && count < max) { if (isMime_SpecialByte(*(cstr + count)) || *(cstr + count) == 32) needsQuote = YES; else count++; } return needsQuote; } - (NSString *)stringValue { [self subclassResponsibility:_cmd]; return nil; } // NSCoding - (Class)classForCoder { return [NGMimeType class]; } - (void)encodeWithCoder:(NSCoder *)_encoder { [_encoder encodeObject:[self type]]; [_encoder encodeObject:[self subType]]; [_encoder encodeObject:[self parametersAsDictionary]]; } - (id)initWithCoder:(NSCoder *)_decoder { NSString *type, *subType; NSDictionary *paras; type = [_decoder decodeObject]; subType = [_decoder decodeObject]; paras = [_decoder decodeObject]; return [self initWithType:type subType:subType parameters:paras]; } // NSCopying - (id)copyWithZone:(NSZone *)_zone { return [[NGMimeType allocWithZone:_zone] initWithType:[self type] subType:[self subType] parameters:[self parametersAsDictionary]]; } // description - (NSString *)description { return [NSString stringWithFormat:@"", [self stringValue]]; } @end /* NGMimeType */ typedef struct { NSString *image; NSString *video; NSString *audio; NSString *text; NSString *star; NSString *application; NSString *multipart; NSString *message; } NGMimeTypeConstants; typedef struct { NSString *plain; NSString *star; NSString *mixed; NSString *jpeg; NSString *png; NSString *gif; NSString *xml; NSString *html; NSString *css; NSString *xMng; NSString *xhtmlXml; NSString *rfc822; NSString *octetStream; } NGMimeSubTypeConstants; static NGMimeTypeConstants *MimeTypeConstants = NULL; static NGMimeSubTypeConstants *MimeSubTypeConstants = NULL; static NSString *_stringForType(char *_type, int _len) { if (NSStringClass == Nil) NSStringClass = [NSString class]; if (MimeTypeConstants == NULL) { MimeTypeConstants = malloc(sizeof(NGMimeTypeConstants)); MimeTypeConstants->image = NGMimeTypeImage; MimeTypeConstants->video = NGMimeTypeVideo; MimeTypeConstants->audio = NGMimeTypeAudio; MimeTypeConstants->text = NGMimeTypeText; MimeTypeConstants->star = @"*"; MimeTypeConstants->application = NGMimeTypeApplication; MimeTypeConstants->multipart = NGMimeTypeMultipart; MimeTypeConstants->message = NGMimeTypeMessage; } switch (_len) { case 0: return @""; case 1: if (_type[0] == '*') return MimeTypeConstants->star; break; case 4: if (strncmp(_type, "text", 4) == 0) return MimeTypeConstants->text; break; case 5: if (_type[0] == 'i') { if (strncmp(_type, "image", 5) == 0) return MimeTypeConstants->image; } else if (_type[0] == 'v') { if (strncmp(_type, "video", 5) == 0) return MimeTypeConstants->video; } else if (_type[0] == 'a') { if (strncmp(_type, "audio", 5) == 0) return MimeTypeConstants->audio; } break; case 7: if (strncmp(_type, "message", 7) == 0) return MimeTypeConstants->message; break; case 9: if (strncmp(_type, "multipart", 9) == 0) return MimeTypeConstants->multipart; break; case 11: if (strncmp(_type, "application", 11) == 0) return MimeTypeConstants->application; break; } return [NSStringClass stringWithCString:_type length:_len]; } static NSString *_stringForSubType(char *_type, int _len) { if (NSStringClass == Nil) NSStringClass = [NSString class]; if (MimeSubTypeConstants == NULL) { MimeSubTypeConstants = malloc(sizeof(NGMimeSubTypeConstants)); MimeSubTypeConstants->plain = @"plain"; MimeSubTypeConstants->star = @"*"; MimeSubTypeConstants->mixed = @"mixed"; MimeSubTypeConstants->jpeg = @"jpeg"; MimeSubTypeConstants->png = @"png"; MimeSubTypeConstants->gif = @"gif"; MimeSubTypeConstants->xml = @"xml"; MimeSubTypeConstants->html = @"html"; MimeSubTypeConstants->css = @"css"; MimeSubTypeConstants->xMng = @"xMng"; MimeSubTypeConstants->xhtmlXml = @"xhtmlXml"; MimeSubTypeConstants->rfc822 = @"rfc822"; MimeSubTypeConstants->octetStream = @"octet-stream"; } switch (_len) { case 0: return @""; case 1: if (_type[0] == '*') return MimeSubTypeConstants->star; break; case 3: if (_type[0] == 'p') { if (strncmp(_type, "png", 3) == 0) return MimeSubTypeConstants->png; } else if (_type[0] == 'g') { if (strncmp(_type, "gif", 3) == 0) return MimeSubTypeConstants->gif; } else if (_type[0] == 'c') { if (strncmp(_type, "css", 3) == 0) return MimeSubTypeConstants->css; } else if (_type[0] == 'x') { if (strncmp(_type, "xml", 3) == 0) return MimeSubTypeConstants->xml; } break; case 4: if (_type[0] == 'h') { if (strncmp(_type, "html", 4) == 0) return MimeSubTypeConstants->html; } else if (_type[0] == 'j') { if (strncmp(_type, "jpeg", 4) == 0) return MimeSubTypeConstants->jpeg; } break; case 5: if (_type[0] == 'p') { if (strncmp(_type, "plain", 5) == 0) return MimeSubTypeConstants->plain; } else if (_type[0] == 'm') { if (strncmp(_type, "mixed", 5) == 0) return MimeSubTypeConstants->mixed; } else if (_type[0] == 'x') { if (strncmp(_type, "x-mng", 5) == 0) return MimeSubTypeConstants->xMng; } break; case 6: if (strncmp(_type, "rfc822", 6) == 0) return MimeSubTypeConstants->rfc822; break; case 9: if (strncmp(_type, "xhtml+xml", 9) == 0) return MimeSubTypeConstants->xhtmlXml; break; case 12: if (strncmp(_type, "octet-stream", 12) == 0) return MimeSubTypeConstants->octetStream; break; } return [NSStringClass stringWithCString:_type length:_len]; } static void _fixMimeType(NSString **type, NSString **subType) { if ([*type isEqualToString: @"multipart"] && [*subType isEqualToString: @"x-zip"]) { *type = MimeTypeConstants->application; *subType = [NSString stringWithString: @"zip"]; } } static BOOL _parseMimeType(id self, NSString *_str, NSString **type, NSString **subType, NSDictionary **parameters) { unsigned len; unichar *cstr, *tmp; unsigned slen = [_str length]; unichar buf[slen + 1]; len = 0; cstr = &(buf[0]); [_str getCharacters:buf]; buf[slen] = '\0'; /* skip leading spaces */ while (isRfc822_LWSP(*cstr) && (*cstr != '\0')) cstr++; /* type name */ tmp = cstr; // keep beginning of type name len = 0; while ((*cstr != '/') && (*cstr != '\0') && (*cstr != ';')) { cstr++; len++; } if (len == 0) return NO; // no type was read { unsigned char buf[len + 3]; register unsigned i; buf[len] = '\0'; for (i = 0; i < len; i++) buf[i] = tolower(tmp[i]); *type = _stringForType((char *)buf, len); } if (*cstr == '/') { // subtype name cstr++; // skip '/' tmp = cstr; // keep beginning of subtype name len = 0; while ((*cstr != ';') && (!isRfc822_LWSP(*cstr)) && (*cstr != '\0')) { cstr++; len++; } if (len <= 0) { *subType = @"*"; return YES; // no subtype was read } else { unsigned char buf[len + 1]; register unsigned i; buf[len] = '\0'; for (i = 0; i < len; i++) buf[i] = tolower(tmp[i]); *subType = _stringForSubType((char *)buf, len); } } else { *subType = @"*"; } // skip spaces while (isRfc822_LWSP(*cstr) && (*cstr != '\0')) cstr++; if (*cstr == ';') // skip ';' (parameter separator) cstr++; // We fix what could be potentially broken MIME type // For example, we can receive multipart/x-zip while // in reality, it is only a application/zip archive. // This will create a mayhem in the SOPE code. _fixMimeType(type, subType); // skip spaces while (isRfc822_LWSP(*cstr) && (*cstr != '\0')) cstr++; if (*cstr == '\0') { // string ends, no parameters defined *parameters = nil; return YES; } // parse parameters *parameters = parseParameters(self, _str, cstr); if (![*parameters isNotEmpty]) *parameters = nil; return YES; } SOPE/sope-mime/NGMime/TODO0000644000000000000000000000054115004363604014022 0ustar rootrootTODO: NGMime ============ NGMimeRFC822DateHeaderFieldGenerator: - do not use -descriptionWithCalendarFormat: - apparently a lot of code duplications for quoted printable decoding/encoding? look for "?iso-8859" in: - NGMimeAddressHeaderFieldGenerator.m - NGMimeContentDispositionHeaderFieldGenerator.m - NGMimeContentTypeHeaderFieldGenerator.m SOPE/sope-mime/NGMime/NGMime-Info.plist0000644000000000000000000000133615004363604016417 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable NGMime CFBundleGetInfoString CFBundleIdentifier org.OpenGroupware.SOPE.mime.NGMime CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType FMWK CFBundleShortVersionString CFBundleSignature ???? CFBundleVersion 4.5 SOPE/sope-mime/NGMime/GNUmakefile.preamble0000644000000000000000000000050415004363604017171 0ustar rootroot# compilation settings ADDITIONAL_CPPFLAGS += \ -DLIBRARY_MAJOR_VERSION=${MAJOR_VERSION} \ -DLIBRARY_MINOR_VERSION=${MINOR_VERSION} \ -DLIBRARY_SUBMINOR_VERSION=${SUBMINOR_VERSION} \ NGMime_INCLUDE_DIRS += \ -I.. -I../.. \ -I../../sope-core/NGStreams/ \ -I../../sope-core/NGExtensions/ \ -I../../sope-core SOPE/sope-mime/NGMime/NSData+RFC822.h0000644000000000000000000000164715004363604015467 0ustar rootroot/* Copyright (C) 2012 Inverse inc Author: Wolfgang Sourdeau This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import @interface NSData (NGRFC822) - (NSData *) dataByEnsuringCRLFLineEndings; @end SOPE/sope-mime/NGMime/NGConcreteMimeType.h0000644000000000000000000001345715004363604017156 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGConcreteMimeType_H__ #define __NGMime_NGConcreteMimeType_H__ #import #include @class NSString, NSDictionary; @interface NGParameterMimeType : NGMimeType { @protected NSString *subType; NSDictionary *parameters; } - (id)initWithType:(NSString *)_type subType:(NSString *)_subType parameters:(NSDictionary *)_parameters; @end /* The "text" media type is intended for sending material which is principally textual in form. A "charset" parameter may be used to indicate the character set of the body text for "text" subtypes, notably including the subtype "text/plain", which is a generic subtype for plain text. Plain text does not provide for or allow formatting commands, font attribute specifications, processing instructions, interpretation directives, or content markup. Plain text is seen simply as a linear sequence of characters, possibly interrupted by line breaks or page breaks. Plain text may allow the stacking of several characters in the same position in the text. Plain text in scripts like Arabic and Hebrew may also include facilitites that allow the arbitrary mixing of text segments with opposite writing directions. Beyond plain text, there are many formats for representing what might be known as "rich text". An interesting characteristic of many such representations is that they are to some extent readable even without the software that interprets them. It is useful, then, to distinguish them, at the highest level, from such unreadable data as images, audio, or text represented in an unreadable form. In the absence of appropriate interpretation software, it is reasonable to show subtypes of "text" to the user, while it is not reasonable to do so with most nontextual data. Such formatted textual data should be represented using subtypes of "text". The format parameter is described in: http://www.ietf.org/internet-drafts/draft-gellens-format-06.txt */ @interface NGConcreteTextMimeType : NGMimeType { @protected NSString *subType; NSString *charset; NSString *name; // used in vcards NSString *format; NSString *method; // used in iCalendars (method=REQUEST) NSString *replyType; // eg value 'response' BOOL delsp; float quality; } - (NSString *)method; @end @interface NGConcreteTextVcardMimeType : NGConcreteTextMimeType @end /* The "application" media type is to be used for discrete data which do not fit in any of the other categories, and particularly for data to be processed by some type of application program. This is information which must be processed by an application before it is viewable or usable by a user. Expected uses for the "application" media type include file transfer, spreadsheets, data for mail-based scheduling systems, and languages for "active" (computational) material. (The latter, in particular, can pose security problems which must be understood by implementors, and are considered in detail in the discussion of the "application/PostScript" media type.) */ @interface NGConcreteApplicationMimeType : NGParameterMimeType @end /* The "octet-stream" subtype is used to indicate that a body contains arbitrary binary data. The set of currently defined parameters is: 1. TYPE -- the general type or category of binary data. This is intended as information for the human recipient rather than for any automatic processing. 2. PADDING -- the number of bits of padding that were appended to the bit-stream comprising the actual contents to produce the enclosed 8bit byte-oriented data. This is useful for enclosing a bit-stream in a body when the total number of bits is not a multiple of 8. Both of these parameters are optional. An additional parameter, "CONVERSIONS", was defined in RFC 1341 but has since been removed. RFC 1341 also defined the use of a "NAME" parameter which gave a suggested file name to be used if the data were to be written to a file. This has been deprecated in anticipation of a separate Content-Disposition header field, to be defined in a subsequent RFC. */ @interface NGConcreteAppOctetMimeType : NGMimeType { @protected NSString *type; // the general type or category of binary data unsigned padding; // the number of bits of padding that were appended NSString *conversions; NSString *name; } @end @interface NGConcreteMultipartMimeType : NGParameterMimeType @end @interface NGConcreteMessageMimeType : NGParameterMimeType @end @interface NGConcreteImageMimeType : NGParameterMimeType @end @interface NGConcreteAudioMimeType : NGParameterMimeType @end @interface NGConcreteVideoMimeType : NGParameterMimeType @end @interface NGConcreteGenericMimeType : NGMimeType { @protected NSString *type; NSString *subType; NSDictionary *parameters; } @end @interface NGConcreteWildcardType : NGMimeType { @protected NSString *type; // nil means wildcard NSString *subType; // nil means wildcard NSDictionary *parameters; } @end #endif /* __NGMime_NGConcreteMimeType_H__ */ SOPE/sope-mime/NGMime/NGMimeType.h0000644000000000000000000000466115004363604015470 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGMimeType_H__ #define __NGMime_NGMimeType_H__ #import #import #include @class NSDictionary, NSString, NSEnumerator; // type & parameter constants NGMime_EXPORT NSString *NGMimeTypeText; NGMime_EXPORT NSString *NGMimeTypeAudio; NGMime_EXPORT NSString *NGMimeTypeVideo; NGMime_EXPORT NSString *NGMimeTypeImage; NGMime_EXPORT NSString *NGMimeTypeApplication; NGMime_EXPORT NSString *NGMimeTypeMultipart; NGMime_EXPORT NSString *NGMimeTypeMessage; NGMime_EXPORT NSString *NGMimeParameterTextCharset; /* NGMimeType is a class cluster */ @interface NGMimeType : NSObject < NSCoding, NSCopying > { } + (id)mimeType:(NSString *)_type subType:(NSString *)_subType; + (id)mimeType:(NSString *)_type subType:(NSString *)_subType parameters:(NSDictionary *)_parameters; + (id)mimeType:(NSString *)_stringValue; + (NSStringEncoding)stringEncodingForCharset:(NSString *)_s; /* type */ - (NSString *)type; - (NSString *)subType; - (BOOL)isCompositeType; /* comparing types */ - (BOOL)isEqualToMimeType:(NGMimeType *)_type; - (BOOL)isEqual:(id)_other; - (BOOL)hasSameGeneralType:(NGMimeType *)_other; // only the 'type' must match - (BOOL)hasSameType:(NGMimeType *)_other; // parameters need not match - (BOOL)doesMatchType:(NGMimeType *)_other; // interpretes wildcards // parameters - (NSEnumerator *)parameterNames; - (id)valueOfParameter:(NSString *)_parameterName; // representations - (NSDictionary *)parametersAsDictionary; - (NSString *)parametersAsString; - (BOOL)valueNeedsQuotes:(NSString *)_parameterValue; - (NSString *)stringValue; @end #endif /* __NGMime_NGMimeType_H__ */ SOPE/sope-mime/NGMime/NGMimeStringHeaderFieldParser.m0000644000000000000000000000444215004363604021251 0ustar rootroot/* Copyright (C) 2000-2006 SKYRIX Software AG Copyright (C) 2006 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGMimeHeaderFieldParser.h" #include "NGMimeHeaderFields.h" #include "NGMimeUtilities.h" #include "common.h" @implementation NGMimeStringHeaderFieldParser static BOOL StripLeadingSpaces = NO; + (void)initialize { StripLeadingSpaces = [self doesStripLeadingSpaces]; } - (id)initWithRemoveComments:(BOOL)_flag { if ((self = [super init])) { self->removeComments = _flag; } return self; } - (id)init { return [self initWithRemoveComments:NO]; } /* operation */ - (id)parseValue:(id)_value ofHeaderField:(NSString *)_field { // TODO: fixup unsigned len = [_value length]; unsigned cnt; unichar src[len + 1]; NSString *res; if (_value == nil) return nil; if (len == 0) return @""; res = self->removeComments ? [self removeCommentsFromValue:_value] : (NSString *)_value; if (StripLeadingSpaces) { /* currently be done during header field parsing */ [res getCharacters:src]; // strip leading spaces cnt = 0; while (isRfc822_LWSP(src[cnt]) && (len > 0)) { cnt++; len--; } if (cnt > 0) res = [[[NSString alloc] initWithCharacters:src+cnt length:len] autorelease]; } return res; } /* description */ - (NSString *)description { return [NSString stringWithFormat: @"", self, self->removeComments ? "YES" : "NO"]; } @end /* NGMimeStringHeaderFieldParser */ SOPE/sope-mime/NGMime/libNGMime.def0000644000000000000000000000500515004363604015615 0ustar rootrootEXPORTS __objc_class_name_NGParameterMimeType; __objc_class_name_NGConcreteTextMimeType; __objc_class_name_NGConcreteTextVcardMimeType; __objc_class_name_NGConcreteApplicationMimeType; __objc_class_name_NGConcreteAppOctetMimeType; __objc_class_name_NGConcreteImageMimeType; __objc_class_name_NGConcreteAudioMimeType; __objc_class_name_NGConcreteVideoMimeType; __objc_class_name_NGConcreteMultipartMimeType; __objc_class_name_NGConcreteMessageMimeType; __objc_class_name_NGConcreteGenericMimeType; __objc_class_name_NGConcreteWildcardType ; __objc_class_name_NGMime; __objc_class_name_NGMimeBodyGenerator; __objc_class_name_NGMimeTextBodyGenerator; __objc_class_name_NGMimeRfc822BodyGenerator; __objc_class_name_NGMimeMultipartBodyGenerator; __objc_class_name_NGMimeBodyParser; __objc_class_name_NGMimeTextBodyParser; __objc_class_name_NGMimeRfc822BodyParser; __objc_class_name_NGMimeMultipartBodyParser; __objc_class_name_NGMimeBodyPart; __objc_class_name_NGMimeBodyPartParser; __objc_class_name_NGMimeCommandMap; __objc_class_name_NGMimeDataHandler; __objc_class_name_NGMimeObjectDataHandler; __objc_class_name_NGMimeException; __objc_class_name_NGMimeParserException; __objc_class_name_NGMimeFileDataSource; __objc_class_name_NGMimeFileTypeMap; __objc_class_name_NGMimeDefaultsFileTypeMap; __objc_class_name_NGMimeHeaderFieldGenerator; __objc_class_name_NGMimeRFC822DateHeaderFieldGenerator; __objc_class_name_NGMimeContentTypeHeaderFieldGenerator; __objc_class_name_NGMimeContentLengthHeaderFieldGenerator; __objc_class_name_NGMimeContentDispositionHeaderFieldGenerator; __objc_class_name_NGMimeStringHeaderFieldGenerator; __objc_class_name_NGMimeHeaderFieldGeneratorSet; __objc_class_name_NGMimeHeaderFieldParser; __objc_class_name_NGMimeRFC822DateHeaderFieldParser; __objc_class_name_NGMimeContentTypeHeaderFieldParser; __objc_class_name_NGMimeContentLengthHeaderFieldParser; __objc_class_name_NGMimeContentDispositionHeaderFieldParser; __objc_class_name_NGMimeStringHeaderFieldParser; __objc_class_name_NGMimeHeaderFieldParserSet; __objc_class_name_NGMimeContentDispositionHeaderField; __objc_class_name_NGMimeMultipartBody; __objc_class_name_NGMimePartGenerator; __objc_class_name_NGMimePartParser; __objc_class_name_NGMimeType; NGMimeTypeText; NGMimeTypeAudio; NGMimeTypeVideo; NGMimeTypeImage; NGMimeTypeApplication; NGMimeTypeMultipart; NGMimeTypeMessage; NGMimeParameterTextCharset; NGMimeContentDispositionInlineType; NGMimeContentDispositionAttachmentType; NGMimeContentDispositionFormType; SOPE/sope-mime/NGMime/NGMimeBodyPartParser.h0000644000000000000000000000220615004363604017441 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGMime_NGMimeBodyPartParser_H__ #define __NGMime_NGMimeBodyPartParser_H__ #include /* Parses body-parts. Body-parts are the parts contained in a multipart body. The multipart body is parsed by a NGMimeMultipartBodyParser. */ @interface NGMimeBodyPartParser : NGMimePartParser @end #endif /* __NGMime_NGMimeBodyPartParser_H__ */ SOPE/packaging/0000755000000000000000000000000015004363604012247 5ustar rootrootSOPE/packaging/debian/0000755000000000000000000000000015004363604013471 5ustar rootrootSOPE/packaging/debian/500mod_ngobjweb.info0000644000000000000000000000024015004363604017223 0ustar rootrootLoadModule ngobjweb_module /usr/lib/apache/1.3/mod_ngobjweb.so Description: Enables apache to handle HTTP requests for the OpenGroupware.org application server SOPE/packaging/debian/libsope-core_SOPEVER_.install0000644000000000000000000000012115004363604021000 0ustar rootrootusr/lib/libNGExtensions.so.* usr/lib/libEOControl.so.* usr/lib/libNGStreams.so.* SOPE/packaging/debian/sope_SOPEVER_-gdl1-postgresql.install0000644000000000000000000000006415004363604022417 0ustar rootrootusr/lib/GNUstep/GDLAdaptors-*/PostgreSQL.gdladaptor SOPE/packaging/debian/sope_SOPEVER_-stxsaxdriver.install0000644000000000000000000000005615004363604022136 0ustar rootrootusr/lib/GNUstep/SaxDrivers-*/STXSaxDriver.sax SOPE/packaging/debian/libsbjson2.3.install0000644000000000000000000000002715004363604017270 0ustar rootrootusr/lib/libSBJson.so.* SOPE/packaging/debian/libapache2-mod-ngobjweb.dirs0000644000000000000000000000006315004363604020715 0ustar rootrootusr/lib/apache2/modules etc/apache2/mods-available SOPE/packaging/debian/rules0000755000000000000000000001230515004363604014552 0ustar rootroot#!/usr/bin/make -f # -*- makefile -*- # Sample debian/rules that uses debhelper. # GNU copyright 1997 to 1999 by Joey Hess. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 CFLAGS = -Wall -g #WARN: doesn't compile/package if HAS_LIBRARY_* options not present (since we use configure now) MAKE_FLAGS = messages=yes OPTFLAG=-O2 HAS_LIBRARY_ldap=yes HAS_LIBRARY_pq=yes HAS_LIBRARY_xml2=yes GNUSTEP_SETUP=/usr/share/GNUstep/Makefiles/GNUstep.sh include Version SOPEVER=$(MAJOR_VERSION).$(MINOR_VERSION) ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) CFLAGS += -O0 else CFLAGS += -O2 endif ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) INSTALL_PROGRAM += -s endif controlfiles: controlfiles-stamp debian/control controlfiles-stamp: debian/rules clean-controlfiles for f in debian/*_SOPEVER_*; do \ newname=$$(echo $$f | sed s/_SOPEVER_/$(SOPEVER)/ ); \ cp $$f $$newname; \ echo $$newname >> controlfiles.tmp; \ done mv controlfiles.tmp controlfiles-stamp clean-controlfiles: if [ -f controlfiles-stamp ]; then \ for f in $$(cat controlfiles-stamp); do \ rm $$f; \ done; \ rm controlfiles-stamp; \ fi if [ -f controlfiles.tmp ]; then \ for f in $$(cat controlfiles-stamp); do \ rm $$f; \ done; \ rm controlfiles.tmp; \ fi debian/control: debian/control.in debian/rules sed -e s/_SOPEVER_/$(SOPEVER)/g < debian/control.in > debian/control config.make: dh_testdir CFLAGS="$(CFLAGS)" . $(GNUSTEP_SETUP); \ ./configure --with-gnustep --enable-debug --disable-strip build: config.make build-stamp controlfiles build-stamp: config.make dh_testdir -mv sope-core/NGStreams/config.guess sope-core/NGStreams/config.guess.upstream -mv sope-core/NGStreams/config.sub sope-core/NGStreams/config.sub.upstream ln -s /usr/share/misc/config.guess sope-core/NGStreams/config.guess ln -s /usr/share/misc/config.sub sope-core/NGStreams/config.sub CFLAGS="$(CFLAGS)" . $(GNUSTEP_SETUP); \ $(MAKE) $(MAKE_FLAGS) all # cp -R sope-appserver/mod_ngobjweb sope-appserver/mod_ngobjweb-apache2 # CFLAGS="$(CFLAGS)" . $(GNUSTEP_SETUP); \ # $(MAKE) $(MAKE_FLAGS) APXS=/usr/bin/apxs -C sope-appserver/mod_ngobjweb all # CFLAGS="$(CFLAGS)" . $(GNUSTEP_SETUP); \ # $(MAKE) $(MAKE_FLAGS) APXS="/usr/bin/apxs2" APXS_INCLUDE_DIRS="$(shell apxs2 -q EXTRA_INCLUDES)"\ # -C sope-appserver/mod_ngobjweb-apache2 all touch build-stamp clean: clean-controlfiles dh_testdir dh_testroot rm -f configure-stamp rm -f build-stamp rm -f config-NSStreams.log rm -rf sope-appserver/mod_ngobjweb-apache2 rm -rf sope-core/NGStreams/x86_64 if [ -L sope-core/NGStreams/config.guess ]; then \ rm sope-core/NGStreams/config.guess; \ fi if [ -L sope-core/NGStreams/config.sub ]; then \ rm sope-core/NGStreams/config.sub; \ fi if [ -f sope-core/NGStreams/config.guess.upstream ]; then \ mv sope-core/NGStreams/config.guess.upstream sope-core/NGStreams/config.guess; \ fi if [ -f sope-core/NGStreams/config.sub.upstream ]; then \ mv sope-core/NGStreams/config.sub.upstream sope-core/NGStreams/config.sub; \ fi # -. $(GNUSTEP_SETUP); $(MAKE) -C sope-appserver/mod_ngobjweb clean # -. $(GNUSTEP_SETUP); $(MAKE) -C sope-appserver/mod_ngobjweb distclean -. $(GNUSTEP_SETUP); $(MAKE) clean -. $(GNUSTEP_SETUP); $(MAKE) distclean dh_clean install: build dh_testdir dh_testroot dh_clean -k dh_installdirs # Add here commands to install the package into debian/tmp CFLAGS="$(CFLAGS)" . $(GNUSTEP_SETUP); \ $(MAKE) $(MAKE_FLAGS) install \ DESTDIR=$(CURDIR)/debian/tmp GNUSTEP_INSTALLATION_DOMAIN=SYSTEM # INSTALL_ROOT_DIR=$(CURDIR)/debian/tmp\ FHS_INSTALL_ROOT=$(CURDIR)/debian/tmp/usr \ FHS_LIB_DIR=$(CURDIR)/debian/tmp/usr/lib/ #WARN: <- trailing slash unbroke build/packages?! # CFLAGS="$(CFLGAS)" . $(GNUSTEP_SETUP); \ $(MAKE) $(MAKE_FLAGS) -C sope-appserver/mod_ngobjweb install \ GNUSTEP_INSTALLATION_DOMAIN=$(CURDIR)/debian/tmp/usr/lib/apache/1.3 # CFLAGS="$(CFLGAS)" . $(GNUSTEP_SETUP); \ $(MAKE) $(MAKE_FLAGS) -C sope-appserver/mod_ngobjweb-apache2 install \ GNUSTEP_INSTALLATION_DOMAIN=$(CURDIR)/debian/tmp/usr/lib/apache2/modules # install -m 644 debian/500mod_ngobjweb.info $(CURDIR)/debian/libapache-mod-ngobjweb/usr/lib/apache/1.3 # install -m 644 debian/ngobjweb.load $(CURDIR)/debian/libapache2-mod-ngobjweb/etc/apache2/mods-available # Build architecture-independent files here. binary-indep: build install # We have nothing to do by default. # Build architecture-dependent files here. binary-arch: build install dh_testdir dh_testroot dh_installchangelogs dh_installdocs dh_installexamples dh_install --sourcedir=debian/tmp # dh_installmenu # dh_installdebconf # dh_installlogrotate # dh_installemacsen # dh_installpam # dh_installmime # dh_installinit # dh_installcron # dh_installinfo dh_installman dh_link dh_strip --dbg-package=sope$(SOPEVER)-dbg dh_compress dh_fixperms # dh_perl # dh_python dh_makeshlibs -V dh_installdeb dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info -L libsope-appserver$(SOPEVER) -L libsope-xml$(SOPEVER) -L libsope-mime$(SOPEVER) \ -L libsope-ldap$(SOPEVER) -L libsope-gdl1-$(SOPEVER) \ -l debian/tmp/usr/lib dh_gencontrol dh_md5sums dh_builddeb -- -Zgzip binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary install configure SOPE/packaging/debian/libapache-mod-ngobjweb.dirs0000644000000000000000000000002315004363604020627 0ustar rootrootusr/lib/apache/1.3 SOPE/packaging/debian/source/0000755000000000000000000000000015004363604014771 5ustar rootrootSOPE/packaging/debian/source/options0000644000000000000000000000002515004363604016404 0ustar rootrootcompression = "gzip" SOPE/packaging/debian/compat0000644000000000000000000000000215004363604014667 0ustar rootroot7 SOPE/packaging/debian/libsope-xml_SOPEVER_.install0000644000000000000000000000010315004363604020650 0ustar rootrootusr/lib/libDOM.so.* usr/lib/libSaxObjC.so.* usr/lib/libXmlRpc.so.* SOPE/packaging/debian/sope_SOPEVER_-appserver.install0000644000000000000000000000000015004363604021364 0ustar rootrootSOPE/packaging/debian/libapache2-mod-ngobjweb.postinst0000755000000000000000000000044015004363604021641 0ustar rootroot#!/bin/bash set -e if [ -e /etc/apache2/httpd.conf ]; then a2enmod ngobjweb fi if [ -x /usr/sbin/invoke-rc.d ] && [ -x /etc/init.d/apache2 ]; then invoke-rc.d apache2 force-reload || true elif [ -x /etc/init.d/apache2 ]; then /etc/init.d/apache2 force-reload || true fi #DEBHELPER# SOPE/packaging/debian/libsope-ldap_SOPEVER_.install0000644000000000000000000000002715004363604020775 0ustar rootrootusr/lib/libNGLdap.so.* SOPE/packaging/debian/ngobjweb.load0000644000000000000000000000010415004363604016122 0ustar rootrootLoadModule ngobjweb_module /usr/lib/apache2/modules/mod_ngobjweb.so SOPE/packaging/debian/copyright0000644000000000000000000000212515004363604015424 0ustar rootrootThis package was debianized by Sebastian Ley on Wed, 26 Nov 2003 21:17:15 +0100. It was downloaded from http://www.opengroupware.org Copyright (C) 2000-2003 SKYRIX Software AG Contact: info@skyrix.com License: This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA On Debian systems, the complete text of the GNU Lesser General Public License can be found in `/usr/share/common-licenses/LGPL'. SOPE/packaging/debian/control.in0000644000000000000000000002412015004363604015500 0ustar rootrootSource: sope Section: web Priority: extra Maintainer: Inverse Support Build-Depends: debhelper (>= 7.0.15), gnustep-make, libgnustep-base-dev, gobjc | objc-compiler, libxml2-dev, libldap2-dev | libldap-dev, libssl-dev, zlib1g-dev, libpq-dev | postgresql-dev, libmysqlclient-dev (>= 5.0) | libmysqlclient15-dev (>= 5.0) | libmariadbclient-dev-compat, autotools-dev Standards-Version: 3.9.1 Package: sope_SOPEVER_-dbg Section: debug Architecture: any Priority: extra Depends: libsope-appserver_SOPEVER_ (= ${binary:Version}) | sope_SOPEVER_-appserver (= ${binary:Version}) | libsope-core_SOPEVER_ (= ${binary:Version}) | libsope-xml_SOPEVER_ (= ${binary:Version}) | libsope-ldap_SOPEVER_ (= ${binary:Version}) | libsope-mime_SOPEVER_ (= ${binary:Version}) | libsope-gdl1-_SOPEVER_ (= ${binary:Version}) | sope_SOPEVER_-gdl1-postgresql (= ${binary:Version}) | sope_SOPEVER_-gdl1-mysql (= ${binary:Version}) | sope_SOPEVER_-stxsaxdriver (= ${binary:Version}) | sope_SOPEVER_-libxmlsaxdriver (= ${binary:Version}), ${misc:Depends} Description: Debugging files SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . This package contains the debugging symbols for all SOPE packages. Package: libsope_SOPEVER_-dev Section: libdevel Architecture: all Provides: libsope-dev Conflicts: libsope-dev Depends: libsope-appserver_SOPEVER_-dev, libsope-core_SOPEVER_-dev, libsope-xml_SOPEVER_-dev, libsope-mime_SOPEVER_-dev, libsope-ldap_SOPEVER_-dev, libsope-gdl1-_SOPEVER_-dev, libsbjson-dev, ${misc:Depends} Description: Development files for all SOPE libraries SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . This is a meta-package depending on all development files of all components of SOPE. Package: libsope-appserver_SOPEVER_-dev Section: libdevel Architecture: any Provides: libsope-appserver-dev Conflicts: libsope-appserver-dev Depends: libsope-appserver_SOPEVER_ (= ${binary:Version}), ${misc:Depends} Description: Development files for the SOPE libraries SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . This package contains the development files for the SOPE application server libraries. Package: libsope-appserver_SOPEVER_ Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: SOPE application server libraries SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . The SOPE application server libraries provide: . * template rendering engine, lots of dynamic elements * HTTP client/server * XML-RPC client * WebDAV server framework * session management * scripting extensions for Foundation, JavaScript bridge * DOM tree rendering library Package: sope_SOPEVER_-appserver Section: web Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: SOPE application server SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . This package contains the application server that serves SOPE sites. Package: libsope-core_SOPEVER_-dev Section: libdevel Architecture: any Provides: libsope-core-dev Conflicts: libsope-core-dev Depends: libsope-core_SOPEVER_ (= ${binary:Version}), ${misc:Depends} Description: Development files for the SOPE core libraries SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . This package contains the header files for the SOPE core libraries, which are part of the SOPE application server framework. Package: libsope-core_SOPEVER_ Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: Core libraries of the SOPE application server The SOPE core libraries contain: . * various Foundation extensions * a java.io like stream and socket library Package: libsope-xml_SOPEVER_-dev Section: libdevel Architecture: any Provides: libsope-xml-dev Conflicts: libsope-xml-dev Depends: libsope-xml_SOPEVER_ (= ${binary:Version}), ${misc:Depends} Description: Development files for the SOPE XML libraries SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . This package contains the development files of the SOPE XML libraries. Package: libsope-xml_SOPEVER_ Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: SOPE libraries for XML processing SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . The SOPE libraries for XML processing contain: . * a SAX2 Implementation for Objective-C * an attempt to implement DOM on top of SaxObjC * an XML-RPC implementation (without a transport layer) Package: libsope-ldap_SOPEVER_-dev Section: libdevel Architecture: any Provides: libsope-ldap-dev Conflicts: libsope-ldap-dev Depends: libsope-ldap_SOPEVER_ (= ${binary:Version}), ${misc:Depends} Description: Development files for the SOPE LDAP libraries SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . This package contains the development files of the SOPE LDAP libraries. Package: libsope-ldap_SOPEVER_ Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: SOPE libraries for LDAP access SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . The SOPE libraries for LDAP access contain an Objective-C wrapper for LDAP directory services. Package: libsope-mime_SOPEVER_-dev Section: libdevel Architecture: any Provides: libsope-mime-dev Conflicts: libsope-mime-dev Depends: libsope-mime_SOPEVER_ (= ${binary:Version}), ${misc:Depends} Description: Development files for the SOPE MIME libraries SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . This package contains the development files of the SOPE MIME libraries. Package: libsope-mime_SOPEVER_ Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: SOPE libraries for MIME processing SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . The SOPE libraries for MIME processing contain: . * classes for processing MIME entities * a full IMAP4 implementation * prototypical POP3 and SMTP processor Package: libsope-gdl1-_SOPEVER_-dev Section: libdevel Architecture: any Provides: libsope-gdl1-dev Conflicts: libsope-gdl1-dev Depends: libsope-gdl1-_SOPEVER_ (= ${binary:Version}), ${misc:Depends} Description: Development files for the GNUstep database libraries SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . This package contains the header files for SOPE's fork of the GNUstep database libraries. Package: libsope-gdl1-_SOPEVER_ Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: GNUstep database libraries for SOPE SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . This package contains a fork of the GNUstep database libraries used by the SOPE application server. Package: sope_SOPEVER_-gdl1-postgresql Section: web Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Provides: sope_SOPEVER_-db-connector Suggests: postgresql (>= 8.2) Description: PostgreSQL connector for SOPE's fork of the GNUstep database environment SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . This package contains the postgresql connector for SOPE's fork of the GNUstep database libraries. Package: sope_SOPEVER_-gdl1-mysql Section: web Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Provides: sope_SOPEVER_-db-connector Suggests: mysql-server (>= 5.0) Description: MySQL connector for SOPE's fork of the GNUstep database environment SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . This package contains the mysql connector for SOPE's fork of the GNUstep database libraries. Package: sope_SOPEVER_-stxsaxdriver Section: web Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Provides: sope-stxsaxdriver Description: Structured Text Parser for SOPE's SAX engine SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . This parser enables SOPE's SAX engine to parse structured text files. Package: sope_SOPEVER_-libxmlsaxdriver Section: web Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Provides: sope-libxmlsaxdriver Description: XML Parser for SOPE's SAX engine SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. . This parser enables SOPE's SAX engine to parse XML files. Package: libsbjson2.3 Section: web Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Provides: libsbjson Description: High performance Objective-C JSON library The BSJson library is a very fast JSON library in Objective-C. . url: http://code.google.com/p/json-framework/ Package: libsbjson2.3-dev Section: libdevel Architecture: any Depends: libsbjson2.3 (= ${binary:Version}), ${misc:Depends} Provides: libsbjson-dev Description: High performance Objective-C JSON library The BSJson library is a very fast JSON library in Objective-C. . url: http://code.google.com/p/json-framework/ SOPE/packaging/debian/libsbjson2.3-dev.install0000644000000000000000000000006015004363604020041 0ustar rootrootusr/include/GNUstep/SBJson usr/lib/libSBJson.so SOPE/packaging/debian/libapache-mod-ngobjweb.postinst0000755000000000000000000000072015004363604021560 0ustar rootroot#!/bin/bash set -e for i in apache apache-perl apache-ssl; do if [ -e /etc/$i/httpd.conf ]; then modules-config $i enable mod_ngobjweb fi if [ -d /etc/$i/conf.d ]; then ucf --purge /etc/$i/conf.d/mod_ngobjweb fi if [ -x /usr/sbin/invoke-rc.d ] && [ -x /etc/init.d/$i ]; then invoke-rc.d $i force-reload || true elif [ -x /etc/init.d/$i ]; then /etc/init.d/$i force-reload || true fi done #DEBHELPER# SOPE/packaging/debian/libapache2-mod-ngobjweb.prerm0000755000000000000000000000044115004363604021104 0ustar rootroot#!/bin/bash set -e if [ -e /etc/apache2/httpd.conf ]; then a2dismod ngobjweb fi if [ -x /usr/sbin/invoke-rc.d ] && [ -x /etc/init.d/apache2 ]; then invoke-rc.d apache2 force-reload || true elif [ -x /etc/init.d/apache2 ]; then /etc/init.d/apache2 force-reload || true fi #DEBHELPER# SOPE/packaging/debian/libsope-mime_SOPEVER_-dev.install0000644000000000000000000000014715004363604021563 0ustar rootrootusr/include/GNUstep/NGMime usr/include/GNUstep/NGImap4 usr/include/GNUstep/NGMail usr/lib/libNGMime.so SOPE/packaging/debian/libapache-mod-ngobjweb.postrm0000755000000000000000000000061315004363604021222 0ustar rootroot#!/bin/bash set -e case "$1" in purge) for i in apache apache-perl apache-ssl; do rm -f /etc/$i/conf.d/mod_ngobjweb for ext in .dpkg-tmp .dpkg-new .dpkg-old .dpkg-dist; do rm -f /etc/$i/conf.d/mod_ngobjweb$ext done ucf --purge /etc/$i/conf.d/mod_ngobjweb done ;; *) ;; esac #DEBHELPER# SOPE/packaging/debian/changelog0000644000000000000000000000445515004363604015353 0ustar rootrootsope (4.9.r1664) unstable; urgency=low * added package for SBJson -- Inverse Support Tue, 02 Nov 2010 14:49:27 -0500 sope (4.9.r1664-1) unstable; urgency=low * updated SOPE patchset for SOGo 1.2.0. * updated upstream SOPE revision to 1664. -- Inverse Support Wed, 06 Jan 2010 14:49:27 -0500 sope (4.9.r1660-2) unstable; urgency=low * debian/control: - we now build the sopeXX-gdl1-mysql package. * updated SOPE patchset from SOGo 1.1.0. -- Inverse Support Mon, 19 Oct 2009 16:36:29 -0400 sope (4.9.r1660-1) unstable; urgency=low * debian/control: - updated dependencies - changed {Source-Version} with {binary:Version} - bumbed standard to 3.8.2 - updated debian/copyright with recent LGPL-2 -- Inverse Support Wed, 12 Aug 2009 10:34:00 -0400 sope (4.7.0-0) UNRELEASED; urgency=low * New upstream release. -- Frank Reppin Thu, 22 Feb 2007 14:51:52 +0100 sope (4.5.5-0) UNRELEASED; urgency=low * New upstream release. * Adjust Build-Depends, that allows building in sarge -- Sebastian Ley Thu, 29 Sep 2005 13:49:11 +0200 sope (4.3.9-1) experimental; urgency=low * New upstream release. * Remove iCalSaxdriver (and thus the dependency on libical) in favour of versitSaxDriver. * Remove standard configuration files for mod_ngobjweb. Such things belong to a setup of a SOPE site and not in mod_ngobjweb's default configuration. -- Sebastian Ley Thu, 21 Oct 2004 17:53:54 +0200 sope (4.3.8-1) experimental; urgency=low * Initial Release. Upstream did some heavy source restructuring, resulting in a greatly reduced number of source packages for SOPE and OpenGroupware.org. At the same time SOPE and OpenGroupware.org will now be treated different projects, since SOPE can be useful without OGo as well. * A new versioning scheme has been applied to the new sources. Versions with an odd number as second component denote unstable development versions. Neither API nor ABI stability may be ensured in this version. Versions with an even second component are the stable releases. * SOPE now installs to FHS compliant paths. -- Sebastian Ley Sat, 2 Oct 2004 18:14:45 +0200 SOPE/packaging/debian/libsope-gdl1-_SOPEVER_.install0000644000000000000000000000003215004363604020755 0ustar rootrootusr/lib/libGDLAccess.so.* SOPE/packaging/debian/libsope-gdl1-_SOPEVER_-dev.install0000644000000000000000000000006615004363604021540 0ustar rootrootusr/include/GNUstep/GDLAccess usr/lib/libGDLAccess.so SOPE/packaging/debian/libapache2-mod-ngobjweb.install0000644000000000000000000000002015004363604021413 0ustar rootrootusr/lib/apache2 SOPE/packaging/debian/libsope-ldap_SOPEVER_-dev.install0000644000000000000000000000006015004363604021546 0ustar rootrootusr/include/GNUstep/NGLdap usr/lib/libNGLdap.so SOPE/packaging/debian/sope_SOPEVER_-libxmlsaxdriver.install0000644000000000000000000000006115004363604022603 0ustar rootrootusr/lib/GNUstep/SaxDrivers-*/libxmlSAXDriver.sax SOPE/packaging/debian/sope_SOPEVER_-gdl1-mysql.install0000644000000000000000000000005715004363604021363 0ustar rootrootusr/lib/GNUstep/GDLAdaptors-*/MySQL.gdladaptor SOPE/packaging/debian/sope_SOPEVER_-appserver.links0000644000000000000000000000010215004363604021041 0ustar rootrootusr/share/man/man7/undocumented.7.gz usr/share/man/man8/sope.8.gz SOPE/packaging/debian/libsope-appserver_SOPEVER_-dev.install0000644000000000000000000000034515004363604022643 0ustar rootrootusr/include/GNUstep/NGHttp usr/include/GNUstep/NGObjWeb usr/include/GNUstep/WOExtensions usr/include/GNUstep/WEExtensions usr/lib/libNGObjWeb.so usr/lib/libWOExtensions.so usr/lib/libWEExtensions.so usr/share/GNUstep/Makefiles/* SOPE/packaging/debian/libsope-appserver_SOPEVER_.install0000644000000000000000000000030515004363604022063 0ustar rootrootusr/lib/libNGObjWeb.so.* usr/lib/libWOExtensions.so.* usr/lib/libWEExtensions.so.* usr/lib/GNUstep/Libraries/Resources/NGObjWeb/* usr/lib/GNUstep/SoProducts-*/* usr/lib/GNUstep/WOxElemBuilders-*/* SOPE/packaging/debian/libsope-xml_SOPEVER_-dev.install0000644000000000000000000000021415004363604021427 0ustar rootrootusr/include/GNUstep/DOM usr/include/GNUstep/SaxObjC usr/include/GNUstep/XmlRpc usr/lib/libDOM.so usr/lib/libSaxObjC.so usr/lib/libXmlRpc.so SOPE/packaging/debian/libapache-mod-ngobjweb.install0000644000000000000000000000001715004363604021337 0ustar rootrootusr/lib/apache SOPE/packaging/debian/libsope-core_SOPEVER_-dev.install0000644000000000000000000000025015004363604021557 0ustar rootrootusr/include/GNUstep/NGExtensions usr/include/GNUstep/EOControl usr/include/GNUstep/NGStreams usr/lib/libNGExtensions.so usr/lib/libEOControl.so usr/lib/libNGStreams.so SOPE/packaging/debian/libapache-mod-ngobjweb.prerm0000755000000000000000000000057415004363604021031 0ustar rootroot#!/bin/bash set -e for i in apache apache-perl apache-ssl; do if [ -e /etc/$i/httpd.conf ]; then modules-config $i disable mod_ngobjweb quiet fi if [ -x /usr/sbin/invoke-rc.d ] && [ -x /etc/init.d/$i ]; then invoke-rc.d $i force-reload || true elif [ -x /etc/init.d/$i ]; then /etc/init.d/$i force-reload || true fi done #DEBHELPER# SOPE/packaging/debian/libsope-mime_SOPEVER_.install0000644000000000000000000000002715004363604021004 0ustar rootrootusr/lib/libNGMime.so.* SOPE/packaging/rhel/0000755000000000000000000000000015004363604013201 5ustar rootrootSOPE/packaging/rhel/sope.spec0000644000000000000000000004245015004363604015030 0ustar rootroot%define apache_modules_dir %{_usr}/lib/httpd/modules %define apache_conf_dir %{_sysconfdir}/httpd/conf.d %define oracle_support 1 %{?el7:%define oracle_support 1} %{?el8:%define oracle_support 0} %{?el9:%define oracle_support 0} Summary: SOPE Name: sope%{sope_major_version}%{sope_minor_version} Version: %{sope_version} Release: %{sope_release}.%{dist_suffix}.%{sope_buildcount} Vendor: http://www.opengroupware.org Packager: Inverse inc. License: GPL URL: https://github.com/inverse-inc/sope Group: Development/Libraries/Objective C AutoReqProv: off Source: %{sope_source} Prefix: /usr BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root BuildPreReq: gnustep-make gcc-objc postgresql-devel %{?el5:BuildRequires: mysql-devel} %{?el6:BuildRequires: mysql-devel} %{?el7:BuildRequires: mariadb-devel} %{?el8:BuildRequires: mariadb-devel} %{?el9:BuildRequires: mariadb-devel} %description sope ######################################### %package xml Summary: SOPE libraries for XML processing Group: Development/Libraries/Objective C AutoReqProv: off %description xml The SOPE libraries for XML processing contain: * a SAX2 Implementation for Objective-C * an attempt to implement DOM on top of SaxObjC * an XML-RPC implementation (without a transport layer) SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. %package xml-devel Summary: Development files for the SOPE XML libraries Group: Development/Libraries/Objective C Requires: sope%{sope_major_version}%{sope_minor_version}-xml libxml2-devel AutoReqProv: off %description xml-devel This package contains the development files of the SOPE XML libraries. SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. ######################################### %package sbjson Summary: JSON framework Group: Development/Libraries/Objective C Version: %{sbjson_version} %description sbjson The SBJson library is a high performance JSON library in Objective-C. Project homepage is: http://code.google.com/p/json-framework/ %package sbjson-devel Summary: JSON framework (devel) Group: Development/Libraries/Objective C Version: %{sbjson_version} %description sbjson-devel The SBJson library is a high performance JSON library in Objective-C. Those are the files required for development. Project homepage is: http://code.google.com/p/json-framework/ ######################################### %package core Summary: Core libraries of the SOPE application server Group: Development/Libraries/Objective C Requires: sope%{sope_major_version}%{sope_minor_version}-xml AutoReqProv: off %description core The SOPE core libraries contain: * various Foundation extensions * a java.io like stream and socket library SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. %package core-devel Summary: Development files for the SOPE core libraries Group: Development/Libraries/Objective C Requires: sope%{sope_major_version}%{sope_minor_version}-core AutoReqProv: off %description core-devel This package contains the header files for the SOPE core libraries, which are part of the SOPE application server framework. SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. ######################################### %package mime Summary: SOPE libraries for MIME processing Group: Development/Libraries/Objective C Requires: sope%{sope_major_version}%{sope_minor_version}-core sope%{sope_major_version}%{sope_minor_version}-xml AutoReqProv: off %description mime The SOPE libraries for MIME processing contain: * classes for processing MIME entities * a full IMAP4 implementation * prototypical POP3 and SMTP processor SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. %package mime-devel Summary: Development files for the SOPE MIME libraries Group: Development/Libraries/Objective C Requires: sope%{sope_major_version}%{sope_minor_version}-mime AutoReqProv: off %description mime-devel This package contains the development files of the SOPE MIME libraries. SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. ######################################### %package appserver Summary: SOPE application server libraries Group: Development/Libraries/Objective C Requires: sope%{sope_major_version}%{sope_minor_version}-xml sope%{sope_major_version}%{sope_minor_version}-core sope%{sope_major_version}%{sope_minor_version}-mime AutoReqProv: off %description appserver The SOPE application server libraries provide: * template rendering engine, lots of dynamic elements * HTTP client/server * XML-RPC client * WebDAV server framework * session management * scripting extensions for Foundation, JavaScript bridge * DOM tree rendering library SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. %package appserver-devel Summary: Development files for the SOPE application server libraries Group: Development/Libraries/Objective C Requires: sope%{sope_major_version}%{sope_minor_version}-appserver AutoReqProv: off %description appserver-devel This package contains the development files for the SOPE application server libraries. SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. ######################################### %package ldap Summary: SOPE libraries for LDAP access Group: Development/Libraries/Objective C Requires: sope%{sope_major_version}%{sope_minor_version}-core sope%{sope_major_version}%{sope_minor_version}-xml AutoReqProv: off %description ldap The SOPE libraries for LDAP access contain an Objective-C wrapper for LDAP directory services. SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. %package ldap-devel Summary: Development files for the SOPE LDAP libraries Group: Development/Libraries/Objective C Requires: sope%{sope_major_version}%{sope_minor_version}-ldap AutoReqProv: off %description ldap-devel This package contains the development files of the SOPE LDAP libraries. SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. ######################################### %package gdl1 Summary: GNUstep database libraries for SOPE Group: Development/Libraries/Objective C Requires: sope%{sope_major_version}%{sope_minor_version}-core sope%{sope_major_version}%{sope_minor_version}-xml AutoReqProv: off %description gdl1 This package contains a fork of the GNUstep database libraries used by the SOPE application server (excluding GDLContentStore). SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. %package gdl1-postgresql Summary: PostgreSQL connector for SOPE's fork of the GNUstep database environment Group: Development/Libraries/Objective C Requires: sope%{sope_major_version}%{sope_minor_version}-gdl1 postgresql-libs AutoReqProv: off %description gdl1-postgresql This package contains the PostgreSQL connector for SOPE's fork of the GNUstep database libraries. SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. %if %oracle_support %package gdl1-oracle Summary: Oracle connector for SOPE's fork of the GNUstep database environment Group: Development/Libraries/Objective C Requires: sope%{sope_major_version}%{sope_minor_version}-gdl1 #Requires: oracle-instantclient-basic AutoReqProv: off %description gdl1-oracle This package contains the Oracle connector for SOPE's fork of the GNUstep database libraries. %endif %package gdl1-mysql Summary: MySQL connector for SOPE's fork of the GNUstep database environment Group: Development/Libraries/Objective C Requires: sope%{sope_major_version}%{sope_minor_version}-gdl1 AutoReqProv: off %description gdl1-mysql This package contains the MySQL connector for SOPE's fork of the GNUstep database libraries. #%package gdl1-sqlite3 #Summary: SQLite3 connector for SOPE's fork of the GNUstep database environment #Group: Development/Libraries/Objective C #Requires: sope%{sope_major_version}%{sope_minor_version}-gdl1 #AutoReqProv: off # #%description gdl1-sqlite3 #This package contains the SQLite3 connector for SOPE's fork of the #GNUstep database libraries. # #SOPE is a framework for developing web applications and services. The #name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. %package gdl1-devel Summary: Development files for the GNUstep database libraries Group: Development/Libraries/Objective C Requires: sope%{sope_major_version}%{sope_minor_version}-gdl1 AutoReqProv: off %description gdl1-devel This package contains the header files for SOPE's fork of the GNUstep database libraries. SOPE is a framework for developing web applications and services. The name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE. #%package -n mod_ngobjweb #Summary: mod_ngobjweb apache module #Group: Development/Libraries #AutoReqProv: off #Requires: %{ngobjweb_requires} # #%description -n mod_ngobjweb #Enables apache to handle HTTP requests for the #OpenGroupware.org application server. ######################################## %prep rm -fr ${RPM_BUILD_ROOT} %setup -q -n SOPE # ****************************** build ******************************** %build case %{_target_platform} in ppc64-*) export CC="gcc -m64";; *) export CC="gcc";; esac %ifarch x86_64 ORACLELIB_PATH="/usr/%{_lib}/oracle/11.2/client64/lib/" %else ORACLELIB_PATH="/usr/%{_lib}/oracle/11.2/client/lib/" %endif if [ -f /usr/lib/rpm/redhat/config.sub ] then cp /usr/lib/rpm/redhat/{config.sub,config.guess} sope-core/NGStreams/ elif [ -f /usr/lib/rpm/config.sub ] then cp /usr/lib/rpm/{config.sub,config.guess} sope-core/NGStreams/ fi ./configure \ --enable-debug \ --disable-strip \ --with-gnustep make CC="$CC" %{sope_makeflags} cd sope-gdl1/MySQL make CC="$CC" LDFLAGS="-L/usr/%{_lib}/mysql" %{sope_makeflags} %if %oracle_support cd ../Oracle8 make CC="$CC" LDFLAGS="-L$ORACLELIB_PATH" %{sope_makeflags} %endif #export PATH=$PATH:/usr/sbin #cd ../../sope-appserver/mod_ngobjweb/ #if [ -x /usr/bin/apr-1-config ] #then # aprconfig=/usr/bin/apr-1-config #else # aprconfig=/usr/bin/apr-config #fi #make apr=$aprconfig apxs=/usr/sbin/apxs # ****************************** install ****************************** %install make %{sope_makeflags} DESTDIR=${RPM_BUILD_ROOT} \ GNUSTEP_INSTALLATION_DOMAIN=SYSTEM \ install cd sope-gdl1/MySQL make %{sope_makeflags} DESTDIR=${RPM_BUILD_ROOT} \ GNUSTEP_INSTALLATION_DOMAIN=SYSTEM \ install %if %oracle_support cd ../Oracle8 make %{sope_makeflags} DESTDIR=${RPM_BUILD_ROOT} \ GNUSTEP_INSTALLATION_DOMAIN=SYSTEM \ install %endif rm -f ${RPM_BUILD_ROOT}%{_bindir}/otest rm -fr ${RPM_BUILD_ROOT}%{_libdir}/GNUstep/GDLAdaptors-%{sope_version}/SQLite3.gdladaptor # rm -f ${RPM_BUILD_ROOT}/usr/GNUstep/System/Tools/Admin/sope-4.9 # export PATH=$PATH:/usr/sbin #mkdir -p ${RPM_BUILD_ROOT}%{apache_modules_dir} #cp sope-appserver/mod_ngobjweb/mod_ngobjweb.so ${RPM_BUILD_ROOT}%{apache_modules_dir}/ # #mkdir -p ${RPM_BUILD_ROOT}%{apache_conf_dir} #echo "#Here we load the 'mod_ngobjweb.so' module # #LoadModule ngobjweb_module %{apache_modules_dir}/mod_ngobjweb.so #" > ${RPM_BUILD_ROOT}%{apache_conf_dir}/ngobjweb.conf # rm -f ${RPM_BUILD_ROOT}%{prefix}/Tools/rss2plist1 # rm -f ${RPM_BUILD_ROOT}%{prefix}/Tools/rss2plist2 # rm -f ${RPM_BUILD_ROOT}%{prefix}/Tools/rssparse # rm -f ${RPM_BUILD_ROOT}%{prefix}/Tools/testqp # rm -fr ${RPM_BUILD_ROOT}%{prefix}/man/ # ****************************** clean ******************************** %clean rm -fr ${RPM_BUILD_ROOT} # ****************************** files ******************************** %files xml %defattr(-,root,root,-) %{_libdir}/libDOM*.so.%{sope_version}* %{_libdir}/libSaxObjC*.so.%{sope_version}* %{_libdir}/libXmlRpc*.so.%{sope_version}* %{_libdir}/GNUstep/SaxDrivers-%{sope_version} %files xml-devel %defattr(-,root,root,-) %{_includedir}/DOM %{_includedir}/SaxObjC %{_includedir}/XmlRpc %{_libdir}/libDOM*.so %{_libdir}/libSaxObjC*.so %{_libdir}/libXmlRpc*.so %files sbjson %defattr(-,root,root,-) %{_libdir}/libSBJson.so.%{sbjson_major_version}* %files sbjson-devel %defattr(-,root,root,-) %{_includedir}/SBJson %{_libdir}/libSBJson.so %files core %defattr(-,root,root,-) %{_libdir}/libEOControl*.so.%{sope_version}* %{_libdir}/libNGExtensions*.so.%{sope_version}* %{_libdir}/libNGStreams*.so.%{sope_version}* %files core-devel %defattr(-,root,root,-) %{_includedir}/EOControl %{_includedir}/NGExtensions %{_includedir}/NGStreams %{_libdir}/libEOControl*.so %{_libdir}/libNGExtensions*.so %{_libdir}/libNGStreams*.so %files mime %defattr(-,root,root,-) %{_libdir}/libNGMime*.so.%{sope_version}* %files mime-devel %defattr(-,root,root,-) %{_includedir}/NGImap4 %{_includedir}/NGMail %{_includedir}/NGMime %{_libdir}/libNGMime*.so %files appserver %defattr(-,root,root,-) %{_libdir}/libNGObjWeb*.so.%{sope_version}* %{_libdir}/libWEExtensions*.so.%{sope_version}* %{_libdir}/libWOExtensions*.so.%{sope_version}* %{_libdir}/GNUstep/Libraries/Resources/NGObjWeb/* %{_libdir}/GNUstep/SoProducts-%{sope_version} %{_libdir}/GNUstep/WOxElemBuilders-%{sope_version} %files appserver-devel %defattr(-,root,root,-) %{_bindir}/wod %{_includedir}/NGHttp %{_includedir}/NGObjWeb %{_includedir}/WEExtensions %{_includedir}/WOExtensions %{_libdir}/libNGObjWeb*.so %{_libdir}/libWEExtensions*.so %{_libdir}/libWOExtensions*.so %if 0%{?rhel} >= 7 %{_libdir}/GNUstep/Makefiles %else %{_datadir}/GNUstep/Makefiles %endif %files ldap %defattr(-,root,root,-) %{_libdir}/libNGLdap*.so.%{sope_version}* %files ldap-devel %defattr(-,root,root,-) %{_includedir}/NGLdap %{_libdir}/libNGLdap*.so %files gdl1 %defattr(-,root,root,-) %{_bindir}/connect-EOAdaptor %{_bindir}/load-EOAdaptor %{_libdir}/libGDLAccess*.so.%{sope_version}* %files gdl1-postgresql %defattr(-,root,root,-) %{_libdir}/GNUstep/GDLAdaptors-%{sope_version}/PostgreSQL.gdladaptor %if %oracle_support %files gdl1-oracle %defattr(-,root,root,-) %{_libdir}/GNUstep/GDLAdaptors-%{sope_version}/Oracle8.gdladaptor %endif %files gdl1-mysql %defattr(-,root,root,-) %{_libdir}/GNUstep/GDLAdaptors-%{sope_version}/MySQL.gdladaptor #%files gdl1-sqlite3 #%defattr(-,root,root,-) #%{_libdir}/GNUstep/GDLAdaptors-%{sope_version}/SQLite3.gdladaptor %files gdl1-devel %defattr(-,root,root,-) %{_includedir}/GDLAccess %{_libdir}/libGDLAccess*.so #%files -n mod_ngobjweb #%defattr(-,root,root,-) #%{apache_modules_dir}/mod_ngobjweb.so #%config %{apache_conf_dir}/ngobjweb.conf # ********************************* changelog ************************* %changelog * Thu Aug 02 2012 Jean Raby - Deduce the oracle lib path from the build arch * Mon Dec 05 2011 Jean Raby - updated for oracle-instantclient11.2 * Fri Oct 14 2011 Wolfgang Sourdeau - adapted to gnustep 1.23 packages, which now uses FHS nomenclature * Fri Jan 23 2009 Ludovic Marcotte - we no longer build mod_ngobjweb * Wed Jul 18 2007 Wolfgang Sourdeau - repackaged for CentOS 5 and GNUstep * Mon Jul 10 2006 Frank Reppin - adjust requires on new libfoundation * Fri Sep 16 2005 Frank Reppin - added WEPrototype and its lib to appserver/appserver-devel * Fri Aug 26 2005 Frank Reppin - added sope-gdl1-sqlite3 (as comment) * Thu Apr 21 2005 Frank Reppin - added sope-gdl1-mysql * Tue Mar 22 2005 Frank Reppin - added GDLContentStore to sope-gdl1 - reworked descriptions regarding GDLContentStore - added new subpackage sope-gdl1-tools - sope-gdl1 now depends on sope-xml due to -lDOM -lSaxObjC used by GDLContentStore * Fri Jan 28 2005 Frank Reppin - reworked dependencies - deal with ld.so.conf in (post|preun) of appserver rather than core * Tue Jan 25 2005 Frank Reppin - fix for OGo Bug #1192 * Tue Jan 11 2005 Frank Reppin - reworked all summaries and descriptions (taken from Debian control to be honest :>) * Tue Nov 16 2004 Frank Reppin - s^4.5^%{sope_version}^g everywhere bc .rpmmacros knows the current version we build for * Sat Nov 06 2004 Helge Hess - updated to 4.5 version * Thu Sep 09 2004 Frank Reppin - initial build SOPE/sope-ldap/0000755000000000000000000000000015004363604012207 5ustar rootrootSOPE/sope-ldap/GNUmakefile0000644000000000000000000000041015004363604014254 0ustar rootroot# GNUstep makefile include ../config.make include $(GNUSTEP_MAKEFILES)/common.make PACKAGE_NAME=sope-ldap VERSION=4.5.0 SUBPROJECTS = \ NGLdap include $(GNUSTEP_MAKEFILES)/aggregate.make # package macosx-pkg :: all ../maintenance/make-osxpkg.sh sope-ldap SOPE/sope-ldap/NGLdap/0000755000000000000000000000000015004363604013314 5ustar rootrootSOPE/sope-ldap/NGLdap/NGLdapSearchResultEnumerator.h0000644000000000000000000000310715004363604021162 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGLdapSearchResultEnumerator_H__ #define __NGLdapSearchResultEnumerator_H__ #import #import /* NGLdapSearchResultEnumerator TODO: document */ @class NGLdapConnection; @interface NGLdapSearchResultEnumerator : NSEnumerator { @public // TODO: required to be public?! NGLdapConnection *connection; void *handle; int msgid; NSTimeInterval timeout; NSTimeInterval startTime; unsigned index; } - (id)initWithConnection:(NGLdapConnection *)_con messageID:(int)_mid; /* accessors */ - (int)messageID; - (NSTimeInterval)duration; - (unsigned)index; - (void)setTimeout:(NSTimeInterval)_value; - (NSTimeInterval)timeout; /* operations */ - (void)cancel; @end #endif /* __NGLdapSearchResultEnumerator_H__ */ SOPE/sope-ldap/NGLdap/NGLdapFileManager.h0000644000000000000000000000623615004363604016674 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGLdapFileManager_H__ #define __NGLdapFileManager_H__ #import #import #import @class NSString, NSDictionary, NSData, NSArray, NSURL; @class NGLdapConnection; @interface NGLdapFileManager : NGFileManager { NGLdapConnection *connection; NSString *rootDN; NSString *currentDN; NSString *currentPath; } - (id)initWithURLString:(NSString *)_url; - (id)initWithURL:(id)_url; - (id)initWithHostName:(NSString *)_host port:(int)_port bindDN:(NSString *)_login credentials:(NSString *)_pwd rootDN:(NSString *)_rootDN; /* operations */ - (BOOL)changeCurrentDirectoryPath:(NSString *)_path; - (NSString *)currentDirectoryPath; - (NSArray *)directoryContentsAtPath:(NSString *)_path; - (NSArray *)subpathsAtPath:(NSString *)_path; - (NSDictionary *)fileAttributesAtPath:(NSString *)_path traverseLink:(BOOL)_fl; /* determine access */ - (BOOL)fileExistsAtPath:(NSString *)_path isDirectory:(BOOL *)_isDir; - (BOOL)fileExistsAtPath:(NSString *)_path; - (BOOL)isReadableFileAtPath:(NSString *)_path; - (BOOL)isWritableFileAtPath:(NSString *)_path; - (BOOL)isExecutableFileAtPath:(NSString *)_path; - (BOOL)isDeletableFileAtPath:(NSString *)_path; /* reading contents */ - (BOOL)contentsEqualAtPath:(NSString *)_path1 andPath:(NSString *)_path2; - (NSData *)contentsAtPath:(NSString *)_path; /* modifications */ - (BOOL)removeFileAtPath:(NSString *)_path handler:(id)handler; - (BOOL)copyPath:(NSString *)_source toPath:(NSString *)_destination handler:(id)_handler; - (BOOL)movePath:(NSString *)_source toPath:(NSString *)_destination handler:(id)_handler; - (BOOL)linkPath:(NSString *)_source toPath:(NSString *)_destination handler:(id)_handler; - (BOOL)createFileAtPath:(NSString *)path contents:(NSData *)contents attributes:(NSDictionary *)attributes; /* internals */ - (NGLdapConnection *)ldapConnection; - (NSString *)dnForPath:(NSString *)_path; - (NSString *)pathForDN:(NSString *)_dn; @end @class EODataSource; @interface NGLdapFileManager(ExtendedFileManager) < NGFileManagerDataSources > /* feature check */ - (BOOL)supportsVersioningAtPath:(NSString *)_path; - (BOOL)supportsLockingAtPath:(NSString *)_path; - (BOOL)supportsFolderDataSourceAtPath:(NSString *)_path; /* writing */ - (BOOL)writeContents:(NSData *)_content atPath:(NSString *)_path; @end #endif /* __NGLdapFileManager_H__ */ SOPE/sope-ldap/NGLdap/NGLdapModification.m0000644000000000000000000000371615004363604017134 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLdapModification.h" #include "NGLdapAttribute.h" #include "common.h" @implementation NGLdapModification + (id)addModification:(NGLdapAttribute *)_attribute { return [[[self alloc] initWithOperation:NGLdapAddAttribute attribute:_attribute] autorelease]; } + (id)replaceModification:(NGLdapAttribute *)_attribute { return [[[self alloc] initWithOperation:NGLdapReplaceAttribute attribute:_attribute] autorelease]; } + (id)deleteModification:(NGLdapAttribute *)_attribute { return [[[self alloc] initWithOperation:NGLdapDeleteAttribute attribute:_attribute] autorelease]; } - (id)initWithOperation:(int)_op attribute:(NGLdapAttribute *)_attribute { self->operation = _op; self->attribute = [_attribute retain]; return self; } - (void)dealloc { [self->attribute release]; [super dealloc]; } - (int)operation { return self->operation; } - (NGLdapAttribute *)attribute { return self->attribute; } - (NSString *)description { return [NSString stringWithFormat:@"%@ : self->attribute %@ operation %d", [super description], self->attribute, self->operation]; } @end /* NGLdapModification */ SOPE/sope-ldap/NGLdap/NGLdapConnection+Private.h0000644000000000000000000000225115004363604020220 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGLdapConnection_Private_H__ #define __NGLdapConnection_Private_H__ #include "NGLdapConnection.h" @class NSException, NSString, NSDictionary; @interface NGLdapConnection(Privates) - (void *)ldapHandle; - (NSException *)_exceptionForErrorCode:(int)_err operation:(NSString *)_operation userInfo:(NSDictionary *)_ui; @end /* NGLdapConnection(Privates) */ #endif /* __NGLdapConnection_H__ */ SOPE/sope-ldap/NGLdap/NGLdapSearchResultEnumerator.m0000644000000000000000000001765415004363604021203 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLdapSearchResultEnumerator.h" #include "NGLdapConnection+Private.h" #include "NGLdapAttribute.h" #include "NGLdapEntry.h" #include "common.h" #include @implementation NGLdapSearchResultEnumerator - (id)initWithConnection:(NGLdapConnection *)_con messageID:(int)_mid { if ((self = [super init]) != nil) { self->connection = [_con retain]; self->handle = [_con ldapHandle]; self->msgid = _mid; // TODO: -timeIntervalSince1970 deprecated on Cocoa self->startTime = [[NSDate date] timeIntervalSince1970]; } return self; } - (id)init { return [self initWithConnection:NULL messageID:-1]; } - (void)dealloc { [self->connection release]; [super dealloc]; } /* state */ - (int)messageID { return self->msgid; } - (NSTimeInterval)duration { // TODO: -timeIntervalSince1970 deprecated on Cocoa return [[NSDate date] timeIntervalSince1970] - self->startTime; } - (unsigned)index { return self->index; } - (void)setTimeout:(NSTimeInterval)_value { self->timeout = _value; } - (NSTimeInterval)timeout { return self->timeout; } /* enumerator */ - (void)cancel { if (self->handle) { ldap_abandon(self->handle, self->msgid); self->handle = NULL; [self->connection release]; self->connection = nil; } } - (NSArray *)_attributesFromResult:(LDAPMessage *)result { NSMutableArray *attributes; char *attr; BerElement *ber; attributes = [[NSMutableArray alloc] initWithCapacity:32]; for (attr = ldap_first_attribute(self->handle, result, &ber); attr != NULL; free(attr), attr = ldap_next_attribute(self->handle, result, ber)) { NSString *key; NGLdapAttribute *attribute; struct berval **values; unsigned valueCount; NSArray *ovalues; if (!(key = [[NSString alloc] initWithCString:attr])) /* missing attribute name */ continue; /* process values */ if ((values = ldap_get_values_len(self->handle, result, attr)) == NULL) { ovalues = [[NSArray alloc] init]; } else if ((valueCount = ldap_count_values_len(values)) == 1) { NSData *value; value = [[NSData alloc] initWithBytes:values[0]->bv_val length:values[0]->bv_len]; ovalues = [[NSArray alloc] initWithObjects:&value count:1]; [value release]; } else { NSMutableArray *a; int j; a = [[NSMutableArray alloc] initWithCapacity:valueCount]; for (j = 0; values[j]; j++) { NSData *data; data = [[NSData alloc] initWithBytes:values[j]->bv_val length:values[j]->bv_len]; [a addObject:data]; [data release]; } ovalues = [a copy]; [a release]; } if (values) { ldap_value_free_len(values); values = NULL; } /* create attribute */ attribute = [[NGLdapAttribute alloc] initWithAttributeName:key values:ovalues]; [key release]; key = nil; [ovalues release]; ovalues = nil; [attributes addObject:attribute]; [attribute release]; } #if 0 if (first) { ldap_memfree(first); } #endif if (ber) { ber_free(ber, 0); } return attributes; } - (id)nextObject { int res; struct timeval to; struct timeval *top; LDAPMessage *msg; id record; if (self->handle == NULL) return nil; msg = NULL; record = nil; top = NULL; if (self->timeout > 0) { to.tv_sec = self->timeout; to.tv_usec = (long)(self->timeout * 1000.0) - (to.tv_sec * 1000); top = &to; } res = ldap_result(self->handle, self->msgid, 0, top, &msg); if (res <= 0 || msg == NULL) { int err; ldap_get_option(self->handle, LDAP_OPT_RESULT_CODE, &err); NSLog(@"Fatal LDAP error during ldap_result: %s", ldap_err2string(err)); return nil; } switch(res) { #if defined(LDAP_RES_SEARCH_REFERENCE) case LDAP_RES_SEARCH_REFERENCE: { int rres; char **rptr = NULL; LDAPControl **ctrl = NULL; rres = ldap_parse_reference(self->handle, msg, &rptr, &ctrl, 0 /* don't free msg */); if (rres == LDAP_SUCCESS) { } else { /* error */ NSLog(@"%s: couldn't parse result reference ..", __PRETTY_FUNCTION__); } NSLog(@"ERROR(%s): does not support result references yet ..", __PRETTY_FUNCTION__); if (rptr != NULL) ldap_value_free(rptr); if (ctrl != NULL) ldap_controls_free(ctrl); break; } #endif case LDAP_RES_SEARCH_ENTRY: { int resultCount; if ((resultCount = ldap_count_entries(self->handle, msg)) == -1) { /* failed */ int err; err = ldap_result2error(self->handle, msg, 1 /* free msg */); [[self->connection _exceptionForErrorCode:err operation:@"count-fetch" userInfo:nil] raise]; return nil; } if (resultCount == 1) { LDAPMessage *result; NSString *dn = nil; char *tmp; NSArray *attributes; if ((result = ldap_first_entry(self->handle, msg)) == NULL) { /* could not get entry */ [[self->connection _exceptionForErrorCode:resultCount operation:@"fetch" userInfo:nil] raise]; return nil; } /* get distinguished name */ if ((tmp = ldap_get_dn(self->handle, result)) != NULL) { // TODO: slow ..., somehow fix that. /* try UTF-8 (as per spec?) */ NS_DURING { dn = [[[NSString alloc] initWithUTF8String:tmp] autorelease]; } NS_HANDLER { fprintf(stderr, "Got exception %s while NSUTF8StringEncoding, " "use defaultCStringEncoding", [[localException description] cString]); dn = nil; } NS_ENDHANDLER; /* try system encoding (Latin-1 on libFoundation) */ if (dn == nil) // TODO: print a warning? dn = [[[NSString alloc] initWithCString:tmp] autorelease]; if (tmp != NULL) free(tmp); } /* get all attributes */ attributes = [self _attributesFromResult:result]; if (result != NULL) { // TODO: ldap_msgfree(result); // do not release result-msg ??? result = NULL; } record = [[NGLdapEntry alloc] initWithDN:dn attributes:attributes]; [attributes release]; attributes = nil; } else if (resultCount == 0) { /* no more results */ record = nil; } break; } case LDAP_RES_SEARCH_RESULT: self->handle = NULL; [self->connection release]; self->connection = nil; break; default: NSLog(@"NGLdap(%s): unexpected msg-code: %X", __PRETTY_FUNCTION__,res); break; } if (msg != NULL) ldap_msgfree(msg); if (record != nil) self->index++; return [record autorelease]; } /* description */ - (NSString *)description { NSMutableString *s; s = [NSMutableString stringWithCapacity:100]; [s appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; [s appendFormat:@" msgid=%i", [self messageID]]; [s appendFormat:@" duration=%.2fs", [self duration]]; [s appendFormat:@" index=%i", [self index]]; [s appendString:@">"]; return s; } @end /* LDAPResultEnumerator */ SOPE/sope-ldap/NGLdap/GNUmakefile0000644000000000000000000000303615004363604015370 0ustar rootroot# GNUstep makefile include ../../config.make include $(GNUSTEP_MAKEFILES)/common.make include ./Version ifneq ($(frameworks),yes) LIBRARY_NAME = libNGLdap else FRAMEWORK_NAME = NGLdap endif libNGLdap_PCH_FILE = common.h libNGLdap_HEADER_FILES_DIR = . libNGLdap_HEADER_FILES_INSTALL_DIR = /NGLdap libNGLdap_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION) libNGLdap_INSTALL_DIR=$(SOPE_SYSLIBDIR) libNGLdap_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION) libNGLdap_HEADER_FILES = \ NGLdap.h \ \ EOQualifier+LDAP.h \ NSString+DN.h \ NGLdapEntry.h \ NGLdapConnection.h \ NGLdapAttribute.h \ NGLdapModification.h \ NGLdapSearchResultEnumerator.h \ \ NGLdapURL.h \ NGLdapGlobalID.h \ NGLdapFileManager.h \ NGLdapDataSource.h \ libNGLdap_CORE_OBJC_FILES = \ EOQualifier+LDAP.m \ NSString+DN.m \ NGLdapAttribute.m \ NGLdapEntry.m \ NGLdapSearchResultEnumerator.m \ NGLdapModification.m \ NGLdapConnection.m \ NGLdapDataSource.m \ libNGLdap_OBJC_FILES = \ $(libNGLdap_CORE_OBJC_FILES) \ NGLdapURL.m \ NGLdapGlobalID.m \ NGLdapFileManager.m \ # framework support NGLdap_PCH_FILE = $(libNGLdap_PCH_FILE) NGLdap_HEADER_FILES = $(libNGLdap_HEADER_FILES) NGLdap_OBJC_FILES = $(libNGLdap_OBJC_FILES) # building -include GNUmakefile.preamble ifneq ($(FHS_INSTALL_ROOT),) GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include endif ifneq ($(frameworks),yes) include $(GNUSTEP_MAKEFILES)/library.make else include $(GNUSTEP_MAKEFILES)/framework.make endif -include GNUmakefile.postamble SOPE/sope-ldap/NGLdap/ChangeLog0000644000000000000000000002160615004363604015073 0ustar rootroot2012-12-20 Jean Raby * NGLdapconnection.h handle is now a LDAP* * NGLdapConnection.m (_reinit): ldap_initialize if provided with a ldap url * NGLdapConnection.m (_exceptionForErrorCode): replace body with ldap_err2str * NGLdapConnection.m (startTLS): raise an exception if ldap_start_tls_s fails Callers should be updated to do something useful with this exception. 2010-03-08 Ludovic Marcotte * Added password policy support when binding to the LDAP server or when changing passwords. 2009-08-13 Wolfgang Sourdeau * NGLdapEntry.m (-attributeWithName:): attribute names are now accessed in a case-insensitive way. 2009-04-02 Wolfgang Sourdeau * NGLdapConnection.m (useSSL,startTLS): new method enabling encryption on the LDAP connection. (v4.7.35) 2007-11-21 Helge Hess * NGLdapConnection.m: replaced some -cString calls with -UTF8String (v4.7.34) * NGLdapURL.m: removed local URL escaping and replaced it with NSString+misc (v4.7.33) * NSString+DN.m: removed cString based space-stripping function and replaced it with the method from NGExtensions (v4.7.32) 2007-07-23 Helge Hess * changed API to use NSTimeInterval, added missing getter methods (v4.7.31) 2007-07-23 Wolfgang Sourdeau * added methods to specify query time and size limits (OGo bug #1888) 2006-07-04 Helge Hess * use %p for pointer formats, fixed gcc 4.1 warnings, minor code cleanups (v4.5.30) 2006-05-16 Marcus Mueller * EOQualifier+LDAP.h: changed EOControl related includes into imports to enable compilation against MulleEOF (v4.5.29) 2006-01-30 Helge Hess * NGLdapConnection.m: set LDAP options prior performing a bind. Default to UTF-8 credentials (can be changed back to Latin1 using the LDAPUseLatin1Creds default). This should fix OGo bug #995 (v4.5.28) 2005-11-17 Helge Hess * NGLdapURL.m: properly include string.h to avoid a warning (v4.5.27) 2005-10-16 Helge Hess * v4.5.26 * NGLdapSearchResultEnumerator.m: minor code improvements 2005-10-16 Jean-Alexis Montignies * NGLdapSearchResultEnumerator.m: properly set microseconds field of timeout, added accessors for fetch-timeout (OGo bug #1588) 2005-08-27 Helge Hess * GNUmakefile: added PCH support (v4.5.25) 2005-08-16 Helge Hess * GNUmakefile, GNUmakefile.preamble: added OSX framework compilation (v4.5.24) 2005-04-25 Helge Hess * fixed gcc 4.0 warnings (v4.5.23) 2005-03-08 Helge Hess * NGLdapConnection.m: fixed not to do unauthenticated binds (related to OGo bug #957) (v4.5.22) 2004-12-14 Marcus Mueller * NGLdap.xcode: minor fixes and updated 2004-10-17 Helge Hess * GNUmakefile: include config.make if available (v4.3.21) 2004-09-22 Marcus Mueller * README.macosx: removed obsoleted documentation * NGLdap.xcode: adjusted several build parameters 2004-08-29 Helge Hess * added hack to install the project in FHS locations - the library, its headers, the tools and the resources will be installed in FHS_INSTALL_ROOT if specified (eg make FHS_INSTALL_ROOT=/usr/local) (v4.3.20) 2004-08-29 Marcus Mueller * NGLdap.xcode: new Xcode project 2004-08-20 Helge Hess * fixed for SOPE 3.3 directory layout (v4.3.19) * moved to sope-ldap * moved to SOPE 4.3 (v4.3.18) 2004-06-20 Florian G. Pflug * NGLdapConnection.m: added support for MS Active Directory, introduced three new defaults: LDAPInitialBindSpecific - YES means not to do anonymous binds, but instead use LDAPInitialBindDN, LDAPInitialBindPW for the initial bind. Two LDAP options are set (protocol version to LDAPv3 and disabled referrals). Finally "LDAP_PARTIAL_RESULTS" is accepted as a valid return code for successful searches. (v4.2.17) 2004-06-09 Helge Hess * GNUmakefile.preamble: added prebinding (v4.2.16) 2004-05-05 Marcus Mueller * GNUmakefile.preamble: added support for building with GNUSTEP_BUILD_DIR environment variable set for recent gnustep-make package. (v4.2.15) 2004-01-19 Helge Hess * NGLdapConnection.m: fixed various compile warnings with OpenLDAP v2 (v4.2.14) 2003-09-07 Marcus Mueller * v4.2.13 * EOQualifier+LDAP.m: define sel_eq for NeXT_RUNTIME * common.h: remove obsolete FoundationExt references 2003-07-28 Helge Hess * GNUmakefile.preamble: do not link against SASL library by default, you can still use the "sasl=yes" makefile parameter to enable compilation against the SASL library (required for some older LDAP libraries which do not link against SASL) 2003-07-18 Helge Hess * NGLdapConnection.m: replaced an indexOfString with rangeOfString (v4.2.12) Wed Apr 16 17:00:06 2003 Jan Reichmann * NGLdapConnection.m: move DN for login code in seperate method (v4.2.11) 2003-04-15 Helge Hess * NGLdapURL.m: small cleanups (v4.2.10) 2003-04-10 Helge Hess * GNUmakefile.preamble: added "nosasl" and "nossl" configuration parameters 2003-04-03 Helge Hess * GNUmakefile.preamble: added setting to compile against reentrant LDAP libraries * NGLdapConnection.m: added new LDAPLoginAttributeName default and a lot more debugging messages if LDAPDebugEnabled is on (v4.2.9) 2003-04-01 GNUstep User * v4.2.8 * common.h: compiles with GNUstep Base * NGLdapDataSource.m, NGLdapFileManager.m: do not use NSFileIdentifier constant (uses a string instead) * NGLdapAttribute.m, NSString+DN.m: replaced -indexOfString: calls with -rangeOfString 2003-01-20 Helge Hess * NGLdapFileManager.m: replaced a RETAIN macro (v4.2.7) 2003-01-07 Helge Hess * changes for improved compilation on MacOSX, replaced RETAIN macros with methods (v4.2.6) Fri Dec 27 10:55:32 2002 Helge Hess * NGLdapAttribute.m: moved UTF8/Latin1 string to NSString conversion to a centralized method (stringFromData) (v4.2.5) 2002-11-21 Helge Hess * NGLdapFileManager.m: made -dnForPath:, -pathForDn: and -ldapConnection public methods (v4.2.4) * NGLdapFileManager.m: added -initWithURL: to init filemanager using an NSURL object (v4.2.3) * moved ldapls, ldap2dsml tools to ../samples/ 2002-09-26 Helge Hess * removed all OpenLDAP v1 things not available in v2 anymore ... (v4.2.2) 2002-05-23 Helge Hess * moved from Skyrix-dev-42 repository to skyrix-core (v4.2.1) Thu Apr 25 15:37:57 2002 Helge Hess * NGLdapConnection.m: pass credentials as ISO-Latin-1 .. Wed Mar 6 13:29:28 CET 2002 Jan41 Reichmann * merge with SkyrixGreen Mon Jan 21 16:29:30 2002 Jan41 Reichmann * NGLdapAttribute.m: * NGLdapSearchResultEnumerator.m: Fixed UTF8 handling Wed Oct 24 12:46:58 2001 Helge Hess * changed various places to use UTF-8 instead of cString * updated to SKYRiXgreen Mon Aug 13 18:01:48 2001 Martin Hoerning * NGLdapSearchResultEnumerator.m: fixed RETAIN-BUG * NGLdapAttribute.m: fixed performance/BUGS * NGLdapConnection.m: repeared RETAIN-BUG, updated changes from SKYRiXgreen * NSString+DN.m: repaired free - BUG * NGLdapSearchResultEnumerator.m: repaired RETAIN bugs * NGLdapConnection.m/NSString+DN.m repaired RETAIN bugs Fri Aug 10 13:52:30 2001 Helge Hess * NGLdapFileManager.m: inherit from NGFileManager Mon Feb 26 17:03:38 2001 Helge Hess * NGLdapConnection.m: use port 389 if none is specified Mon Jan 29 15:38:23 2001 Helge Hess * NGLdapFileManager.m: added (non-)support for trash-folder Fri Jan 19 16:15:57 2001 Helge Hess * NGLdapFileManager.m: added support for global-ids Thu Jan 18 17:08:50 2001 Helge Hess * NGLdapFileManager.m: use new FileManager protocols in NGExtensions Mon Dec 18 13:02:10 2000 Helge Hess * NGLdapEntry.m: added -valueForKey: Wed Nov 29 18:06:03 2000 Helge Hess * created ChangeLog SOPE/sope-ldap/NGLdap/common.h0000644000000000000000000000217615004363604014763 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGLdap_common_H__ #define __NGLdap_common_H__ #if USE_OWN_LIBLDAP # include # include # include #else # include # include #endif #import #include #include #endif /* __NGLdap_common_H__ */ SOPE/sope-ldap/NGLdap/NGLdapFileManager.m0000644000000000000000000004360215004363604016677 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLdapFileManager.h" #include "NGLdapConnection.h" #include "NGLdapEntry.h" #include "NGLdapAttribute.h" #include "NGLdapURL.h" #include "NSString+DN.h" #import #include "common.h" @implementation NGLdapFileManager static NSString *LDAPObjectClassKey = @"objectclass"; static NSArray *objectClassAttrs = nil; static NSArray *fileInfoAttrs = nil; + (void)_initCache { if (objectClassAttrs == nil) { objectClassAttrs = [[NSArray alloc] initWithObjects:&LDAPObjectClassKey count:1]; } if (fileInfoAttrs == nil) { fileInfoAttrs = [[NSArray alloc] initWithObjects: @"objectclass", @"createTimestamp", @"modifyTimestamp", @"creatorsName", @"modifiersName", nil]; } } - (id)initWithLdapConnection:(NGLdapConnection *)_con { // designated initializer if (_con == nil) { [self release]; return nil; } [[self class] _initCache]; if ((self = [super init])) { self->connection = [_con retain]; } return self; } - (id)initWithHostName:(NSString *)_host port:(int)_port bindDN:(NSString *)_login credentials:(NSString *)_pwd rootDN:(NSString *)_rootDN { NGLdapConnection *ldap; ldap = [[NGLdapConnection alloc] initWithHostName:_host port:_port?_port:389]; if (ldap == nil) { [self release]; return nil; } ldap = [ldap autorelease]; if (![ldap bindWithMethod:@"simple" binddn:_login credentials:_pwd]) { NSLog(@"couldn't bind as DN '%@' with %@", _login, ldap); [self release]; return nil; } if ((self = [self initWithLdapConnection:ldap])) { if (_rootDN == nil) { /* check cn=config as available in OpenLDAP */ NSArray *nctxs; if ((nctxs = [self->connection namingContexts])) { if ([nctxs count] > 1) NSLog(@"WARNING: more than one naming context handled by server !"); if ([nctxs isNotEmpty]) _rootDN = [[nctxs objectAtIndex:0] lowercaseString]; } } if (_rootDN) { ASSIGNCOPY(self->rootDN, _rootDN); ASSIGNCOPY(self->currentDN, _rootDN); self->currentPath = @"/"; } } return self; } - (id)initWithURLString:(NSString *)_url { NGLdapURL *url; if ((url = [NGLdapURL ldapURLWithString:_url]) == nil) { /* couldn't parse URL */ [self release]; return nil; } return [self initWithHostName:[url hostName] port:[url port] bindDN:nil credentials:nil rootDN:[url baseDN]]; } - (id)initWithURL:(id)_url { return (![_url isKindOfClass:[NSURL class]]) ? [self initWithURLString:[_url stringValue]] : [self initWithURLString:[_url absoluteString]]; } - (void)dealloc { [self->connection release]; [self->rootDN release]; [self->currentDN release]; [self->currentPath release]; [super dealloc]; } /* internals */ - (NSString *)_rdnForPathComponent:(NSString *)_pathComponent { return _pathComponent; } - (NSString *)_pathComponentForRDN:(NSString *)_rdn { return _rdn; } - (NSString *)pathForDN:(NSString *)_dn { NSEnumerator *dnComponents; NSString *path; NSString *rdn; if (_dn == nil) return nil; _dn = [_dn lowercaseString]; if (![_dn hasSuffix:self->rootDN]) { /* DN is not rooted in this hierachy */ return nil; } /* cut of root */ _dn = [_dn substringToIndex:([_dn length] - [self->rootDN length])]; path = @"/"; dnComponents = [[_dn dnComponents] reverseObjectEnumerator]; while ((rdn = [dnComponents nextObject])) { NSString *pathComponent; pathComponent = [self _pathComponentForRDN:rdn]; path = [path stringByAppendingPathComponent:pathComponent]; } return path; } - (NGLdapConnection *)ldapConnection { return self->connection; } - (NSString *)dnForPath:(NSString *)_path { NSString *dn = nil; NSArray *pathComponents; unsigned i, count; if (![_path isAbsolutePath]) _path = [[self currentDirectoryPath] stringByAppendingPathComponent:_path]; if (![_path isNotEmpty]) return nil; NSAssert1([_path isAbsolutePath], @"path %@ is not an absolute path (after append to cwd) !", _path); NSAssert(self->rootDN, @"missing root DN !"); pathComponents = [_path pathComponents]; for (i = 0, count = [pathComponents count]; i < count; i++) { NSString *pathComponent; NSString *rdn; pathComponent = [pathComponents objectAtIndex:i]; if ([pathComponent isEqualToString:@"."]) continue; if (![pathComponent isNotEmpty]) continue; if ([pathComponent isEqualToString:@"/"]) { dn = self->rootDN; continue; } if ([pathComponent isEqualToString:@".."]) { dn = [dn stringByDeletingLastDNComponent]; continue; } rdn = [self _rdnForPathComponent:pathComponent]; dn = [dn stringByAppendingDNComponent:rdn]; } return [dn lowercaseString]; } /* accessors */ - (BOOL)changeCurrentDirectoryPath:(NSString *)_path { NSString *dn; NSString *path; if (![_path isNotEmpty]) return NO; if ((dn = [self dnForPath:_path]) == nil) return NO; if ((path = [self pathForDN:dn]) == nil) return NO; ASSIGNCOPY(self->currentDN, dn); ASSIGNCOPY(self->currentPath, path); return YES; } - (NSString *)currentDirectoryPath { return self->currentPath; } - (NSArray *)directoryContentsAtPath:(NSString *)_path { NSString *dn; NSEnumerator *e; NSMutableArray *rdns; NGLdapEntry *entry; if ((dn = [self dnForPath:_path]) == nil) return nil; e = [self->connection flatSearchAtBaseDN:dn qualifier:nil attributes:objectClassAttrs]; if (e == nil) return nil; rdns = nil; while ((entry = [e nextObject])) { if (rdns == nil) rdns = [NSMutableArray arrayWithCapacity:128]; [rdns addObject:[entry rdn]]; } return [[rdns copy] autorelease]; } - (NSArray *)subpathsAtPath:(NSString *)_path { NSString *dn; NSEnumerator *e; NSMutableArray *paths; NGLdapEntry *entry; if ((dn = [self dnForPath:_path]) == nil) return nil; _path = [self pathForDN:dn]; e = [self->connection deepSearchAtBaseDN:dn qualifier:nil attributes:objectClassAttrs]; if (e == nil) return nil; paths = nil; while ((entry = [e nextObject])) { NSString *path; NSString *sdn; sdn = [entry dn]; if ((path = [self pathForDN:sdn]) == nil) { NSLog(@"got no path for dn '%@' ..", sdn); continue; } if ([path hasPrefix:_path]) path = [path substringFromIndex:[_path length]]; if (paths == nil) paths = [NSMutableArray arrayWithCapacity:128]; [paths addObject:path]; } return [[paths copy] autorelease]; } - (NSDictionary *)fileAttributesAtPath:(NSString *)_path traverseLink:(BOOL)_fl { NSString *dn; NGLdapEntry *entry; NGLdapAttribute *attr; id keys[10]; id vals[10]; short count; if ((dn = [self dnForPath:_path]) == nil) return nil; entry = [self->connection entryAtDN:dn attributes:fileInfoAttrs]; if (entry == nil) return nil; count = 0; if ((attr = [entry attributeWithName:@"modifytimestamp"])) { keys[count] = NSFileModificationDate; vals[count] = [[attr stringValueAtIndex:0] ldapTimestamp]; count++; } if ((attr = [entry attributeWithName:@"modifiersname"])) { keys[count] = NSFileOwnerAccountName; vals[count] = [[attr allStringValues] componentsJoinedByString:@","]; count++; } if ((attr = [entry attributeWithName:@"creatorsname"])) { keys[count] = @"NSFileCreatorAccountName"; vals[count] = [[attr allStringValues] componentsJoinedByString:@","]; count++; } if ((attr = [entry attributeWithName:@"createtimestamp"])) { keys[count] = @"NSFileCreationDate"; vals[count] = [[attr stringValueAtIndex:0] ldapTimestamp]; count++; } if ((attr = [entry attributeWithName:@"objectclass"])) { keys[count] = @"LDAPObjectClasses"; vals[count] = [attr allStringValues]; count++; } keys[count] = @"NSFileIdentifier"; if ((vals[count] = [entry dn])) count++; keys[count] = NSFilePath; if ((vals[count] = _path)) count++; keys[count] = NSFileName; if ((vals[count] = [self _pathComponentForRDN:[dn lastDNComponent]])) count++; return [NSDictionary dictionaryWithObjects:vals forKeys:keys count:count]; } /* determine access */ - (BOOL)fileExistsAtPath:(NSString *)_path { return [self fileExistsAtPath:_path isDirectory:NULL]; } - (BOOL)fileExistsAtPath:(NSString *)_path isDirectory:(BOOL *)_isDir { NSString *dn; NGLdapEntry *entry; if ((dn = [self dnForPath:_path]) == nil) return NO; entry = [self->connection entryAtDN:dn attributes:objectClassAttrs]; if (entry == nil) return NO; if (_isDir) { NSEnumerator *e; /* is-dir based on child-availablitiy */ e = [self->connection flatSearchAtBaseDN:dn qualifier:nil attributes:objectClassAttrs]; *_isDir = [e nextObject] ? YES : NO; } return YES; } - (BOOL)isReadableFileAtPath:(NSString *)_path { return [self fileExistsAtPath:_path]; } - (BOOL)isWritableFileAtPath:(NSString *)_path { return [self fileExistsAtPath:_path]; } - (BOOL)isExecutableFileAtPath:(NSString *)_path { return NO; } - (BOOL)isDeletableFileAtPath:(NSString *)_path { return [self fileExistsAtPath:_path]; } /* reading contents */ - (BOOL)contentsEqualAtPath:(NSString *)_path1 andPath:(NSString *)_path2 { NSString *dn1, *dn2; NGLdapEntry *e1, *e2; if ((dn1 = [self dnForPath:_path1]) == nil) return NO; if ((dn2 = [self dnForPath:_path2]) == nil) return NO; if ([dn1 isEqualToString:dn2]) /* same DN */ return YES; e1 = [self->connection entryAtDN:dn1 attributes:nil]; e2 = [self->connection entryAtDN:dn2 attributes:nil]; return [e1 isEqual:e2]; } - (NSData *)contentsAtPath:(NSString *)_path { /* generate LDIF for record */ NSString *dn; NGLdapEntry *entry; if ((dn = [self dnForPath:_path]) == nil) return nil; entry = [self->connection entryAtDN:dn attributes:nil]; if (entry == nil) return nil; return [[entry ldif] dataUsingEncoding:NSUTF8StringEncoding]; } /* modifications */ - (NSDictionary *)_errDictForPath:(NSString *)_path toPath:(NSString *)_dest dn:(NSString *)_dn reason:(NSString *)_reason { id keys[6]; id values[6]; short count; count = 0; if (_path) { keys[count] = @"Path"; values[count] = _path; count++; } if (_dest) { keys[count] = @"ToPath"; values[count] = _dest; count++; } if (_reason) { keys[count] = @"Error"; values[count] = _reason; count++; } if (_dn) { keys[count] = @"dn"; values[count] = _dn; count++; keys[count] = @"ldap"; values[count] = self->connection; count++; } return [NSDictionary dictionaryWithObjects:values forKeys:keys count:count]; } - (BOOL)removeFileAtPath:(NSString *)_path handler:(id)_fhandler { NSString *dn; [_fhandler fileManager:(id)self willProcessPath:_path]; if ((dn = [self dnForPath:_path]) == nil) { if (_fhandler) { NSDictionary *errDict; errDict = [self _errDictForPath:_path toPath:nil dn:nil reason:@"couldn't map path to LDAP dn"]; if ([_fhandler fileManager:(id)self shouldProceedAfterError:errDict]) return YES; } return NO; } /* should delete sub-entries first ... */ /* delete entry */ if (![self->connection removeEntryWithDN:dn]) { if (_fhandler) { NSDictionary *errDict; errDict = [self _errDictForPath:_path toPath:nil dn:dn reason:@"couldn't remove LDAP entry"]; if ([_fhandler fileManager:(id)self shouldProceedAfterError:errDict]) return YES; } return NO; } return YES; } - (BOOL)copyPath:(NSString *)_path toPath:(NSString *)_destination handler:(id)_fhandler { NGLdapEntry *e; NSString *fromDN, *toDN, *toRDN; [_fhandler fileManager:(id)self willProcessPath:_path]; if ((fromDN = [self dnForPath:_path]) == nil) { if (_fhandler) { NSDictionary *errDict; errDict = [self _errDictForPath:_path toPath:_destination dn:nil reason:@"couldn't map source path to LDAP dn"]; if ([_fhandler fileManager:(id)self shouldProceedAfterError:errDict]) return YES; } return NO; } /* split destination. 'toDN' is the target 'directory', 'toRDN' the name of the target 'file' */ toDN = [self dnForPath:_destination]; toRDN = [toDN lastDNComponent]; toDN = [toDN stringByDeletingLastDNComponent]; if ((toDN == nil) || (toRDN == nil)) { if (_fhandler) { NSDictionary *errDict; errDict = [self _errDictForPath:_path toPath:_destination dn:fromDN reason:@"couldn't map destination path to LDAP dn"]; if ([_fhandler fileManager:(id)self shouldProceedAfterError:errDict]) return YES; } return NO; } /* process record */ if ((e = [self->connection entryAtDN:fromDN attributes:nil]) == nil) { if (_fhandler) { NSDictionary *errDict; errDict = [self _errDictForPath:_path toPath:_destination dn:fromDN reason:@"couldn't load source LDAP record"]; if ([_fhandler fileManager:(id)self shouldProceedAfterError:errDict]) return YES; } return NO; } else { /* create new record with the attributes of the old one */ NGLdapEntry *newe; NSArray *attrs; attrs = [[e attributes] allValues]; newe = [[NGLdapEntry alloc] initWithDN:toDN attributes:attrs]; newe = [newe autorelease]; /* insert record in target space */ if (![self->connection addEntry:newe]) { /* insert failed */ if (_fhandler) { NSDictionary *errDict; errDict = [self _errDictForPath:_path toPath:_destination dn:toDN reason:@"couldn't insert LDAP record in target dn"]; if ([_fhandler fileManager:(id)self shouldProceedAfterError:errDict]) return YES; } return NO; } } /* should process children ? */ return YES; } - (BOOL)movePath:(NSString *)_path toPath:(NSString *)_destination handler:(id)_fhandler { /* needs to invoke a modrdn operation */ [_fhandler fileManager:(id)self willProcessPath:_path]; return NO; } - (BOOL)linkPath:(NSString *)_path toPath:(NSString *)_destination handler:(id)_fhandler { /* LDAP doesn't support links .. */ [_fhandler fileManager:(id)self willProcessPath:_path]; return NO; } - (BOOL)createFileAtPath:(NSString *)path contents:(NSData *)contents attributes:(NSDictionary *)attributes { return NO; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:64]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if (self->rootDN) [ms appendFormat:@" root=%@", self->rootDN]; if (self->currentDN && ![self->currentDN isEqualToString:self->rootDN]) [ms appendFormat:@" cwd=%@", self->currentDN]; if (self->connection) [ms appendFormat:@" ldap=%@", self->connection]; [ms appendString:@">"]; return ms; } @end /* NGLdapFileManager */ #include #include @implementation NGLdapFileManager(ExtendedFileManager) /* feature check */ - (BOOL)supportsVersioningAtPath:(NSString *)_path { return NO; } - (BOOL)supportsLockingAtPath:(NSString *)_path { return NO; } - (BOOL)supportsFolderDataSourceAtPath:(NSString *)_path { return YES; } /* writing */ - (BOOL)writeContents:(NSData *)_content atPath:(NSString *)_path { /* should decode LDIF and store at path .. */ return NO; } /* datasources (work on folders) */ - (EODataSource *)dataSourceAtPath:(NSString *)_path { NGLdapDataSource *ds; NSString *dn; if ((dn = [self dnForPath:_path]) == nil) /* couldn't get DN for specified path .. */ return nil; ds = [[NGLdapDataSource alloc] initWithLdapConnection:self->connection searchBase:dn]; return [ds autorelease]; } - (EODataSource *)dataSource { return [self dataSourceAtPath:[self currentDirectoryPath]]; } /* global-IDs */ - (EOGlobalID *)globalIDForPath:(NSString *)_path { NSString *dn; NGLdapGlobalID *gid; if ((dn = [self dnForPath:_path]) == nil) return nil; gid = [[NGLdapGlobalID alloc] initWithHost:[self->connection hostName] port:[self->connection port] dn:dn]; return [gid autorelease]; } - (NSString *)pathForGlobalID:(EOGlobalID *)_gid { NGLdapGlobalID *gid; if (![_gid isKindOfClass:[NGLdapGlobalID class]]) return nil; gid = (NGLdapGlobalID *)_gid; /* check whether host&port is correct */ if (![[self->connection hostName] isEqualToString:[gid host]]) return nil; if (!([self->connection port] == [gid port])) return nil; return [self pathForDN:[gid dn]]; } /* trash */ - (BOOL)supportsTrashFolderAtPath:(NSString *)_path { return NO; } - (NSString *)trashFolderForPath:(NSString *)_path { return nil; } @end /* NGLdapFileManager(ExtendedFileManager) */ SOPE/sope-ldap/NGLdap/NGLdapEntry.m0000644000000000000000000001314015004363604015620 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG Copyright (C) 2012 Inverse inc. This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLdapEntry.h" #include "NGLdapAttribute.h" #include "NSString+DN.h" #import #include "common.h" @implementation NGLdapEntry - (id)initWithDN:(NSString *)_dn attributes:(NSArray *)_attrs { _dn = [_dn lowercaseString]; self->dn = [[[_dn dnComponents] componentsJoinedByString:@","] copy]; self->attributes = _attrs; [self->attributes retain]; return self; } - (id)init { [self release]; return nil; } - (void)dealloc { [self->attributes release]; [self->dn release]; [super dealloc]; } /* distinguished name */ - (NSString *)dn { return self->dn; } - (NSString *)rdn { return [self->dn lastDNComponent]; } /* class */ - (NSArray *)objectClasses { NGLdapAttribute *a; a = [self attributeWithName:@"objectclass"]; return [[a allStringValues] sortedArrayUsingSelector:@selector(compare:)]; } /* attributes */ - (unsigned)count { return [self->attributes count]; } - (NSArray *)attributeNames { NSMutableArray *ma; NSArray *a; NSEnumerator *e; NGLdapAttribute *attr; ma = [[NSMutableArray alloc] initWithCapacity:[self->attributes count]]; e = [self->attributes objectEnumerator]; while ((attr = [e nextObject])) [ma addObject:[attr attributeName]]; a = [ma copy]; [ma release]; return [a autorelease]; } - (NSDictionary *)attributes { NSMutableDictionary *md; NSDictionary *d; NSEnumerator *e; NGLdapAttribute *a; md = [[NSMutableDictionary alloc] initWithCapacity:[self->attributes count]]; e = [self->attributes objectEnumerator]; while ((a = [e nextObject])) [md setObject:a forKey:[a attributeName]]; d = [md copy]; [md release]; return [d autorelease]; } - (NGLdapAttribute *)attributeWithName:(NSString *)_name { NSEnumerator *e; NGLdapAttribute *a; NSString *upperName; if (_name == nil) return nil; upperName = [_name uppercaseString]; e = [self->attributes objectEnumerator]; while ((a = [e nextObject])) { if ([[[a attributeName] uppercaseString] isEqualToString:upperName]) return a; } return nil; } - (NGLdapAttribute *)attributeWithName:(NSString *)_name language:(NSString *)_language { NSEnumerator *e; NGLdapAttribute *a; NGLdapAttribute *awl, *al; if (_language == nil) return [self attributeWithName:_name]; awl = al = nil; e = [self->attributes objectEnumerator]; while ((a = [e nextObject])) { if ([[a attributeBaseName] isEqualToString:_name]) { NSString *lang; if (al == nil) al = a; if ((lang = [a langSubtype])) { if ([lang isEqualToString:_language]) return a; } else { awl = a; } } } if (awl) return awl; if (al) return al; return nil; } /* LDIF */ - (NSString *)ldif { NSMutableString *ms; NSEnumerator *names; NSString *cname; ms = [NSMutableString stringWithCapacity:256]; /* add DN to LDIF */ [ms appendString:@"DN: "]; [ms appendString:[self dn]]; [ms appendString:@"\n"]; /* add attributes */ names = [[self attributeNames] objectEnumerator]; while ((cname = [names nextObject])) { NGLdapAttribute *attr; if ((attr = [self attributeWithName:cname])) { NSEnumerator *values; NSString *value; values = [attr stringValueEnumerator]; while ((value = [values nextObject])) { [ms appendString:cname]; [ms appendString:@": "]; [ms appendString:value]; [ms appendString:@"\n"]; } } } return ms; } /* key-value coding */ - (id)valueForKey:(NSString *)_key { return [self attributeWithName:_key]; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { return [[[self class] alloc] initWithDN:self->dn attributes:self->attributes]; } /* description */ - (NSString *)description { NSMutableString *s; s = [NSMutableString stringWithCapacity:100]; [s appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; [s appendFormat:@" dn='%@'", [self dn]]; [s appendString:@" attrs="]; [s appendString:[[self attributes] description]]; [s appendString:@">"]; return s; } - (NSMutableDictionary *) asDictionary { NSMutableDictionary *ldapRecord; NSDictionary *ldapAttributes; NSArray *keys; NSString *key; NSUInteger count, max; id value; ldapAttributes = [self attributes]; keys = [ldapAttributes allKeys]; max = [keys count]; ldapRecord = [NSMutableDictionary dictionaryWithCapacity: max]; for (count = 0; count < max; count++) { key = [keys objectAtIndex: count]; value = [[ldapAttributes objectForKey: key] asArrayOrString]; if (!value) value = [[[ldapAttributes objectForKey: key] allValues] lastObject]; if (value) [ldapRecord setObject: value forKey: [key lowercaseString]]; } return ldapRecord; } @end /* NGLdapEntry */ SOPE/sope-ldap/NGLdap/NGLdapAttribute.h0000644000000000000000000000351315004363604016460 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG Copyright (C) 2012 Inverse inc. This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGLdapAttribute_H__ #define __NGLdapAttribute_H__ #import @class NSString, NSArray, NSData, NSEnumerator; @interface NGLdapAttribute : NSObject < NSCopying > { NSString *name; NSArray *values; BOOL didChange; } - (id)initWithAttributeName:(NSString *)_name; - (id)initWithAttributeName:(NSString *)_name values:(NSArray *)_values; /* attribute name operations */ - (NSString *)attributeName; + (NSString *)baseNameOfAttributeName:(NSString *)_attrName; - (NSString *)attributeBaseName; + (NSArray *)subtypesOfAttributeName:(NSString *)_attrName; - (NSArray *)subtypes; - (BOOL)hasSubtype:(NSString *)_subtype; - (NSString *)langSubtype; /* values */ - (unsigned)count; - (void)addValue:(NSData *)_value; - (NSArray *)allValues; - (NSEnumerator *)valueEnumerator; - (void)addStringValue:(NSString *)_value; - (NSArray *)allStringValues; - (NSEnumerator *)stringValueEnumerator; - (NSString *)stringValueAtIndex:(unsigned)_idx; - (id) asArrayOrString; @end #endif /* __NGLdapAttribute_H__ */ SOPE/sope-ldap/NGLdap/NGLdapDataSource.h0000644000000000000000000000317715004363604016555 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGLdapDataSource_H__ #define __NGLdapDataSource_H__ #import @class EOFetchSpecification; @class NGLdapConnection; /* supported keys: any LDAP attribute name supported fetch hints: NSFetchKeys - array of NSString's denoting the keys to fetch NSFetchScope - [NSFetchScopeBase|NSFetchScopeOneLevel|NSFetchScopeSubTree] */ @interface NGLdapDataSource : EODataSource { NGLdapConnection *ldap; EOFetchSpecification *fspec; NSString *searchBase; } - (id)initWithLdapConnection:(NGLdapConnection *)_con searchBase:(NSString *)_dn; /* accessors */ - (void)setFetchSpecification:(EOFetchSpecification *)_fspec; - (EOFetchSpecification *)fetchSpecification; /* operations */ - (NSArray *)fetchObjects; - (NSString *)searchBase; @end /* NGLdapDataSource */ #endif /* __NGLdapDataSource_H__ */ SOPE/sope-ldap/NGLdap/NGLdapGlobalID.h0000644000000000000000000000220215004363604016124 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGLdapGlobalID_H__ #define __NGLdapGlobalID_H__ #import @interface NGLdapGlobalID : EOGlobalID { NSString *host; int port; NSString *dn; } - (id)initWithHost:(NSString *)_host port:(int)_port dn:(NSString *)_dn; /* accessors */ - (NSString *)host; - (NSString *)dn; - (int)port; @end #endif /* __NGLdapGlobalID_H__ */ SOPE/sope-ldap/NGLdap/COPYING0000644000000000000000000006130315004363604014352 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SOPE/sope-ldap/NGLdap/fhs.make0000644000000000000000000000173315004363604014737 0ustar rootroot# postprocessing # FHS support (this is a hack and is going to be done by gstep-make!) ifneq ($(FHS_INSTALL_ROOT),) FHS_INCLUDE_DIR=$(FHS_INSTALL_ROOT)/include/ FHS_BIN_DIR=$(FHS_INSTALL_ROOT)/bin/ ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib64/ else FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib/ endif fhs-header-dirs :: $(MKDIRS) $(FHS_INCLUDE_DIR)$(libNGLdap_HEADER_FILES_INSTALL_DIR) move-headers-to-fhs :: fhs-header-dirs @echo "moving headers to $(FHS_INCLUDE_DIR) .." mv $(GNUSTEP_HEADERS)$(libNGLdap_HEADER_FILES_INSTALL_DIR)/*.h \ $(FHS_INCLUDE_DIR)$(libNGLdap_HEADER_FILES_INSTALL_DIR)/ NONFHS_LIBDIR="$(GNUSTEP_LIBRARIES)/$(GNUSTEP_TARGET_LDIR)/" NONFHS_LIBNAME="$(LIBRARY_NAME)$(LIBRARY_NAME_SUFFIX)$(SHARED_LIBEXT)" move-libs-to-fhs :: @echo "moving libs to $(FHS_LIB_DIR) .." mv $(NONFHS_LIBDIR)/$(NONFHS_LIBNAME)* $(FHS_LIB_DIR)/ move-to-fhs :: move-headers-to-fhs move-libs-to-fhs after-install :: move-to-fhs endif SOPE/sope-ldap/NGLdap/NGLdapModification.h0000644000000000000000000000265115004363604017124 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGLdapModification_H__ #define __NGLdapModification_H__ #import @class NGLdapAttribute; #define NGLdapAddAttribute 1 #define NGLdapDeleteAttribute 2 #define NGLdapReplaceAttribute 3 @interface NGLdapModification : NSObject { int operation; NGLdapAttribute *attribute; } + (id)addModification:(NGLdapAttribute *)_attribute; + (id)replaceModification:(NGLdapAttribute *)_attribute; + (id)deleteModification:(NGLdapAttribute *)_attribute; - (id)initWithOperation:(int)_op attribute:(NGLdapAttribute *)_attribute; - (int)operation; - (NGLdapAttribute *)attribute; @end #endif /* __NGLdapModification_H__ */ SOPE/sope-ldap/NGLdap/README0000644000000000000000000000056015004363604014175 0ustar rootrootNGLdap ====== NGLdap is a thin wrapper library around the libldap C client library for LDAP directory servers. Examples ======== ldapls ldap2dsml Defaults ======== LDAPDebugEnabled - debug mode, log operations LDAPLoginAttributeName - the name of the attribute which stores login names for password checks (default: uid) SOPE/sope-ldap/NGLdap/NGLdapDataSource.m0000644000000000000000000001321115004363604016550 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLdapDataSource.h" #include "NGLdapEntry.h" #include "NGLdapAttribute.h" #include "NGLdapConnection.h" #import #import #include "common.h" @implementation NGLdapDataSource - (id)initWithLdapConnection:(NGLdapConnection *)_con searchBase:(NSString *)_dn{ if (_con == nil) { [self release]; return nil; } if ((self = [super init])) { self->ldap = [_con retain]; self->searchBase = [_dn copy]; } return self; } - (void)dealloc { [self->searchBase release]; [self->fspec release]; [self->ldap release]; [super dealloc]; } - (void)setFetchSpecification:(EOFetchSpecification *)_fspec { /* should invalidate ds chain */ ASSIGN(self->fspec, _fspec); } - (EOFetchSpecification *)fetchSpecification { return self->fspec; } /* transformation */ - (NSDictionary *)_recordFromEntry:(NGLdapEntry *)_entry { NSMutableDictionary *md; NSEnumerator *keys; NSString *key; id tmp; if (_entry == nil) return nil; md = [NSMutableDictionary dictionaryWithCapacity:[_entry count]]; if ((tmp = [_entry dn])) { [md setObject:tmp forKey:@"NSFileIdentifier"]; [md setObject:tmp forKey:NSFilePath]; } if ((tmp = [_entry rdn])) [md setObject:tmp forKey:NSFileName]; keys = [[_entry attributeNames] objectEnumerator]; while ((key = [keys nextObject])) { NGLdapAttribute *attribute; unsigned count; id value; attribute = [_entry attributeWithName:key]; count = [attribute count]; if (count == 0) value = [EONull null]; else if (count == 1) value = [attribute stringValueAtIndex:0]; else value = [attribute allStringValues]; [md setObject:value forKey:key]; } return [[md copy] autorelease]; } /* operations */ - (NSArray *)fetchObjects { // TODO: use the new fetch-enumerator NSAutoreleasePool *pool; NSString *scope; EOQualifier *qualifier; NSArray *sortOrderings; NSEnumerator *e; NSString *baseDN; NSMutableArray *results; NGLdapEntry *entry; NSArray *array; NSArray *attrs; pool = [NSAutoreleasePool new]; scope = nil; qualifier = nil; sortOrderings = nil; baseDN = nil; attrs = nil; if (self->fspec) { NSString *entityName; qualifier = [self->fspec qualifier]; sortOrderings = [self->fspec sortOrderings]; scope = [[self->fspec hints] objectForKey:@"NSFetchScope"]; attrs = [[self->fspec hints] objectForKey:@"NSFetchKeys"]; if ((entityName = [self->fspec entityName])) { EOQualifier *oq; oq = [[EOKeyValueQualifier alloc] initWithKey:@"objectclass" operatorSelector:EOQualifierOperatorEqual value:entityName]; if (qualifier) { NSArray *qa; qa = [NSArray arrayWithObjects:oq, qualifier, nil]; qualifier = [[EOAndQualifier alloc] initWithQualifierArray:qa]; qualifier = [qualifier autorelease]; [oq release]; oq = nil; } else { qualifier = [oq autorelease]; oq = nil; } } } else { static NSArray *so = nil; if (so == nil) { EOSortOrdering *o; o = [EOSortOrdering sortOrderingWithKey:@"NSFileIdentifier" selector:EOCompareAscending]; so = [[NSArray alloc] initWithObjects:&o count:1]; } sortOrderings = so; } if (scope == nil) scope = @"NSFetchScopeOneLevel"; if (baseDN == nil) baseDN = self->searchBase; if ([scope isEqualToString:@"NSFetchScopeOneLevel"]) { e = [self->ldap flatSearchAtBaseDN:baseDN qualifier:qualifier attributes:attrs]; } else if ([scope isEqualToString:@"NSFetchScopeSubTree"]) { e = [self->ldap deepSearchAtBaseDN:baseDN qualifier:qualifier attributes:attrs]; } else { [NSException raise:@"NGLdapDataSourceException" format:@"unsupported fetch-scope: '%@' !", scope]; e = nil; } if (e == nil) { /* no results */ [pool release]; return nil; } /* transform results into records */ results = [NSMutableArray arrayWithCapacity:64]; while ((entry = [e nextObject])) { NSDictionary *record; if ((record = [self _recordFromEntry:entry]) == nil) { NSLog(@"WARNING: couldn't transform entry %@ into record !", entry); continue; } [results addObject:record]; } array = [[results copy] autorelease]; /* apply sort-orderings in-memory */ if (sortOrderings) array = [array sortedArrayUsingKeyOrderArray:sortOrderings]; array = [array retain]; [pool release]; return [array autorelease]; } - (NSString *)searchBase { return self->searchBase; } @end /* NGLdapDataSource */ SOPE/sope-ldap/NGLdap/NGLdapGlobalID.m0000644000000000000000000000463415004363604016144 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLdapGlobalID.h" #include "NSString+DN.h" #import #include "common.h" @implementation NGLdapGlobalID - (id)initWithHost:(NSString *)_host port:(int)_port dn:(NSString *)_dn { self->host = [_host copy]; self->port = _port; self->dn = [[[_dn dnComponents] componentsJoinedByString:@","] copy]; return self; } - (void)dealloc { [self->host release]; [self->dn release]; [super dealloc]; } /* accessors */ - (NSString *)host { return self->host; } - (NSString *)dn { return self->dn; } - (int)port { return self->port; } /* equality */ - (NSUInteger)hash { return [self->dn hash] + [self->host hash]; } - (BOOL)isEqual:(id)_other { NGLdapGlobalID *ooid; if ([_other class] != [self class]) return NO; ooid = _other; if ((ooid->dn == self->dn) && (ooid->host == self->host) && (ooid->port == self->port)) return YES; if (![ooid->dn isEqualToString:self->dn]) return NO; if (ooid->port != self->port) return NO; if (![ooid->host isEqualToString:self->host]) return NO; return YES; } /* description */ - (NSString *)stringValue { return [NSString stringWithFormat:@"%@:%i/%@", self->host, self->port, self->dn]; } - (NSString *)description { NSMutableString *s; NSString *d; s = [[NSMutableString alloc] init]; [s appendFormat:@"<0x%p[%@]: ", self, NSStringFromClass([self class])]; [s appendFormat:@" host=%@", self->host]; [s appendFormat:@" port=%i", self->port]; [s appendFormat:@" dn=%@", self->dn]; [s appendString:@">"]; d = [s copy]; [s release]; return [d autorelease]; } @end /* NGLdapGlobalID */ SOPE/sope-ldap/NGLdap/NGLdapAttribute.m0000644000000000000000000001667015004363604016475 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG Copyright (C) 2012 Inverse inc. This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLdapAttribute.h" #include "common.h" @implementation NGLdapAttribute - (id)initWithAttributeName:(NSString *)_name values:(NSArray *)_values { self->name = [_name copy]; self->values = [_values copy]; return self; } - (id)initWithAttributeName:(NSString *)_name { return [self initWithAttributeName:_name values:nil]; } - (void)dealloc { [self->name release]; [self->values release]; [super dealloc]; } /* attribute name operations */ - (NSString *)attributeName { return self->name; } + (NSString *)baseNameOfAttributeName:(NSString *)_attrName { NSRange r; r = [_attrName rangeOfString:@";"]; if (r.length == 0) return _attrName; return [_attrName substringToIndex:r.location]; } - (NSString *)attributeBaseName { return [[self class] baseNameOfAttributeName:[self attributeName]]; } + (NSArray *)subtypesOfAttributeName:(NSString *)_attrName { NSArray *parts; parts = [_attrName componentsSeparatedByString:@";"]; return [parts count] > 1 ? [parts subarrayWithRange:NSMakeRange(1, [parts count] - 1)] : (NSArray *)[NSArray array]; } - (NSArray *)subtypes { return [[self class] subtypesOfAttributeName:[self attributeName]]; } - (BOOL)hasSubtype:(NSString *)_subtype { NSString *attrName; if (_subtype == nil) return NO; attrName = [self attributeName]; _subtype = [NSString stringWithFormat:@";%@;", _subtype]; return [attrName rangeOfString:_subtype].length > 0 ? YES : NO; } - (NSString *)langSubtype { NSString *attrName; NSRange r; attrName = [self attributeName]; r = [attrName rangeOfString:@";lang-"]; if (r.length == 0) return nil; attrName = [attrName substringFromIndex:(r.location + 1)]; r = [attrName rangeOfString:@";"]; if (r.length > 0) attrName = [attrName substringToIndex:r.location]; return attrName; } /* values */ - (unsigned)count { return [self->values count]; } - (void)addValue:(NSData *)_value { self->didChange = YES; if (self->values == nil) self->values = [[NSArray alloc] initWithObjects:&_value count:1]; else { NSArray *tmp; tmp = self->values; self->values = [[tmp arrayByAddingObject:_value] retain]; [tmp release]; } } - (NSArray *)allValues { return self->values; } - (NSEnumerator *)valueEnumerator { return [self->values objectEnumerator]; } - (void)addStringValue:(NSString *)_value { NSData *d; d = [_value dataUsingEncoding:NSUTF8StringEncoding]; [self addValue:d]; } - (void)catchedDecodeException:(NSException *)_exception { fprintf(stderr, "Got exception %s decoding NSUTF8StringEncoding, " "use defaultCStringEncoding", [[_exception description] cString]); } - (NSString *)stringFromData:(NSData *)_data { static NSStringEncoding enc = 0; NSString *s; if (enc == 0) enc = [NSString defaultCStringEncoding]; if (_data == nil) return nil; NS_DURING s = [[NSString alloc] initWithData:_data encoding:NSUTF8StringEncoding]; NS_HANDLER { [self catchedDecodeException:localException]; s = nil; } NS_ENDHANDLER; if (s == nil) s = [[NSString alloc] initWithData:_data encoding:enc]; return s; } - (NSString *)stringValueAtIndex:(unsigned)_idx { NSData *data; data = [[self allValues] objectAtIndex:_idx]; if (![data isNotNull]) return nil; return [[self stringFromData:data] autorelease]; } - (NSArray *)allStringValues { unsigned cnt; if ((cnt = [self count]) == 0) { return [NSArray array]; } else if (cnt == 1) { NSString *s; NSData *data; NSArray *a; data = [[self allValues] objectAtIndex:0]; if (![data isNotNull]) return nil; s = [self stringFromData:data]; if (s) { a = [[NSArray alloc] initWithObjects:&s count:1]; [s release]; return [a autorelease]; } else { //[self errorWithFormat: @"could not convert value of %@ to string", [self attributeName]]; return nil; } } else { id *objs; unsigned i; NSArray *vals, *a; NSData *data; vals = [self allValues]; objs = calloc(cnt, sizeof(id)); for (i = 0; i < cnt; i++) { objs[i] = nil; data = [vals objectAtIndex: i]; if (data) objs[i] = [self stringFromData: data]; if (!objs[i]) { NSLog(@"missing data for value at index %i", i); objs[i] = [[NSString alloc] initWithString: @""]; } } a = [[NSArray alloc] initWithObjects:objs count:cnt]; for (i = 0; i < cnt; i++) [objs[i] release]; free(objs); objs = NULL; return [a autorelease]; } } - (NSEnumerator *)stringValueEnumerator { return [[self allStringValues] objectEnumerator]; } /* NSObject */ - (BOOL) isEqual: (id)aAttribute { BOOL rc = NO; NSArray *otherValues; id value, otherValue; NSUInteger count, max; if (aAttribute == self) rc = YES; else { if ([name isEqualToString: [aAttribute attributeName]]) { max = [values count]; otherValues = [aAttribute allValues]; if (max == [otherValues count]) { rc = YES; for (count = 0; rc && count < max; count++) { value = [values objectAtIndex: count]; otherValue = [otherValues objectAtIndex: count]; if (value != otherValue && ![value isEqual: otherValue]) rc = NO; } } } } return rc; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { return [[[self class] alloc] initWithAttributeName:self->name values:self->values]; } /* description */ - (NSString *)stringValue { NSMutableString *ms; NSString *s; NSEnumerator *e; id value; BOOL isFirst; ms = [[NSMutableString alloc] initWithCapacity:100]; e = [self stringValueEnumerator]; isFirst = YES; while ((value = [e nextObject])) { if (isFirst) isFirst = NO; else [ms appendString:@","]; [ms appendString:[value description]]; } s = [ms copy]; [ms release]; return [s autorelease]; } - (NSString *)description { NSMutableString *s; s = [NSMutableString stringWithCapacity:100]; [s appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; [s appendFormat:@" name='%@'", [self attributeName]]; [s appendString:@" values="]; [s appendString:[self stringValue]]; [s appendString:@">"]; return s; } - (id) asArrayOrString { NSArray *arrayValue; id value; arrayValue = [self allStringValues]; if ([arrayValue count] == 1) value = [arrayValue objectAtIndex: 0]; else value = arrayValue; return value; } @end /* NGLdapAttribute */ SOPE/sope-ldap/NGLdap/Version0000644000000000000000000000010515004363604014660 0ustar rootroot# Version file MAJOR_VERSION=4 MINOR_VERSION=9 SUBMINOR_VERSION:=35 SOPE/sope-ldap/NGLdap/EOQualifier+LDAP.h0000644000000000000000000000207015004363604016345 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __EOQualifier_LDAP_H__ #define __EOQualifier_LDAP_H__ #import @class NSString; @interface EOQualifier(LDAP) - (id)initWithLDAPFilterString:(NSString *)_filter; - (NSString *)ldapFilterString; @end /* EOQualifier(LDAP) */ #endif /* __EOQualifier_LDAP_H__ */ SOPE/sope-ldap/NGLdap/NSString+DN.m0000644000000000000000000001352315004363604015502 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #import #include #include "NSString+DN.h" #include #include "common.h" static NSString *dnSeparator = @","; static NSCharacterSet *escapableChars = nil; static NSArray *cleanDNComponents(NSArray *_components) { unsigned i, count; id *cs; if ((count = [_components count]) == 0) return nil; cs = calloc(count, sizeof(id)); for (i = 0; i < count; i++) cs[i] = [[_components objectAtIndex:i] stringByTrimmingWhiteSpaces]; _components = [NSArray arrayWithObjects:cs count:count]; if (cs != NULL) { free(cs); cs = NULL; } return _components; } @implementation NSString(DNSupport) + (NSString *)dnWithComponents:(NSArray *)_components { return [cleanDNComponents(_components) componentsJoinedByString:dnSeparator]; } /* returns each dn component in a NSArray * returns nil if there is a decoding error */ - (NSArray *)dnComponents { char *componentStr; int i, err; LDAPDN dn; NSMutableArray *components; if (![self length]) return nil; dn = NULL; components = [NSMutableArray arrayWithCapacity:0]; err = ldap_str2dn([self cStringUsingEncoding: NSUTF8StringEncoding], &dn, LDAP_DN_FORMAT_LDAPV3); if(err) { /* sorry for the noise but this has to be known */ NSLog(@"ldap_str2dn: %s\n", ldap_err2string(err)); ldap_dnfree(dn); return nil; } /* loop through the dn parts * convert them back to properly quoted/escaped strings */ for (i=0; dn[i]; i++) { componentStr = NULL; err = ldap_rdn2str(dn[i], &componentStr, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY); if(err) { NSLog(@"ldap_rdn2dn: %s\n", ldap_err2string(err)); ldap_dnfree(dn); return nil; } if(componentStr) { [components addObject: [NSString stringWithCString: componentStr encoding: NSUTF8StringEncoding]]; free(componentStr); } } ldap_dnfree(dn); return [NSArray arrayWithArray: components]; } - (NSString *)stringByAppendingDNComponent:(NSString *)_component { NSString *s; if (![(s = [self stringByTrimmingWhiteSpaces]) isNotEmpty]) return _component; s = [dnSeparator stringByAppendingString:self]; return [_component stringByAppendingString:s]; } - (NSString *)stringByDeletingLastDNComponent { NSMutableArray *components; components = [NSMutableArray arrayWithArray: [self dnComponents]]; if (![components count]) return nil; /* "Last DN component" is actually the first component : * For "cn=bob,ou=users,dc=example,dc=com", remove "cn=bob" */ [components removeObjectAtIndex: 0]; return [components componentsJoinedByString:dnSeparator]; } - (NSString *)lastDNComponent { NSMutableArray *components; components = [NSMutableArray arrayWithArray: [self dnComponents]]; if (![components count]) return nil; /* "Last DN component" is actually the first component : * For "cn=bob,ou=users,dc=example,dc=com", return "cn=bob" */ return [components objectAtIndex: 0]; } - (const char *)ldapRepresentation { return [self UTF8String]; } - (NSDate *)ldapTimestamp { /* eg: '20000403055250Z' */ unsigned len; short year, month, day, hour, minute, second; NSString *tzname; NSTimeZone *tz; if ((len = [self length]) == 0) return nil; if (len < 14) return nil; year = [[self substringWithRange:NSMakeRange(0, 4)] intValue]; month = [[self substringWithRange:NSMakeRange(4, 2)] intValue]; day = [[self substringWithRange:NSMakeRange(6, 2)] intValue]; hour = [[self substringWithRange:NSMakeRange(8, 2)] intValue]; minute = [[self substringWithRange:NSMakeRange(10, 2)] intValue]; second = [[self substringWithRange:NSMakeRange(12, 2)] intValue]; /* timezone ??? */ tzname = @"GMT"; tz = [NSTimeZone timeZoneWithAbbreviation:tzname]; return [NSCalendarDate dateWithYear:year month:month day:day hour:hour minute:minute second:second timeZone:tz]; } - (NSString *) escapedForLDAPDN { NSMutableString *newString; NSString *format; unichar *uniString; unichar currentChar; NSUInteger count, length; if (!escapableChars) { escapableChars = [NSCharacterSet characterSetWithCharactersInString: @"\"+,;<>\\"]; [escapableChars retain]; } length = [self length]; newString = [NSMutableString stringWithCapacity: length]; uniString = NSZoneMalloc (NULL, sizeof (unichar) * length); [self getCharacters: uniString]; /* see rfc4514, section 2.4 */ for (count = 0; count < length; count++) { currentChar = uniString[count]; if ((currentChar == ' ' && (count == 0 || count == (length - 1))) || [escapableChars characterIsMember: currentChar]) format = @"\\%Lc"; else format = @"%Lc"; [newString appendFormat: format, currentChar]; } NSZoneFree (NULL, uniString); return newString; } @end /* NSString(DNSupport) */ SOPE/sope-ldap/NGLdap/EOQualifier+LDAP.m0000644000000000000000000001270215004363604016355 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOQualifier+LDAP.h" #include "common.h" @interface EOQualifier(LDAPPrivates) - (void)addToLDAPFilterString:(NSMutableString *)_s inContext:(id)_ctx; @end @implementation EOQualifier(LDAP) - (id)initWithLDAPFilterString:(NSString *)_filter { return nil; } - (void)addToLDAPFilterString:(NSMutableString *)_s inContext:(id)_ctx { [self doesNotRecognizeSelector:_cmd]; // subclass } - (NSString *)ldapFilterString { NSMutableString *s; NSString *is; s = [[NSMutableString alloc] initWithCapacity:100]; [self addToLDAPFilterString:s inContext:nil]; is = [s copy]; [s release]; return [is autorelease]; } @end /* EOQualifier(LDAP) */ @implementation EOAndQualifier(LDAP) - (void)addToLDAPFilterString:(NSMutableString *)_s inContext:(id)_ctx { unsigned i, cnt; NSArray *array; array = [self qualifiers]; cnt = [array count]; [_s appendString:@"(&"]; for (i = 0; i < cnt; i++) { EOQualifier *sq; sq = [array objectAtIndex:i]; [sq addToLDAPFilterString:_s inContext:_ctx]; } [_s appendString:@")"]; } @end /* EOAndQualifier(LDAP) */ @implementation EOOrQualifier(LDAP) - (void)addToLDAPFilterString:(NSMutableString *)_s inContext:(id)_ctx { unsigned i, cnt; NSArray *array; array = [self qualifiers]; cnt = [array count]; [_s appendString:@"(|"]; for (i = 0; i < cnt; i++) { EOQualifier *sq; sq = [array objectAtIndex:i]; [sq addToLDAPFilterString:_s inContext:_ctx]; } [_s appendString:@")"]; } @end /* EOOrQualifier(LDAP) */ @implementation EONotQualifier(LDAP) - (void)addToLDAPFilterString:(NSMutableString *)_s inContext:(id)_ctx { [_s appendString:@"(!"]; [[self qualifier] addToLDAPFilterString:_s inContext:_ctx]; [_s appendString:@")"]; } @end /* EONotQualifier(LDAP) */ @implementation EOKeyValueQualifier(LDAP) - (void)addToLDAPFilterString:(NSMutableString *)_s inContext:(id)_ctx { // TODO: patterns are treated like regular strings or the reverse? SEL sel; sel = [self selector]; if (sel_isEqual(sel, EOQualifierOperatorNotEqual)) [_s appendString:@"(!"]; [_s appendString:@"("]; [_s appendString:[self key]]; if (sel_isEqual(sel, EOQualifierOperatorEqual)) [_s appendString:@"="]; else if (sel_isEqual(sel, EOQualifierOperatorNotEqual)) [_s appendString:@"="]; else if (sel_isEqual(sel, EOQualifierOperatorLessThan)) [_s appendString:@"<"]; else if (sel_isEqual(sel, EOQualifierOperatorGreaterThan)) [_s appendString:@">"]; else if (sel_isEqual(sel, EOQualifierOperatorLessThanOrEqualTo)) [_s appendString:@"<="]; else if (sel_isEqual(sel, EOQualifierOperatorGreaterThanOrEqualTo)) [_s appendString:@">="]; else if (sel_isEqual(sel, EOQualifierOperatorContains)) [_s appendString:@"=*"]; else if (sel_isEqual(sel, EOQualifierOperatorLike)) [_s appendString:@"="]; else if (sel_isEqual(sel, EOQualifierOperatorCaseInsensitiveLike)) [_s appendString:@"="]; else { NSLog(@"UNKNOWN operator: %@", NSStringFromSelector([self selector])); [_s appendString:@"="]; } [_s appendString:[[self value] description]]; [_s appendString:@")"]; if (sel_isEqual(sel, EOQualifierOperatorNotEqual)) [_s appendString:@")"]; } @end /* EOKeyValueQualifier(LDAP) */ @implementation EOKeyComparisonQualifier(LDAP) - (void)addToLDAPFilterString:(NSMutableString *)_s inContext:(id)_ctx { /* ldap supports no comparison operations on keys */ SEL sel; sel = [self selector]; if (sel_isEqual(sel, EOQualifierOperatorNotEqual)) [_s appendString:@"(!"]; [_s appendString:@"("]; [_s appendString:[self leftKey]]; if (sel_isEqual(sel, EOQualifierOperatorEqual)) [_s appendString:@"="]; else if (sel_isEqual(sel, EOQualifierOperatorNotEqual)) [_s appendString:@"="]; else if (sel_isEqual(sel, EOQualifierOperatorLessThan)) [_s appendString:@"<"]; else if (sel_isEqual(sel, EOQualifierOperatorGreaterThan)) [_s appendString:@">"]; else if (sel_isEqual(sel, EOQualifierOperatorLessThanOrEqualTo)) [_s appendString:@"<="]; else if (sel_isEqual(sel, EOQualifierOperatorGreaterThanOrEqualTo)) [_s appendString:@">="]; else if (sel_isEqual(sel, EOQualifierOperatorContains)) [_s appendString:@"=*"]; else if (sel_isEqual(sel, EOQualifierOperatorLike)) [_s appendString:@"="]; else if (sel_isEqual(sel, EOQualifierOperatorCaseInsensitiveLike)) [_s appendString:@"="]; else { NSLog(@"UNKNOWN operator: %@", NSStringFromSelector([self selector])); [_s appendString:@"="]; } [_s appendString:[self rightKey]]; [_s appendString:@")"]; if (sel_isEqual(sel, EOQualifierOperatorNotEqual)) [_s appendString:@")"]; } @end /* EOKeyComparisonQualifier(LDAP) */ SOPE/sope-ldap/NGLdap/NGLdapConnection.h0000644000000000000000000001171115004363604016613 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGLdapConnection_H__ #define __NGLdapConnection_H__ #import #import #define LDAP_DEPRECATED 1 #include @class NSString, NSArray, NSEnumerator; @class EOQualifier; @class NGLdapEntry; @interface NGLdapConnection : NSObject { LDAP *handle; NSString *hostName; int port; unsigned int sizeLimit; NSTimeInterval timeLimit; NSTimeInterval cacheTimeout; long cacheMaxMemory; /* in bytes */ BOOL isCacheEnabled; struct { BOOL isBound:1; } flags; } - (id)initWithHostName:(NSString *)_hostName port:(int)_port; // designated init - (id)initWithHostName:(NSString *)_hostName; /* settings */ - (NSString *)hostName; - (int)port; /* encryption */ - (BOOL)useSSL; - (BOOL)startTLS; /* binding */ - (BOOL)isBound; - (void)unbind; - (BOOL)bindWithMethod:(NSString *)_method binddn:(NSString *)_login credentials:(NSString *)_cred; #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST - (BOOL) bindWithMethod: (NSString *) _method binddn: (NSString *) _login credentials: (NSString *) _cred perr: (LDAPPasswordPolicyError *) _perr expire: (int *) _expire grace: (int *) _grace; - (BOOL) changePasswordAtDn: (NSString *) _dn oldPassword: (NSString *) _oldPassword newPassword: (NSString *) _newPassword perr: (LDAPPasswordPolicyError *) _perr; #endif - (BOOL) changeADPasswordAtDn: (NSString *) _dn oldPassword: (NSString *) _oldPassword newPassword: (NSString *) _newPassword; /* query parameters */ - (void)setQueryTimeLimit:(NSTimeInterval)_timeLimit; - (NSTimeInterval)queryTimeLimit; - (void)setQuerySizeLimit:(unsigned int)_timeLimit; - (unsigned int )querySizeLimit; /* running queries */ - (NSEnumerator *)flatSearchAtBaseDN:(NSString *)_base qualifier:(EOQualifier *)_q attributes:(NSArray *)_attributes sortAttribute:(NSString *)_sortAttribute sortReverse:(BOOL)_sortReverse; - (NSEnumerator *)flatSearchAtBaseDN:(NSString *)_base qualifier:(EOQualifier *)_q attributes:(NSArray *)_attributes; - (NSEnumerator *)deepSearchAtBaseDN:(NSString *)_base qualifier:(EOQualifier *)_q attributes:(NSArray *)_attributes sortAttribute:(NSString *)_sortAttribute sortReverse:(BOOL)_sortReverse; - (NSEnumerator *)deepSearchAtBaseDN:(NSString *)_base qualifier:(EOQualifier *)_q attributes:(NSArray *)_attributes; - (NSEnumerator *)baseSearchAtBaseDN:(NSString *)_base qualifier:(EOQualifier *)_q attributes:(NSArray *)_attributes; - (NSEnumerator *)baseSearchAtBaseDN:(NSString *)_base qualifier:(EOQualifier *)_q attributes:(NSArray *)_attributes sortAttribute:(NSString *)_sortAttribute sortReverse:(BOOL)_sortReverse; - (NGLdapEntry *)entryAtDN:(NSString *)_dn qualifier:(EOQualifier *)_q attributes:(NSArray *)_attrs; - (NGLdapEntry *)entryAtDN:(NSString *)_dn attributes:(NSArray *)_attrs; /* cache */ - (void)setCacheTimeout:(NSTimeInterval)_to; - (NSTimeInterval)cacheTimeout; - (void)setCacheMaxMemoryUsage:(long)_maxMem; - (long)cacheMaxMemoryUsage; - (void)setUseCache:(BOOL)_flag; - (BOOL)doesUseCache; - (void)flushCache; - (void)destroyCache; - (void)cacheForgetEntryWithDN:(NSString *)_dn; /* modifications */ - (BOOL)addEntry:(NGLdapEntry *)_entry; - (BOOL)removeEntryWithDN:(NSString *)_dn; - (BOOL)modifyEntryWithDN:(NSString *)_dn changes:(NSArray *)_mods; /* root DSE */ - (NGLdapEntry *)schemaEntry; - (NGLdapEntry *)rootDSE; - (NGLdapEntry *)rootDSEWithAttributes: (NSArray *) attributes; - (NGLdapEntry *)configEntry; - (NSArray *)namingContexts; - (BOOL) isADCompatible; @end @interface NGLdapConnection(PlainPasswordCheck) /* specialized password check routine */ - (NSString *)dnForLogin:(NSString *)_login baseDN:(NSString *)_baseDN; + (BOOL)checkPassword:(NSString *)_pwd ofLogin:(NSString *)_login atBaseDN:(NSString *)_baseDN onHost:(NSString *)_hostName port:(int)_port; @end #endif /* __NGLdapConnection_H__ */ SOPE/sope-ldap/NGLdap/NGLdapURL.m0000644000000000000000000001311415004363604015162 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLdapURL.h" #include "NGLdapConnection.h" #include "NGLdapEntry.h" #include "EOQualifier+LDAP.h" #include #include "common.h" #include @implementation NGLdapURL + (id)ldapURLWithString:(NSString *)_url { if (!ldap_is_ldap_url((char *)[_url UTF8String])) return nil; return [[[self alloc] initWithString:_url] autorelease]; } - (id)initWithString:(NSString *)_url { LDAPURLDesc *urld = NULL; unsigned attrCount, i; int err; self->scope = -1; if ((err = ldap_url_parse((char *)[_url UTF8String], &urld)) != 0) { [self release]; return nil; } if (urld == NULL) { [self release]; return nil; } self->host = [[NSString alloc] initWithCString:urld->lud_host]; self->port = urld->lud_port; self->base = [[NSString alloc] initWithCString:urld->lud_dn]; self->scope = urld->lud_scope; self->filter = [[NSString alloc] initWithCString:urld->lud_filter]; if (urld != NULL && urld->lud_attrs != NULL) { register char *tmp, **a; a = urld->lud_attrs; for (i = 0; (tmp = a[i]); i++) ; attrCount = i; } else attrCount = 0; if (attrCount > 0) { id *attrs; attrs = calloc(attrCount+1, sizeof(id)); for (i = 0; i < attrCount; i++) attrs[i] = [[NSString alloc] initWithCString:urld->lud_attrs[i]]; self->attributes = [[NSArray alloc] initWithObjects:attrs count:attrCount]; for (i = 0; i < attrCount; i++) [attrs[i] release]; if (attrs) free(attrs); } if (urld) ldap_free_urldesc(urld); return self; } - (id)init { return [self initWithString:nil]; } - (void)dealloc { [self->host release]; [self->base release]; [self->filter release]; [self->attributes release]; [super dealloc]; } /* accessors */ - (NSString *)hostName { return self->host; } - (NSHost *)host { return [NSHost hostWithName:[self hostName]]; } - (int)port { return self->port; } - (NSString *)baseDN { return self->base; } - (int)scope { return self->scope; } - (NSString *)searchFilter { return self->filter; } - (EOQualifier *)searchFilterQualifier { EOQualifier *q; if (self->filter == nil) return nil; q = nil; q = [[EOQualifier alloc] initWithLDAPFilterString:self->filter]; return [q autorelease]; } - (NSArray *)attributes { return self->attributes; } /* perform fetches */ - (NGLdapConnection *)openConnection { NGLdapConnection *con; con = [[NGLdapConnection alloc] initWithHostName:[self hostName] port:[self port] ? [self port] : 389]; return [con autorelease]; } - (NSEnumerator *)fetchEntries { NGLdapConnection *con; if ((con = [self openConnection]) == nil) return nil; switch (self->scope) { case LDAP_SCOPE_ONELEVEL: return [con flatSearchAtBaseDN:[self baseDN] qualifier:[self searchFilterQualifier] attributes:[self attributes]]; case LDAP_SCOPE_SUBTREE: return [con deepSearchAtBaseDN:[self baseDN] qualifier:[self searchFilterQualifier] attributes:[self attributes]]; case LDAP_SCOPE_BASE: return [con baseSearchAtBaseDN:[self baseDN] qualifier:[self searchFilterQualifier] attributes:[self attributes]]; } return nil; } - (NGLdapEntry *)fetchEntry { return [[self fetchEntries] nextObject]; } /* url */ - (NSString *)urlString { NSMutableString *s; NSString *r; s = [[NSMutableString alloc] initWithCapacity:200]; [s appendString:@"ldap://"]; [s appendString:self->host != nil ? self->host : (NSString *)@"localhost"]; if (self->port > 0) [s appendFormat:@":%i", self->port]; [s appendString:@"/"]; [s appendString:[self->base stringByEscapingURL]]; if ((self->attributes != nil) || (self->scope!=-1) || (self->filter != nil)){ NSString *is; [s appendString:@"?"]; is = [self->attributes componentsJoinedByString:@","]; [s appendString:[is stringByEscapingURL]]; } if ((self->scope != -1) || (self->filter != nil)) { [s appendString:@"?"]; switch (self->scope) { case LDAP_SCOPE_ONELEVEL: [s appendString:@"one"]; break; case LDAP_SCOPE_SUBTREE: [s appendString:@"sub"]; break; case LDAP_SCOPE_BASE: default: [s appendString:@"base"]; break; } } if ([self->filter isNotEmpty]) { [s appendString:@"?"]; [s appendString:[self->filter stringByEscapingURL]]; } r = [[s copy] autorelease]; [s release]; s = nil; return r; } /* NSCopying */ - (id)copyWithZone:(NSZone *)_zone { return [[[self class] allocWithZone:_zone] initWithString:[self urlString]]; } /* description */ - (NSString *)description { return [self urlString]; } @end /* NGLdapURL */ SOPE/sope-ldap/NGLdap/COPYRIGHT0000644000000000000000000000010615004363604014604 0ustar rootrootCopyright (C) 2000-2005 SKYRIX Software AG Contact: info@skyrix.com SOPE/sope-ldap/NGLdap/NGLdap-Info.plist0000644000000000000000000000133615004363604016372 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable NGLdap CFBundleGetInfoString CFBundleIdentifier org.OpenGroupware.SOPE.ldap.NGLdap CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType FMWK CFBundleShortVersionString CFBundleSignature ???? CFBundleVersion 4.5 SOPE/sope-ldap/NGLdap/NGLdapURL.h0000644000000000000000000000321715004363604015160 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGLdapURL_H__ #define __NGLdapURL_H__ #import // required by gstep-base #import @class NSString, NSArray, NSHost, NSEnumerator; @class NGLdapConnection, NGLdapEntry; // ldap://hostport/dn[?attributes[?scope[?filter]]] @interface NGLdapURL : NSURL < NSCopying > { NSString *host; int port; NSString *base; int scope; NSString *filter; NSArray *attributes; } + (id)ldapURLWithString:(NSString *)_url; - (id)initWithString:(NSString *)_url; // designated initializer /* accessors */ - (NSString *)hostName; - (NSHost *)host; - (int)port; - (NSString *)baseDN; - (int)scope; - (NSString *)searchFilter; - (NSArray *)attributes; /* query */ - (NGLdapConnection *)openConnection; - (NSEnumerator *)fetchEntries; - (NGLdapEntry *)fetchEntry; /* url */ - (NSString *)urlString; @end #endif /* __NGLdapURL_H__ */ SOPE/sope-ldap/NGLdap/NGLdapConnection.m0000644000000000000000000012464415004363604016632 0ustar rootroot/* Copyright (C) 2000-2007 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGLdapConnection.h" #include "NGLdapSearchResultEnumerator.h" #include "NGLdapEntry.h" #include "NGLdapAttribute.h" #include "NGLdapModification.h" #include "EOQualifier+LDAP.h" #include "common.h" static BOOL LDAPDebugEnabled = NO; static BOOL LDAPInitialBindSpecific = NO; static NSString *LDAPInitialBindDN = @"" ; static NSString *LDAPInitialBindPW = @"" ; /* this is required by SuSE EMail Server III */ static BOOL LDAPUseLatin1Creds = NO; @interface NGLdapConnection(Privates) - (BOOL)_reinit; @end @implementation NGLdapConnection static void freeMods(LDAPMod **mods) { LDAPMod *buf; unsigned i; if (mods == NULL) return; buf = mods[0]; for (i = 0; mods[i] != NULL; i++) { struct berval **values; char *type; if ((values = buf[i].mod_bvalues) != NULL) { unsigned j; for (j = 0; values[j] != NULL; j++) free(values[j]); free(values); } if ((type = buf[i].mod_type) != NULL) free(type); } if (buf) free(buf); if (mods) free(mods); } + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; static BOOL didInit = NO; if (didInit) return; didInit = YES; LDAPDebugEnabled = [ud boolForKey:@"LDAPDebugEnabled"]; LDAPInitialBindSpecific = [ud boolForKey:@"LDAPInitialBindSpecific"]; LDAPInitialBindDN = [[ud stringForKey:@"LDAPInitialBindDN"] copy]; LDAPInitialBindPW = [[ud stringForKey:@"LDAPInitialBindPW"] copy]; LDAPUseLatin1Creds = [ud boolForKey:@"LDAPUseLatin1Creds"]; } - (BOOL)_reinit { static int ldap_version3 = LDAP_VERSION3; int rc; if (self->handle != NULL) { ldap_unbind(self->handle); self->handle = NULL; } if (ldap_is_ldap_url([self->hostName UTF8String])) { if (LDAPDebugEnabled) [self logWithFormat:@"Using ldap_initialize for LDAP URL: %@", self->hostName]; rc = ldap_initialize(&self->handle, [self->hostName UTF8String]); if (rc != LDAP_SUCCESS) { [self logWithFormat:@"ERROR: ldap_initialize: %s", ldap_err2string(rc)]; return NO; } } else { /* Keep deprecated API around for old configurations */ if (LDAPDebugEnabled) [self logWithFormat:@"Using ldap_init (deprecated) for LDAP host:port %@:%d", self->hostName, self->port]; self->handle = ldap_init([self->hostName UTF8String], self->port); if (self->handle == NULL) return NO; } /* setup options (must be done before the bind) */ rc = ldap_set_option(self->handle, LDAP_OPT_PROTOCOL_VERSION, &ldap_version3); if (rc != LDAP_OPT_SUCCESS) [self logWithFormat:@"WARN: could not set protocol version to LDAPv3!"]; rc = ldap_set_option(self->handle, LDAP_OPT_REFERRALS, LDAP_OPT_OFF) ; if (rc != LDAP_OPT_SUCCESS) [self logWithFormat:@"Note: could not disable LDAP referrals."]; return YES; } - (id)initWithHostName:(NSString *)_hostName port:(int)_port { self->hostName = [_hostName copy]; self->port = (_port != 0) ? _port : 389; if (![self _reinit]) { [self release]; return nil; } [self setCacheTimeout:120.0]; [self setCacheMaxMemoryUsage:16000]; [self setQueryTimeLimit:0.0]; [self setQuerySizeLimit:0]; return self; } - (id)initWithHostName:(NSString *)_hostName { return [self initWithHostName:_hostName port:0]; } - (void)dealloc { if (self->handle != NULL) { if ([self isBound]) [self unbind]; else { // call unbind to free resources ldap_unbind(self->handle); self->handle = NULL; } // free handle } [self->hostName release]; [super dealloc]; } /* settings */ - (NSString *)hostName { return self->hostName; } - (int)port { return self->port; } /* internals */ - (void *)ldapHandle { return self->handle; } /* errors */ - (NSException *)_exceptionForErrorCode:(int)_err operation:(NSString *)_operation userInfo:(NSDictionary *)_ui { NSException *e; NSString *name, *reason, *ldapError; NSMutableDictionary *userInfo; name = @"LDAPException"; ldapError = [NSString stringWithCString: ldap_err2string(_err) encoding: NSUTF8StringEncoding]; reason = [NSString stringWithFormat: @"operation %@ failed: %@ (0x%X)", _operation, ldapError, _err]; userInfo = [[_ui mutableCopy] autorelease]; [userInfo setObject: [NSNumber numberWithInteger: _err] forKey: @"error_code"]; e = [NSException exceptionWithName:name reason:reason userInfo:userInfo]; return e; } /* encryption */ - (BOOL)useSSL { BOOL rc; int option; if (self->handle != NULL) { option = LDAP_OPT_X_TLS_HARD; rc = (ldap_set_option(self->handle, LDAP_OPT_X_TLS, &option) == LDAP_SUCCESS); } else rc = NO; return rc; } - (BOOL)startTLS { int rc; if (!self->handle) return NO; rc = ldap_start_tls_s(self->handle, NULL, NULL); /* manpage says it returns LDAP_LOCAL_ERROR if TLS is already installed */ /* but it actually returns LDAP_OPERATIONS_ERROR */ if (rc != LDAP_SUCCESS && rc != LDAP_LOCAL_ERROR && rc != LDAP_OPERATIONS_ERROR) { [[self _exceptionForErrorCode: rc operation: @"startTLS" userInfo: nil] raise]; return NO; } else return YES; } /* binding */ - (BOOL)isBound { return self->flags.isBound ? YES : NO; } - (void)unbind { if (self->flags.isBound) { ldap_unbind(self->handle); self->flags.isBound = 0; self->handle = NULL; } } - (BOOL)bindWithMethod:(NSString *)_method binddn:(NSString *)_login credentials:(NSString *)_cred { static NSString *loginKey = @"login"; NSDictionary *ui; NSException *e; int method, err; const char *l, *p; if (self->handle == NULL) [self _reinit]; if ((_method == nil) || ([_method isEqualToString:@"simple"])) { method = LDAP_AUTH_SIMPLE; } else if ([_method isEqualToString:@"krbv41"]) { method = LDAP_AUTH_KRBV41; } else if ([_method isEqualToString:@"krbv42"]) { method = LDAP_AUTH_KRBV42; } else /* unknown method */ return NO; l = [_login UTF8String]; p = LDAPUseLatin1Creds ? [_cred cString] : [_cred UTF8String]; err = (method == LDAP_AUTH_SIMPLE) ? ldap_simple_bind_s(self->handle, l, p) : ldap_bind_s(self->handle, l, p, method); if (err == LDAP_SUCCESS) { self->flags.isBound = YES; return YES; } /* exceptions */ if (_login == nil) _login = @""; ui = [[NSDictionary alloc] initWithObjects:&_login forKeys:&loginKey count:1]; e = [self _exceptionForErrorCode:err operation:@"bind" userInfo:ui]; [ui release]; ui = nil; [e raise]; return NO; } #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST - (BOOL) bindWithMethod: (NSString *) _method binddn: (NSString *) _login credentials: (NSString *) _cred perr: (LDAPPasswordPolicyError *) _perr expire: (int *) _expire grace: (int *) _grace { LDAPControl **sctrlsp = NULL; LDAPControl *sctrls[2]; LDAPControl sctrl[2]; LDAPControl **ctrls; LDAPControl c, *ctrl; LDAPMessage *result = NULL; int err, msgid, rc; const char *l, *p; char *matched = NULL; char *info = NULL; char **refs = NULL; struct berval passwd = { 0, NULL }; l = [_login UTF8String]; p = LDAPUseLatin1Creds ? [_cred cString] : [_cred UTF8String]; *_perr = -1; passwd.bv_val = (char *) p; passwd.bv_len = strlen(p); c.ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYREQUEST; c.ldctl_value.bv_val = NULL; c.ldctl_value.bv_len = 0; c.ldctl_iscritical = 0; sctrl[0] = c; sctrls[0] = &sctrl[0]; sctrls[1] = NULL; sctrlsp = sctrls; rc = ldap_sasl_bind(self->handle, l, LDAP_SASL_SIMPLE, &passwd, sctrlsp, NULL, &msgid); if (msgid == -1 || rc != LDAP_SUCCESS) { [self logWithFormat: @"bind - ldap_sasl_bind call failed"]; return NO; } rc = ldap_result(self->handle, msgid, LDAP_MSG_ALL, NULL, &result); if (rc == -1) { [self logWithFormat: @"bind - ldap_result call failed"]; if (result) ldap_msgfree(result); return NO; } [self logWithFormat: @"bind - ldap_result call result: %d", rc]; rc = ldap_parse_result(self->handle, result, &err, &matched, &info, &refs, &ctrls, 1); if (rc != LDAP_SUCCESS) { [self logWithFormat: @"bind - ldap_parse_result call failed"]; //if (result) ldap_msgfree(result); => causes a crash!? if (matched) ber_memfree(matched); if (info) ber_memfree(info); if (refs) ber_memvfree((void **)refs); return NO; } if (err == LDAP_SUCCESS) self->flags.isBound = YES; else self->flags.isBound = NO; // Even if we aren't bound to the server, we continue and we go get the // policy control if (ctrls) { ctrl = ldap_find_control(LDAP_CONTROL_PASSWORDPOLICYRESPONSE, ctrls); if (ctrl) { rc = ldap_parse_passwordpolicy_control(self->handle, ctrl, _expire, _grace, _perr); if (rc == LDAP_SUCCESS) { [self logWithFormat: @"bind - policy values: %d %d %d - bound: %d", *_expire, *_grace, *_perr, self->flags.isBound]; } else [self logWithFormat: @"bind - ldap_parse_passwordpolicy call failed"]; } else [self logWithFormat: @"bind - ldap_find_control call failed"]; ldap_controls_free(ctrls); } else { // A NULL control object doesn't mean it failed. 389-ds retuns one only // when it actually fails - upon success, it returns nothing. [self logWithFormat: @"bind - ldap_parse_result - ctrls is NULL"]; *_perr = 65535; } return self->flags.isBound; } // // Bind is required prior to calling this method. // - (BOOL) changePasswordAtDn: (NSString *) _dn oldPassword: (NSString *) _oldPassword newPassword: (NSString *) _newPassword perr: (LDAPPasswordPolicyError *) _perr { char *p; const char *user; int rc; *_perr = -1; user = [_dn UTF8String]; p = LDAPUseLatin1Creds ? (char *)[_oldPassword cString] : (char *)[_oldPassword UTF8String]; if (self->flags.isBound) { struct berval newpw = { 0, NULL }; struct berval oldpw = { 0, NULL }; struct berval bv = {0, NULL}; struct berval *retdata = NULL; LDAPControl *sctrls[2]; LDAPControl **ctrls; LDAPControl sctrl[2]; LDAPControl c, *ctrl; LDAPMessage *result; BerElement *ber = NULL; char *matcheddn = NULL, *retoid = NULL, *text = NULL, **refs = NULL; int idd, grace, expire, code; code = LDAP_OTHER; newpw.bv_val = LDAPUseLatin1Creds ? (char *)[_newPassword cString] : (char *)[_newPassword UTF8String]; newpw.bv_len = strlen(newpw.bv_val); oldpw.bv_val = p; oldpw.bv_len = strlen(p); ber = ber_alloc_t(LBER_USE_DER); if (ber == NULL) return NO; ber_printf(ber, "{"); ber_printf(ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, user); ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, &oldpw); ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, &newpw); ber_printf(ber, "N}"); rc = ber_flatten2(ber, &bv, 0 ); if (rc < 0) { [self logWithFormat: @"change password - ber_flatten2 call failed"]; ber_free(ber, 1); return NO; } // Everything is alright... *_perr = -1; c.ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYREQUEST; c.ldctl_value.bv_val = NULL; c.ldctl_value.bv_len = 0; c.ldctl_iscritical = 0; sctrl[0] = c; sctrls[0] = &sctrl[0]; sctrls[1] = NULL; rc = ldap_set_option(self->handle, LDAP_OPT_SERVER_CONTROLS, sctrls); if (rc != LDAP_OPT_SUCCESS) { [self logWithFormat: @"change password - ldap_set_option call failed"]; ber_free(ber, 1); return NO; } rc = ldap_extended_operation(self->handle, LDAP_EXOP_MODIFY_PASSWD, &bv, NULL, NULL, &idd); ber_free(ber, 1); if (rc != LDAP_SUCCESS ) { [self logWithFormat: @"change password - ldap_extended_operation call failed"]; return NO; } rc = ldap_result(self->handle, LDAP_RES_ANY, LDAP_MSG_ALL, NULL, &result); if (rc < 0) { [self logWithFormat: @"change password - ldap_result call failed"]; return NO; } rc = ldap_parse_result(self->handle, result, &code, &matcheddn, &text, &refs, &ctrls, 0); if (rc != LDAP_SUCCESS || code == LDAP_UNWILLING_TO_PERFORM) { [self logWithFormat: @"change password - ldap_parse_result call failed, rc = %d, code = %d, matcheddn = %s, text = %s", rc, code, matcheddn, text]; ber_memfree(text); ber_memfree(matcheddn); ber_memvfree((void **) refs); free(ctrls); return NO; } rc = ldap_parse_extended_result(self->handle, result, &retoid, &retdata, 1); if (rc != LDAP_SUCCESS) { [self logWithFormat: @"change password - ldap_parse_extended result call failed"]; ber_memfree(text); ber_memfree(matcheddn); ber_memvfree((void **) refs); ber_memfree(retoid); ber_bvfree(retdata); free(ctrls); return NO; } ctrl = ldap_find_control(LDAP_CONTROL_PASSWORDPOLICYRESPONSE, ctrls); if (ctrl) { rc = ldap_parse_passwordpolicy_control(self->handle, ctrl, &expire, &grace, _perr); if (rc == LDAP_SUCCESS && *_perr == PP_noError) { [self logWithFormat: @"change password - policy values: %d %d %d", expire, grace, *_perr]; } else { [self logWithFormat: @"change password - ldap_parse_passwordpolicy call failed or error during password change: %d", *_perr]; ber_memfree(text); ber_memfree(matcheddn); ber_memvfree((void **) refs); ber_memfree(retoid); ber_bvfree(retdata); free(ctrls); return NO; } } else { // Ending up here doesn't mean that things failed. It could simply be caused by the // fact that the password change was a success but no policy control object // could be found. [self logWithFormat: @"change password - ldap_find_control call failed"]; } ber_memfree(text); ber_memfree(matcheddn); ber_memvfree((void **) refs); ber_memfree(retoid); ber_bvfree(retdata); free(ctrls); return YES; } return NO; } #endif /* LDAP_CONTROL_PASSWORDPOLICYREQUEST */ - (void)setQueryTimeLimit:(NSTimeInterval)_timeLimit { self->timeLimit = _timeLimit; } - (NSTimeInterval)queryTimeLimit { return self->timeLimit; } - (void)setQuerySizeLimit:(unsigned int)_sizeLimit { self->sizeLimit = _sizeLimit; } - (unsigned int)querySizeLimit { return self->sizeLimit; } /* password operations */ - (BOOL) changeADPasswordAtDn: (NSString *) _dn oldPassword: (NSString *) _oldPassword newPassword: (NSString *) _newPassword { /* Change a user password in Active Directory (or Samba4) following these * guidelines: http://support.microsoft.com/kb/269190 * http://msdn.microsoft.com/en-us/library/cc223248.aspx */ BOOL didChange; NSArray *mods; NSData *dataOldPassword, *dataNewPassword; NGLdapAttribute *attrOldPassword, *attrNewPassword; NGLdapModification *modPasswordDelete, *modPasswordAdd; /* Passwords must be quoted and UTF16 encoded */ dataOldPassword = [[NSString stringWithFormat: @"\"%@\"", _oldPassword] dataUsingEncoding: NSUTF16LittleEndianStringEncoding]; dataNewPassword = [[NSString stringWithFormat: @"\"%@\"", _newPassword] dataUsingEncoding: NSUTF16LittleEndianStringEncoding]; attrOldPassword = [[NGLdapAttribute alloc] initWithAttributeName: @"unicodePwd" values: [NSArray arrayWithObject: dataOldPassword]]; [attrOldPassword autorelease]; attrNewPassword = [[NGLdapAttribute alloc] initWithAttributeName: @"unicodePwd" values: [NSArray arrayWithObject: dataNewPassword]]; [attrNewPassword autorelease]; /* Password delete op must contain quoted old password */ modPasswordDelete = [NGLdapModification deleteModification: attrOldPassword]; modPasswordAdd = [NGLdapModification addModification: attrNewPassword]; mods = [NSArray arrayWithObjects: modPasswordDelete, modPasswordAdd, nil]; NS_DURING { didChange = [self modifyEntryWithDN: _dn changes: mods]; } NS_HANDLER { [self errorWithFormat: @"Couldn't change password for %@", _dn]; [localException raise]; } NS_ENDHANDLER; return didChange; } /* running queries */ - (NSEnumerator *)_searchAtBaseDN:(NSString *)_base qualifier:(EOQualifier *)_q attributes:(NSArray *)_attributes scope:(int)_scope sortAttribute:(NSString *)_sortAttribute sortReverse:(BOOL)_sortReverse { NSString *filter; int msgid, rc; char **attrs; NGLdapSearchResultEnumerator *e; LDAPSortKey **keys; struct berval control_value = { 0L, NULL }; LDAPControl** ctrls; if (self->handle == NULL) [self _reinit]; if ((filter = [_q ldapFilterString]) == nil) filter = @"(objectclass=*)"; if (_attributes != nil) { unsigned i, acount; acount = [_attributes count]; attrs = calloc(acount + 3, sizeof(char *)); for (i = 0; i < acount; i++) attrs[i] = (char *)[[_attributes objectAtIndex:i] UTF8String]; attrs[i] = NULL; } else attrs = NULL; if (LDAPDebugEnabled) { NSLog(@"%s: search at base '%@' filter '%@' for attrs '%@'\n", __PRETTY_FUNCTION__, _base, filter, [_attributes componentsJoinedByString: @","]); } /* trigger search with sorting */ keys = malloc(2 * sizeof(LDAPSortKey)); keys[0] = malloc(sizeof(LDAPSortKey)); keys[0]->attributeType = (char *)[_sortAttribute UTF8String]; keys[0]->orderingRule = "2.5.13.3"; keys[0]->reverseOrder = _sortReverse ? 1 : 0; rc = ldap_create_sort_control_value(self->handle, keys, &control_value); if (LDAP_SUCCESS == rc) { ctrls = malloc(2 * sizeof(LDAPControl)); rc = ldap_control_create(LDAP_CONTROL_SORTREQUEST, LDAP_OPT_ON, &control_value, 1, ctrls); if (LDAP_SUCCESS == rc) { ctrls[1] = NULL; struct timeval tv_timelimit, *tv_timelimitp = NULL; if (self->timeLimit > 0.0) { tv_timelimit.tv_sec = self->timeLimit; } else { tv_timelimit.tv_sec = 10.0; } tv_timelimit.tv_usec = 0; tv_timelimitp = &tv_timelimit; rc = ldap_search_ext ( self->handle, (char *)[_base UTF8String], _scope, (char *)[filter UTF8String], attrs, 0, ctrls, NULL, tv_timelimitp, self->sizeLimit > 0 ? self->sizeLimit : 1000, &msgid); if (LDAP_SUCCESS != rc) { msgid = -1; [self errorWithFormat: @"[sssvlv 3] %@", [NSString stringWithUTF8String: ldap_err2string(rc)]]; } } else { msgid = -1; [self errorWithFormat: @"[sssvlv 2] %@", [NSString stringWithUTF8String: ldap_err2string(rc)]]; } free(ctrls); } else { msgid = -1; [self errorWithFormat: @"[sssvlv 1] %@", [NSString stringWithUTF8String: ldap_err2string(rc)]]; } free(keys[0]); free(keys); /* free attributes */ if (attrs != NULL) free(attrs); attrs = NULL; if (msgid == -1) { /* trouble */ int err; ldap_get_option(self->handle, LDAP_OPT_RESULT_CODE, &err); NSLog(@"Fatal LDAP error during ldap_search: %s", ldap_err2string(err)); return nil; } e = [[NGLdapSearchResultEnumerator alloc] initWithConnection:self messageID:msgid]; return [e autorelease]; } - (NSEnumerator *)_searchAtBaseDN:(NSString *)_base qualifier:(EOQualifier *)_q attributes:(NSArray *)_attributes scope:(int)_scope { NSString *filter; int msgid; char **attrs; NGLdapSearchResultEnumerator *e; if (self->handle == NULL) [self _reinit]; if ((filter = [_q ldapFilterString]) == nil) filter = @"(objectclass=*)"; if (_attributes != nil) { unsigned i, acount; acount = [_attributes count]; attrs = calloc(acount + 3, sizeof(char *)); for (i = 0; i < acount; i++) attrs[i] = (char *)[[_attributes objectAtIndex:i] UTF8String]; attrs[i] = NULL; } else attrs = NULL; if (LDAPDebugEnabled) { NSLog(@"%s: search at base '%@' filter '%@' for attrs '%@'\n", __PRETTY_FUNCTION__, _base, filter, [_attributes componentsJoinedByString: @","]); } /* apply limits */ if (self->sizeLimit > 0) ldap_set_option(self->handle, LDAP_OPT_SIZELIMIT, &(self->sizeLimit)); if (self->timeLimit > 0.0) { int tl = self->timeLimit; /* specified in seconds */ ldap_set_option(self->handle, LDAP_OPT_TIMELIMIT, &tl); } /* trigger search */ msgid = ldap_search(self->handle, (char *)[_base UTF8String], _scope, (char *)[filter UTF8String], attrs, 0); /* free attributes */ if (attrs != NULL) free(attrs); attrs = NULL; if (msgid == -1) { /* trouble */ int err; ldap_get_option(self->handle, LDAP_OPT_RESULT_CODE, &err); NSLog(@"Fatal LDAP error during ldap_search: %s", ldap_err2string(err)); return nil; } e = [[NGLdapSearchResultEnumerator alloc] initWithConnection:self messageID:msgid]; return [e autorelease]; } - (NSEnumerator *)flatSearchAtBaseDN: (NSString *)_base qualifier: (EOQualifier *)_q attributes: (NSArray *)_attributes sortAttribute: (NSString *)_sortAttribute sortReverse: (BOOL)_sortReverse { return [self _searchAtBaseDN:_base qualifier:_q attributes:_attributes scope:LDAP_SCOPE_ONELEVEL sortAttribute: _sortAttribute sortReverse: _sortReverse]; } - (NSEnumerator *)flatSearchAtBaseDN:(NSString *)_base qualifier:(EOQualifier *)_q attributes:(NSArray *)_attributes { return [self _searchAtBaseDN:_base qualifier:_q attributes:_attributes scope:LDAP_SCOPE_ONELEVEL]; } - (NSEnumerator *)deepSearchAtBaseDN:(NSString *)_base qualifier:(EOQualifier *)_q attributes:(NSArray *)_attributes sortAttribute:(NSString *)_sortAttribute sortReverse:(BOOL)_sortReverse { return [self _searchAtBaseDN:_base qualifier:_q attributes:_attributes scope:LDAP_SCOPE_SUBTREE sortAttribute: _sortAttribute sortReverse: _sortReverse]; } - (NSEnumerator *)deepSearchAtBaseDN:(NSString *)_base qualifier:(EOQualifier *)_q attributes:(NSArray *)_attributes { return [self _searchAtBaseDN:_base qualifier:_q attributes:_attributes scope:LDAP_SCOPE_SUBTREE]; } - (NSEnumerator *)baseSearchAtBaseDN:(NSString *)_base qualifier:(EOQualifier *)_q attributes:(NSArray *)_attributes sortAttribute:(NSString *)_sortAttribute sortReverse:(BOOL)_sortReverse { return [self _searchAtBaseDN:_base qualifier:_q attributes:_attributes scope:LDAP_SCOPE_BASE sortAttribute: _sortAttribute sortReverse: _sortReverse]; } - (NSEnumerator *)baseSearchAtBaseDN:(NSString *)_base qualifier:(EOQualifier *)_q attributes:(NSArray *)_attributes { return [self _searchAtBaseDN:_base qualifier:_q attributes:_attributes scope:LDAP_SCOPE_BASE]; } - (NGLdapEntry *)entryAtDN:(NSString *)_dn qualifier:(EOQualifier *)_q attributes:(NSArray *)_attrs { NSEnumerator *e; NGLdapEntry *entry; e = [self _searchAtBaseDN:_dn qualifier:_q attributes:_attrs scope:LDAP_SCOPE_BASE]; entry = [e nextObject]; if ([e nextObject] != nil) { [self logWithFormat:@"WARN: more than one search results in base search!"]; /* consume all entries */ while ([e nextObject] != nil) // TODO: can't we cancel the request? ; } return entry; } - (NGLdapEntry *)entryAtDN:(NSString *)_dn attributes:(NSArray *)_attrs { return [self entryAtDN:_dn qualifier:nil attributes:_attrs]; } /* cache */ - (void)setCacheTimeout:(NSTimeInterval)_to { if (self->cacheTimeout != _to) { self->cacheTimeout = _to; if (self->isCacheEnabled) { #if LDAP_API_VERSION > 2000 NSLog(@"WARNING(%s): setting cache-timeout unsupported on the client " @"library version!", __PRETTY_FUNCTION__); #else ldap_disable_cache(self->handle); ldap_enable_cache(self->handle, _to, [self cacheMaxMemoryUsage]); #endif } } } - (NSTimeInterval)cacheTimeout { return self->cacheTimeout; } - (void)setCacheMaxMemoryUsage:(long)_maxMem { if (self->cacheMaxMemory != _maxMem) { self->cacheMaxMemory = _maxMem; if (self->isCacheEnabled) { #if LDAP_API_VERSION > 2000 NSLog(@"WARNING(%s): setting maxmem usage unsupported on the client " @"library version!", __PRETTY_FUNCTION__); #else ldap_disable_cache(self->handle); ldap_enable_cache(self->handle, [self cacheTimeout], _maxMem); #endif } } } - (long)cacheMaxMemoryUsage { return self->cacheMaxMemory; } - (void)setUseCache:(BOOL)_flag { if (_flag) { #if LDAP_API_VERSION > 2000 NSLog(@"WARNING(%s): setting cache-usage unsupported on the client " @"library version!", __PRETTY_FUNCTION__); #else ldap_enable_cache(self->handle, [self cacheTimeout], [self cacheMaxMemoryUsage]); #endif self->isCacheEnabled = YES; } else { #if LDAP_API_VERSION > 2000 NSLog(@"WARNING(%s): setting cache-usage unsupported on the client " @"library version!", __PRETTY_FUNCTION__); #else ldap_disable_cache(self->handle); #endif self->isCacheEnabled = NO; } } - (BOOL)doesUseCache { return self->isCacheEnabled; } - (void)flushCache { #if !(LDAP_API_VERSION > 2000) ldap_flush_cache(self->handle); #endif } - (void)destroyCache { #if !(LDAP_API_VERSION > 2000) ldap_destroy_cache(self->handle); #endif self->isCacheEnabled = NO; } - (void)cacheForgetEntryWithDN:(NSString *)_dn { if (_dn == nil) return; #if !(LDAP_API_VERSION > 2000) ldap_uncache_entry(self->handle, (char *)[_dn UTF8String]); #endif } /* modifications */ - (BOOL)addEntry:(NGLdapEntry *)_entry { int msgid, res; LDAPMod **attrs; LDAPMessage *msg; LDAPMod *attrBuf; unsigned count; attrs = NULL; attrBuf = NULL; /* construct attributes */ { unsigned i; NSEnumerator *e; NGLdapAttribute *attribute; count = [_entry count]; attrBuf = calloc(count, sizeof(LDAPMod)); NSAssert(attrBuf, @"couldn't allocate attribute buffer"); attrs = calloc(count + 1, sizeof(LDAPMod *)); NSAssert(attrs, @"couldn't allocate attribute ptr buffer"); e = [[[_entry attributes] allValues] objectEnumerator]; for (i = 0; (attribute = [e nextObject]) && (i < count); i++) { unsigned valCount, j; struct berval **values; NSEnumerator *ve; NSData *v; char *attrName; NSString *key; key = [attribute attributeName]; valCount = [attribute count]; values = calloc(valCount + 1, sizeof(struct berval *)); ve = [attribute valueEnumerator]; for (j = 0; (v = [ve nextObject]) && (j < valCount); j++) { struct berval *bv; bv = malloc(sizeof(struct berval)); bv->bv_len = [v length]; bv->bv_val = (void *)[v bytes]; values[j] = bv; } values[valCount] = NULL; attrName = strdup([key UTF8String]); attrBuf[i].mod_op = LDAP_MOD_BVALUES; attrBuf[i].mod_type = attrName; attrBuf[i].mod_bvalues = values; attrs[i] = &(attrBuf[i]); } attrs[count] = NULL; } /* start operation */ msgid = ldap_add(self->handle, (char *)[[_entry dn] UTF8String], attrs); /* deconstruct attributes */ freeMods(attrs); attrs = NULL; attrBuf = NULL; /* check operation return value */ if (msgid == -1) { [[self _exceptionForErrorCode: 0 /* was in v1: ((LDAP *)self->handle)->ld_errno */ operation:@"add" userInfo:[NSDictionary dictionaryWithObject:_entry forKey:@"entry"]] raise]; return NO; } /* process result */ msg = NULL; res = ldap_result(self->handle, msgid, 0, NULL /* timeout */, &msg); if (res != LDAP_SUCCESS) { /* error */ int err; err = ldap_result2error(self->handle, msg, 1 /* free msg */); [[self _exceptionForErrorCode:err operation:@"add" userInfo:[NSDictionary dictionaryWithObject:_entry forKey:@"entry"]] raise]; return NO; } if (msg) ldap_msgfree(msg); return YES; } /* comparing */ - (BOOL)compareAttribute:(NSString *)_attr ofEntryWithDN:(NSString *)_dn withValue:(id)_value { int res; if (_dn == nil) return NO; res = ldap_compare_s(self->handle, (char *)[_dn UTF8String], (char *)[_attr UTF8String], (char *)[[_value stringValue] UTF8String]); if (res == LDAP_COMPARE_TRUE) return YES; if (res == LDAP_COMPARE_FALSE) return NO; [[self _exceptionForErrorCode:res operation:@"compare" userInfo:[NSDictionary dictionaryWithObject:_dn forKey:@"dn"]] raise]; return NO; } - (BOOL)removeEntryWithDN:(NSString *)_dn { int res; if (_dn == nil) return YES; res = ldap_delete_s(self->handle, (char *)[_dn UTF8String]); if (res == LDAP_SUCCESS) return YES; [[self _exceptionForErrorCode:res operation:@"delete" userInfo:[NSDictionary dictionaryWithObject:_dn forKey:@"dn"]] raise]; return NO; } - (BOOL)modifyEntryWithDN:(NSString *)_dn changes:(NSArray *)_mods { int res; LDAPMod **mods; LDAPMod *modBuf; unsigned i, count; if (_dn == nil) return NO; if ((count = [_mods count]) == 0) return YES; /* construct mods */ mods = calloc(count + 1, sizeof(LDAPMod *)); modBuf = calloc(count, sizeof(LDAPMod)); NSAssert(mods, @"couldn't allocate modification array"); NSAssert(modBuf, @"couldn't allocate modification buffer"); for (i = 0; i < count; i++) { NGLdapModification *mod; NGLdapAttribute *attr; NSString *attrName; unsigned valCount; NSEnumerator *e; NSData *value; struct berval **values; unsigned j; mod = [_mods objectAtIndex:i]; mods[i] = &(modBuf[i]); switch ([mod operation]) { case NGLdapAddAttribute: modBuf[i].mod_op = LDAP_MOD_ADD; break; case NGLdapDeleteAttribute: modBuf[i].mod_op = LDAP_MOD_DELETE; break; case NGLdapReplaceAttribute: modBuf[i].mod_op = LDAP_MOD_REPLACE; break; } modBuf[i].mod_op |= LDAP_MOD_BVALUES; attr = [mod attribute]; attrName = [attr attributeName]; /* TODO: use UTF-8, UNICODE */ modBuf[i].mod_type = strdup([attrName UTF8String]); valCount = [attr count]; values = calloc(valCount + 1, sizeof(struct berval *)); e = [attr valueEnumerator]; for (j = 0; (value = [e nextObject]) && (j < valCount); j++) { struct berval *bv; bv = malloc(sizeof(struct berval)); bv->bv_len = [value length]; bv->bv_val = (void *)[value bytes]; values[j] = bv; } values[valCount] = NULL; modBuf[i].mod_bvalues = values; } mods[count] = NULL; /* run modify */ res = ldap_modify_s(self->handle, (char *)[_dn UTF8String], mods); /* free structures */ freeMods(mods); mods = NULL; modBuf = NULL; /* check result */ if (res != LDAP_SUCCESS) { [[self _exceptionForErrorCode: res /* was in v1: ((LDAP *)self->handle)->ld_errno */ operation:@"modify" userInfo:[NSDictionary dictionaryWithObject:_dn forKey:@"dn"]] raise]; return NO; } return YES; } /* root DSE */ - (NGLdapEntry *)schemaEntry { NGLdapEntry *e; if ((e = [self entryAtDN:@"cn=schema" attributes:nil])) return e; return nil; } - (NGLdapEntry *)rootDSEWithAttributes: (NSArray *) attributes { NGLdapEntry *e; if ((e = [self entryAtDN:@"" attributes: attributes])) return e; return nil; } - (NGLdapEntry *)rootDSE { return [self rootDSEWithAttributes: nil]; } - (NGLdapEntry *)configEntry { NGLdapEntry *e; if ((e = [self entryAtDN:@"cn=config" attributes:nil])) return e; return nil; } - (NSArray *)namingContexts { NGLdapEntry *e; NSEnumerator *values; NSString *value; NSMutableArray *ma; if ((e = [self rootDSE])) { /* LDAP v3 */ return [[e attributeWithName:@"namingcontexts"] allStringValues]; } if ((e = [self configEntry]) == nil) return nil; /* OpenLDAP */ values = [[e attributeWithName:@"database"] stringValueEnumerator]; ma = [NSMutableArray arrayWithCapacity:4]; while ((value = [values nextObject])) { NSRange r; r = [value rangeOfString:@":"]; if (r.length == 0) /* couldn't parse value */ continue; value = [value substringFromIndex:(r.location + r.length)]; [ma addObject:value]; } return ma; } - (NSArray*) _supportedCapabilities { NGLdapEntry *e; NSArray *reqAttrs, *resAttrs; resAttrs = nil; reqAttrs = [NSArray arrayWithObject: @"supportedCapabilities"]; if ((e = [self rootDSEWithAttributes: reqAttrs])) { resAttrs = [[e attributeWithName:@"supportedCapabilities"] allStringValues]; } return resAttrs; } - (BOOL) isADCompatible { /* * Check that the LDAP server is Active Directory compatible (samba) * by checking if it supports LDAP_CAP_ACTIVE_DIRECTORY_OID in its supportedCapabilities * http://msdn.microsoft.com/en-us/library/cc223360.aspx */ BOOL rc; NSArray *caps; rc = NO; caps = [self _supportedCapabilities]; // LDAP_CAP_ACTIVE_DIRECTORY_OID = 1.2.840.113556.1.4.800 // LDAP_CAP_ACTIVE_DIRECTORY_LDAP_INTEG_OID = 1.2.840.113556.1.4.1791 if ([caps containsObject: @"1.2.840.113556.1.4.800"]) rc = YES; return rc; } /* description */ - (NSString *)description { NSMutableString *s; s = [NSMutableString stringWithCapacity:100]; [s appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])]; if ([self isBound]) [s appendString:@" bound"]; if ([self doesUseCache]) { [s appendFormat:@" cache[to=%.2fs,mem=%i]", [self cacheTimeout], (int)[self cacheMaxMemoryUsage]]; } [s appendString:@">"]; return s; } /* PlainPasswordCheck */ + (NSString *)uidAttributeName { static NSString *uidAttr = nil; if (uidAttr == nil) { // TODO: can't we do this in +initialize? (maybe not if setup later by OGo) NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; uidAttr = [[ud stringForKey:@"LDAPLoginAttributeName"] copy]; if (![uidAttr isNotEmpty]) uidAttr = @"uid"; } return uidAttr; } - (NSString *)dnForLogin:(NSString *)_login baseDN:(NSString *)_baseDN { NSString *filter; char *attrs[2]; LDAPMessage *result; LDAPMessage *entry; char *dn; BOOL didBind = NO; int matchCount; NSString *strDN; int ldap_search_result ; if (LDAPDebugEnabled) [self logWithFormat:@"dn for login '%@' on %@", _login, _baseDN]; if (self->handle == NULL) { if (![self _reinit]) { NSLog(@"%s: _reinit failed...:", __PRETTY_FUNCTION__); return nil; } } if (![self isBound]) { didBind = NO; NS_DURING { if (LDAPInitialBindSpecific) { // TODO: can't we just check whether the DN is set? if (LDAPDebugEnabled) { [self logWithFormat: @" attempt to do a simple, authenticated bind " @"(dn=%@,pwd=%s) ..", LDAPInitialBindDN, [LDAPInitialBindPW length] > 0 ? "yes":"no"]; } didBind = [self bindWithMethod:@"simple" binddn:LDAPInitialBindDN credentials:LDAPInitialBindPW]; } else { if (LDAPDebugEnabled) [self logWithFormat:@" attempt to do a simple, anonymous bind .."]; didBind = [self bindWithMethod:@"simple" binddn:@"" credentials:@""]; } } NS_HANDLER didBind = NO; NS_ENDHANDLER; if (!didBind) { /* couldn't bind */ if (LDAPDebugEnabled) [self logWithFormat:@" bind failed !"]; return nil; } didBind = YES; if (LDAPDebugEnabled) [self logWithFormat:@" bound."]; } filter = [NSString stringWithFormat:@"(%@=%@)", [[self class] uidAttributeName], _login]; if (LDAPDebugEnabled) [self logWithFormat:@" search: uid='%@': '%@'", _login, filter]; /* we only check the DN anyway .. */ attrs[0] = "objectclass"; attrs[1] = NULL; ldap_search_result = ldap_search_s(self->handle, (char *)[_baseDN UTF8String], LDAP_SCOPE_SUBTREE, (char *)[filter UTF8String], attrs, 1, &result) ; if ((ldap_search_result != LDAP_SUCCESS) && (ldap_search_result != LDAP_PARTIAL_RESULTS)) { /* search failed */ if (didBind) [self unbind]; if (LDAPDebugEnabled) [self logWithFormat:@" search failed"]; return nil; } /* If the entry count is not equal to one, either the UID was not unique or there was no match */ if (((matchCount = ldap_count_entries(self->handle, result))) != 1) { if (didBind) [self unbind]; if (LDAPDebugEnabled) [self logWithFormat:@" failed: %i matches", matchCount]; return nil; } /* get first entry */ if ((entry = ldap_first_entry(self->handle, result)) == NULL) { if (didBind) [self unbind]; if (LDAPDebugEnabled) [self logWithFormat:@" could not retrieve first entry !"]; return nil; } /* get DN of first entry */ if ((dn = ldap_get_dn(self->handle, entry)) == NULL) { /* could not get DN */ if (didBind) [self unbind]; if (LDAPDebugEnabled) [self logWithFormat:@" got no DN for entry !"]; return nil; } strDN = nil; NS_DURING { strDN = [[[NSString alloc] initWithUTF8String:dn] autorelease]; } NS_HANDLER { // Note: this is not NSLog because of GCC crashers with exception handlers fprintf(stderr, "Got exception %s while NSUTF8StringEncoding, " "use defaultCStringEncoding", [[localException description] UTF8String]); strDN = nil; } NS_ENDHANDLER; if (strDN == nil) { if (LDAPDebugEnabled) { [self logWithFormat: @"could not convert DN to UTF-8 string, try cString .."]; } strDN = [[[NSString alloc] initWithCString:dn] autorelease]; } if (dn != NULL) free(dn); dn = NULL; if (result != NULL) { ldap_msgfree(result); } [self unbind]; if (LDAPDebugEnabled) [self logWithFormat:@" return DN %@", strDN]; return strDN; } - (BOOL)checkPassword:(NSString *)_pwd ofLogin:(NSString *)_login atBaseDN:(NSString *)_baseDN { BOOL didBind; NSString *strDN; if (LDAPDebugEnabled) [self logWithFormat:@"check pwd of login '%@' on %@", _login, _baseDN]; if (![_pwd isNotEmpty]) { if (LDAPDebugEnabled) [self logWithFormat:@" no password provided."]; return NO; } if (self->handle == NULL) { if (![self _reinit]) { NSLog(@"%s: _reinit failed...:", __PRETTY_FUNCTION__); } } strDN = [self dnForLogin:_login baseDN:_baseDN]; if (![strDN isNotEmpty]) { if (LDAPDebugEnabled) { [self logWithFormat:@" missing dn for login %@ atBaseDN %@", _login, _baseDN]; } return NO; } if (LDAPDebugEnabled) { [self logWithFormat:@" attempting to bind login %@ DN: %@ %s!", _login, strDN, [_pwd isNotEmpty] ? "(with password) " : "(empty password) "]; } /* Now bind as the DN with the password supplied earlier... Successful bind means the password was correct, otherwise the password is invalid. */ didBind = NO; NS_DURING { /* Note: beware: do _not_ use empty passwords! (unauthenticated binds) */ didBind = [self bindWithMethod:@"simple" binddn:strDN credentials:_pwd]; } NS_HANDLER didBind = NO; NS_ENDHANDLER; if (!didBind) { /* invalid login or password */ if (LDAPDebugEnabled) [self logWithFormat:@" simple bind failed for DN: '%@'", strDN]; [self unbind]; return NO; } [self unbind]; if (LDAPDebugEnabled) [self logWithFormat:@" bound successfully !"]; return YES; } + (BOOL)checkPassword:(NSString *)_pwd ofLogin:(NSString *)_login atBaseDN:(NSString *)_baseDN onHost:(NSString *)_hostName port:(int)_port { NGLdapConnection *ldap; if (LDAPDebugEnabled) { NSLog(@"LDAP: check pwd of login '%@' on %@,%i,%@ ...", _login, _hostName, _port, _baseDN); } if (![_pwd isNotEmpty]) { if (LDAPDebugEnabled) [self logWithFormat:@" no password provided."]; return NO; } if ((ldap = [[self alloc] initWithHostName:_hostName port:_port]) == nil) { if (LDAPDebugEnabled) NSLog(@"LDAP: got no connection to %@,%i ...", _hostName, _port); return NO; } ldap = [ldap autorelease]; if (LDAPDebugEnabled) NSLog(@"LDAP: use connection: %@", ldap); return [ldap checkPassword:_pwd ofLogin:_login atBaseDN:_baseDN]; } @end /* NGLdapConnection */ SOPE/sope-ldap/NGLdap/NGLdapEntry.h0000644000000000000000000000313415004363604015615 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG Copyright (C) 2012 Inverse inc. This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGLdapEntry_H__ #define __NGLdapEntry_H__ #import @class NSString, NSDictionary, NSMutableDictionary, NSArray; @class NGLdapAttribute; @interface NGLdapEntry : NSObject < NSCopying > { NSString *dn; NSArray *attributes; } - (id)initWithDN:(NSString *)_dn attributes:(NSArray *)_attrs; /* distinguished name */ - (NSString *)dn; - (NSString *)rdn; /* relative dn */ /* class */ - (NSArray *)objectClasses; /* attributes */ - (NGLdapAttribute *)attributeWithName:(NSString *)_name; - (NGLdapAttribute *)attributeWithName:(NSString *)_name language:(NSString *)_language; - (NSArray *)attributeNames; - (NSDictionary *)attributes; - (unsigned)count; /* LDIF */ - (NSString *)ldif; - (NSMutableDictionary *) asDictionary; @end #endif /* __NGLdapEntry_H__ */ SOPE/sope-ldap/NGLdap/NGLdap.h0000644000000000000000000000233715004363604014577 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NGLdap_H__ #define __NGLdap_H__ #include #include #include #include #include #include #include #include #include #include #include #endif /* __NGLdap_H__ */ SOPE/sope-ldap/NGLdap/GNUmakefile.preamble0000644000000000000000000000370015004363604017154 0ustar rootroot# compiler flags SOPE_ROOT=../.. ADDITIONAL_INCLUDE_DIRS += \ -I.. \ -I../../sope-core/NGExtensions \ -I../../sope-core \ -I/usr/local/include ADDITIONAL_CPPFLAGS += -Wall -Wno-protocol # dependencies libNGLdap_LIBRARIES_DEPEND_UPON += \ -lNGExtensions -lEOControl \ $(BASE_LIBS) NGLdap_LIBRARIES_DEPEND_UPON += \ -framework NGExtensions -framework EOControl \ -framework DOM -framework SaxObjC # OpenLDAP library dependencies ifeq ($(reentrant),yes) ADDITIONAL_CPPFLAGS += -D_REENTRANT=1 libNGLdap_LIBRARIES_DEPEND_UPON += -lldap_r -llber -lpthread NGLdap_LIBRARIES_DEPEND_UPON += -lldap_r -llber -lpthread else libNGLdap_LIBRARIES_DEPEND_UPON += -lldap -llber NGLdap_LIBRARIES_DEPEND_UPON += -lldap -llber endif # SASL/SSL dependencies ifneq ($(FOUNDATION_LIB),nx) ifeq ($(sasl),yes) libNGLdap_LIBRARIES_DEPEND_UPON += -lsasl endif else # is NeXT/Apple Foundation # TODO: document whether Foundation includes required dependencies ADDITIONAL_LDFLAGS += -framework Foundation endif # library/framework search pathes DEP_DIRS = \ $(SOPE_ROOT)/sope-core/NGStreams \ $(SOPE_ROOT)/sope-core/NGExtensions \ $(SOPE_ROOT)/sope-core/EOControl \ $(SOPE_ROOT)/sope-xml/DOM \ $(SOPE_ROOT)/sope-xml/SaxObjC ifneq ($(frameworks),yes) ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),\ -L$(GNUSTEP_BUILD_DIR)/$(dir)/$(GNUSTEP_OBJ_DIR_NAME)) else ADDITIONAL_LIB_DIRS += \ $(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir)) endif ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64) SYSTEM_LIB_DIR += -L/usr/local/lib64 else SYSTEM_LIB_DIR += -L/usr/local/lib endif # Apple ifeq ($(FOUNDATION_LIB),apple) libNGLdap_PREBIND_ADDR="0xC1C00000" libNGLdap_LDFLAGS += -seg1addr $(libNGLdap_PREBIND_ADDR) NGLdap_LDFLAGS += -seg1addr $(libNGLdap_PREBIND_ADDR) endif # only required on 10.2 and before? #ifneq ($(FOUNDATION_LIB),apple) #ADDITIONAL_INCLUDE_DIRS += -I/usr/local/openldap/include #SYSTEM_LIB_DIR += -L/usr/local/openldap/lib #endif SOPE/sope-ldap/NGLdap/NSString+DN.h0000644000000000000000000000241415004363604015472 0ustar rootroot/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __NSString_DN_H__ #define __NSString_DN_H__ #import @class NSArray, NSDate; @interface NSString(DNSupport) + (NSString *)dnWithComponents:(NSArray *)_components; - (NSArray *)dnComponents; - (NSString *)stringByAppendingDNComponent:(NSString *)_component; - (NSString *)stringByDeletingLastDNComponent; - (NSString *)lastDNComponent; - (const char *)ldapRepresentation; - (NSDate *)ldapTimestamp; - (NSString *) escapedForLDAPDN; @end #endif /* __NSString_DN_H__ */ SOPE/sope-ldap/README-OSX.txt0000644000000000000000000000044115004363604014353 0ustar rootrootPlease refer to ../README-OSX.txt for compilation directives. Building Notes ============== Prerequisites: - sope-xml - sope-core Prebinding Notes (DEPRECATED, for reference only) ================================================= sope-core: 0xC1000000 - 0xC2FFFFFF 0xC1C00000 NGLdap